Development Tip

서버에서 보낸 이벤트와 PHP-서버에서 이벤트를 트리거하는 것은 무엇입니까?

yourdevel 2020. 10. 10. 12:07
반응형

서버에서 보낸 이벤트와 PHP-서버에서 이벤트를 트리거하는 것은 무엇입니까?


모두,

HTML5 Rocks에는 SSE (Server-sent Events)에 대한 멋진 초보자 자습서가 있습니다.

http://www.html5rocks.com/en/tutorials/eventsource/basics/

그러나 중요한 개념을 이해하지 못합니다. 서버에서 메시지를 보내는 이벤트를 트리거하는 것은 무엇입니까?

즉, HTML5 예제에서 서버는 타임 스탬프를 한 번만 보냅니다 .

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache'); // recommended to prevent caching of event data.
function sendMsg($id, $msg) {
  echo "id: $id" . PHP_EOL;
  echo "data: $msg" . PHP_EOL;
  echo PHP_EOL;
  ob_flush();
  flush();
}
$serverTime = time();
sendMsg($serverTime, 'server time: ' . date("h:i:s", time()));

예를 들어 페이스 북 스타일의 "벽"이나 주식 시세표와 같은 실용적인 예를 만들고 있다면, 서버가 데이터의 일부가 변경 될 때마다 새로운 메시지를 클라이언트에 "푸시"하는 방법은 어떻게 작동합니까?

다시 말해 ... PHP 스크립트에는 데이터의 변경 사항을 확인한 다음 찾을 때마다 메시지를 보내는 루프가 지속적으로 실행됩니까? 그렇다면 해당 프로세스를 언제 끝낼 지 어떻게 알 수 있습니까?

아니면-PHP 스크립트가 단순히 메시지를 보낸 다음 종료합니까 (HTML5Rocks 예제의 경우처럼)? 그렇다면-어떻게 지속적인 업데이트를 받습니까? 브라우저가 단순히 정기적으로 PHP 페이지를 폴링합니까? 그렇다면 어떻게 "서버에서 보낸 이벤트"입니까? AJAX를 사용하여 정기적으로 PHP 페이지를 호출하는 JavaScript에서 setInterval 함수를 작성하는 것과 어떻게 다릅니 까?

죄송합니다. 이것은 아마도 믿을 수 없을 정도로 순진한 질문 일 것입니다. 그러나 내가 찾은 예 중 어느 것도 이것을 명확하게하지 않습니다.

[최신 정보]

내 질문이 제대로 표현되지 않은 것 같아 여기에 몇 가지 설명이 있습니다.

Apple 주식의 가장 최근 가격을 표시해야하는 웹 페이지가 있다고 가정 해 보겠습니다.

사용자가 페이지를 처음 열면 페이지는 내 "스트림"의 URL을 사용하여 EventSource를 만듭니다.

var source = new EventSource('stream.php');

내 질문은 이것이다- "stream.php"는 어떻게 작동해야합니까?

이렇게? (의사 코드) :

<?php
    header('Content-Type: text/event-stream');
    header('Cache-Control: no-cache'); // recommended to prevent caching of event data.
    function sendMsg($msg) {
        echo "data: $msg" . PHP_EOL;
        echo PHP_EOL;
        flush();
    }

    while (some condition) {
        // check whether Apple's stock price has changed
        // e.g., by querying a database, or calling a web service
        // if it HAS changed, sendMsg with new price to client
        // otherwise, do nothing (until next loop)
        sleep (n) // wait n seconds until checking again
    }
?>

즉, "stream.php"는 클라이언트가 "연결"되어있는 한 계속 열려 있습니까?

그렇다면 stream.php동시 사용자 수만큼 스레드가 실행 되고 있음을 의미 합니까? 그렇다면-원격으로 실행 가능합니까, 아니면 애플리케이션을 구축하는 적절한 방법입니까? 그리고 인스턴스를 언제 끝낼 수 있는지 어떻게 알 수 stream.php있습니까?

내 순진한 인상은이 경우 PHP 이러한 종류의 서버에 적합한 기술 이 아니라는 것입니다. 그러나 내가 지금까지 본 모든 데모는 PHP가 이것에 적합하다는 것을 암시합니다.


서버 전송 이벤트는 서버 측에서 클라이언트 측으로의 실시간 업데이트를위한 것입니다. 첫 번째 예에서는 서버로부터의 연결이 유지되지 않고 클라이언트가 3 초마다 다시 연결을 시도하고 서버에서 보낸 이벤트를 ajax 폴링에 차이가 없도록합니다.

따라서 연결이 지속되도록하려면 코드를 루프로 래핑하고 지속적으로 업데이트를 확인해야합니다.

PHP는 스레드 기반이며 연결된 사용자가 많을수록 서버의 리소스가 부족해집니다. 이 문제는 스크립트 실행 시간을 제어하여 해결할 수 있으며 시간 (예 : 10 분)을 초과하면 스크립트를 종료 할 수 있습니다. EventSource지연이 허용 가능한 범위에 있도록 API가 자동으로 다시 연결한다.

또한 내 PHP 라이브러리에서 서버 전송 이벤트를 확인하면 PHP에서 서버 전송 이벤트 를 수행하는 방법에 대해 더 많이 이해하고 코딩을 더 쉽게 할 수 있습니다.


"..."stream.php "는 클라이언트가"연결 "되어있는 한 계속 열려 있습니까?"

예, 의사 코드는 합리적인 접근 방식입니다.

"그리고 stream.php의 인스턴스를 언제 끝낼 수 있는지 어떻게 알 수 있습니까?"

가장 일반적인 경우 이는 사용자가 사이트를 떠날 때 발생합니다. (Apache는 닫힌 소켓을 인식하고 PHP 인스턴스를 종료합니다.) 서버 측에서 소켓을 닫을 수있는 주된 시간은 잠시 동안 데이터가 없음을 알고있는 경우입니다. 클라이언트에게 보내는 마지막 메시지는 특정 시간에 다시 오라고 말하는 것입니다. 예를 들어 주식 스트리밍의 경우 오후 8시에 연결을 종료하고 고객에게 8 시간 후에 다시 오라고 말할 수 있습니다 (나스닥이 오전 4 시부 터 오후 8 시까 지 견적을 위해 열려 있다고 가정). 금요일 저녁 당신은 그들에게 월요일 아침에 돌아 오라고 말한다. (SSE에 대한 책이 있으며이 주제에 대해 몇 가지 섹션을 제공합니다.)

"...이 경우 PHP는 이런 종류의 서버에 적합한 기술이 아닙니다.하지만 지금까지 본 모든 데모는 PHP가 이것에 적합하다는 것을 암시합니다. 이것이 제가 그렇게하는 이유입니다. 혼란스러워 ... "

글쎄요, 사람들은 PHP가 일반 웹 사이트에 적합한 기술이 아니라고 주장하며 옳습니다. 전체 LAMP 스택을 C ++로 교체하면 훨씬 적은 메모리와 CPU 주기로 수행 할 수 있습니다. 그러나 이것에도 불구하고 PHP는 대부분의 사이트에 잘 작동합니다. 친숙한 C와 유사한 구문과 많은 라이브러리의 조합으로 인해 웹 작업에 매우 생산적인 언어이며, 고용 할 PHP 프로그래머, 많은 책 및 기타 리소스, 그리고 일부 큰 사용 사례 (예 : Facebook 및 Wikipedia). 이는 기본적으로 스트리밍 기술로 PHP를 선택할 수있는 동일한 이유입니다.

일반적인 설정은 PHP 인스턴스 당 NASDAQ에 대한 하나의 연결이 아닙니다. 대신 NASDAQ에 대한 단일 연결 또는 클러스터의 각 머신에서 NASDAQ에 대한 단일 연결이있는 다른 프로세스를 갖게됩니다. 그런 다음 가격을 SQL / NoSQL 서버 또는 공유 메모리로 푸시합니다. 그런 다음 PHP는 해당 공유 메모리 (또는 데이터베이스)를 폴링하고 데이터를 푸시합니다. 또는 데이터 수집 서버가 있고 각 PHP 인스턴스가 해당 서버에 대한 소켓 연결을 엽니 다. 데이터 수집 서버는 업데이트를 수신 할 때 각 PHP 클라이언트에 업데이트를 푸시하고 해당 데이터를 클라이언트에 푸시합니다.

스트리밍에 Apache + PHP를 사용할 때 발생하는 주요 확장 성 문제는 각 Apache 프로세스의 메모리입니다. 하드웨어의 메모리 한계에 도달하면 클러스터에 다른 시스템을 추가하거나 Apache를 루프에서 제거하고 전용 HTTP 서버를 작성하기로 비즈니스 결정을 내립니다. 후자는 PHP로 수행 할 수 있으므로 기존의 모든 지식과 코드를 재사용하거나 전체 애플리케이션을 다른 언어로 다시 작성할 수 있습니다. 저의 순수한 개발자는 전용의 간소화 된 HTTP 서버를 C ++로 작성했습니다. 내 매니저는 다른 상자를 추가 할 것입니다.


나는 sse techink가 모든 지연 데이터를 클라이언트에 전송한다는 것을 알았습니다.

<?php
        session_start();
        header('Content-Type: text/event-stream');
        header('Cache-Control: no-cache'); // recommended to prevent caching of event data
        require 'sse.php';
        if ($_POST['message'] != ""){
                $_SESSION['message'] = $_POST['message'];
                $_SESSION['serverTime'] = time();
        }
        sendMsg($_SESSION['serverTime'], $_SESSION['message'] );
?>

sse.php는 다음과 같습니다.

<?php
function sendMsg($id, $msg) {
  echo "id: $id" . PHP_EOL;
  echo "data: $msg" . PHP_EOL;
  echo PHP_EOL;
  ob_flush();
  flush();
}
?>

Notice that at the sseSerer.php i start a session and using a session variable! to overcome the problem.

Also i call the sseServer.php via Ajax (posting and set value to variable message) every time that i want to "update" message.

Now at the jQuery (javascript) i do something like that : 1st) i declare a global variable var timeStamp=0; 2nd) i use the next algorithm :

if(typeof(EventSource)!=="undefined"){
        var source=new EventSource("sseServer.php");
        source.onmessage=function(event)
        if ((timeStamp!=event.lastEventId) && (timeStamp!=0)){
                /* this is initialization */
                timeStamp=event.lastEventId;
                $.notify("Please refresh "+event.data, "info");
        } else {
                if (timeStamp==0){
                         timeStamp=event.lastEventId;
                }
        } /* fi */

} else {
        document.getElementById("result").innerHTML="Sorry, your browser does not support server-sent events...";
} /* fi */

At the line of : $.notify("Please refresh "+event.data, "info"); is there that you can handle the message.

For my case i used to send an jQuery notify.

You may use POSIX PIPES or a DB Table instead to pass the "message" via POST since the sseServer.php does something like an "infinite loop".

My problem at the time is that the above code DOES NOT SENDS THE "message" to all clients but only to the pair (client that called the sseServer.php works as individual to every pair) so i'll change the technik and to a DB update from the page that i want to trigger the "message" and then the sseServer.php instead to get the message via POST it will get it from DB table.

I hope that i have help!


This is really a structural question about your application. Real-time events are something that you want to think about from the beginning, so you can design your application around it. If you have written an application that just runs a bunch of random mysql(i)_query methods using string queries and doesn't pass them through any sort of intermediary, then many times you won't have a choice but to either rewrite much of your application, or do constant server-side polling.

If, however, you manage your entities as objects and pass them through some sort of intermediary class, you can hook into that process. Look at this example:

<?php
class MyQueryManager {
    public function find($myObject, $objectId) {
        // Issue a select query against the database to get this object
    }

    public function save($myObject) {
        // Issue a query that saves the object to the database
        // Fire a new "save" event for the type of object passed to this method
    }

    public function delete($myObject) {
        // Fire a "delete" event for the type of object
    }
}

In your application, when you're ready to save:

<?php
$someObject = $queryManager->find("MyObjectName", 1);
$someObject->setDateTimeUpdated(time());
$queryManager->save($someObject);

This is not the most graceful example but it should serve as a decent building block. You can hook into your actual persistence layer to handle triggering these events. Then you get them immediately (as real-time as it can get) without hammering your server (since you have no need to constantly query your database and see if things changed).

You obviously won't catch manual changes to the database this way - but if you're doing anything manually to your database with any frequency, you should either:

  • Fix the problem that requires you to have to make a manual change
  • Build a tool to expedite the process, and fire these events

Basically, PHP is not suitable techonology for this sort of things. Yes you can make it work, but it will be a disaster on highload. We run stockservers that send stock-change signals via websockets to dozens thousends users - and If we'd use php for that... Well, we could, but those homemade cycles - is just a nightmare. Every single connection will make a separate process on server or you have to handle connections from some sort of database.

Simply use nodejs and socket.io. It will let you easily start and have a running server in couple days. Nodejs has own limitations also, but for websockets (and SSE) connections now its the most powerfull technology.

And also - SSE is not that good as it seems. The only advantage to websockets - is that packets are being gzipped natively (ws is not gzipped), but on the downside is that SSE is one-side connection. You user, if he wants to add another stock symbol to subscripton, will have to make ajax request (including all troubles with origin control and the request will be slow). In websockets client and sever communicate both ways in one single opened connection, so if user sends a trading signal or subscribes to quote, he just send a string in already opened connection. And it's fast.

참고URL : https://stackoverflow.com/questions/14564903/server-sent-events-and-php-what-triggers-events-on-the-server

반응형