2013-07-25 4 views
3

Реализация серверных событий на первый взгляд является довольно простой задачей. Заимствуя примеры в документации Mozilla на стороне клиентского кода будет вдоль линийОтправленные сервером события, код на стороне сервера

var evtSource = new EventSource("ssedemo.php"); 
evtSource.onmessage = function(e){//do stuff with e.data here} 

Что мне трудно понять, что происходит на стороне сервера. То, что головоломка, мне

  • Итак, вы хотите, чтобы посылать события из ssdemo.php означает, что вам нужно, чтобы запустить его в петлю и дайте ему спать, когда он не посылает
  • Но по умолчанию Apache является установкой для уничтожения сценариев, которые занимают слишком много времени, чтобы выполнить это, так что это не может быть бесконечным циклом, если вы не настроите этот сценарий таким образом
  • Если у меня есть 10 пользователей, которые приходят с запросом одной и той же службы SSE (ssdemo.php), это значит, что у меня было бы 10 экземпляров этого зацикленного скрипта?

Я подозреваю, что мое понимание того, как работает код на стороне сервера, должно быть закодировано либо испорчено, либо наивно, либо и то, и другое. Я был бы очень признателен за любые указатели на правильный способ сделать это.

ответ

1

Ваше понимание неверное. PHP нужно продолжать работать, а в PHP вам понадобится цикл, и вы быстро исчерпаете бесплатные потоки Apache.

Если вам нужно обрабатывать множество соединений, вам необходимо использовать сервер на основе событий, такой как Node.js или Tornado, который может обрабатывать множество открытых соединений.

Если вы предпочитаете использовать PHP, то частным решением является закрытие соединения через несколько секунд. Браузер снова подключится, поэтому вы получите гибрид опроса и SSE.

В PHP вы можете проверить sys_getloadavg(), чтобы решить, можно ли открывать соединение или работать на свободных процессах.

0

Я искал, чтобы ответить на такой же вопросы, когда дело доходит до SSE, вот мое исследование:

У меня есть основной javax HttpServlet, который будет печатать данные в PrintWriter каждые Rando секунд.

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { 
    System.out.println("You just entered the doGetMethod"); 
    response.setContentType("text/event-stream"); 
    response.setCharacterEncoding("UTF-8"); 
    PrintWriter printWriter = null; 
    while(true){ 
    try{ 
     System.out.println("You just entered the while loop"); 
     double randomNumber = Math.random()*10000; 
     printWriter = response.getWriter(); 
     printWriter.print("data: " + "[next server time check event in " + 
     Math.round(randomNumber/1000) + " seconds]\n"); 
     printWriter.print("data: " + "Time: " + Calendar.getInstance().getTime() + "\n\n"); 
     response.flushBuffer(); 
     Thread.sleep((long)randomNumber); 

    } catch (IOException | InterruptedException e){ 
     e.printStackTrace(); 
     break; 
    } 
    } 
    System.out.println("Connection was aborted"); 
} 

и вот скрипт, который заполняет {текстовой идентификатор = "displayTextArea} элемент

<script> 
    var eventSource = null; 
    function start(){ 
    eventSource = new EventSource('http://localhost:8080/SSEServlet'); 
    eventSource.onopen = function(){displayTextArea.value+='Connected ..' + '\n';}; 
    eventSource.onmessage = function(message){displayTextArea.value+=message.data + '\n\n';}; 
    eventSource.onerror = function(){displayTextArea.value+='Error Occurred...' + '\n';}; 
    } 
    function stop(){ 
    eventSource.close(); 
    } 
    function clearText(){ 
    displayTextArea.value = ''; 
    } 
</script> 

- Чтобы ответить на ваш первый вопрос:
Если вы смотрите консоль при запуске приложение, вы заметите, что консоль не печатает «Вы только что ввели doGetMethod» до тех пор, пока вы не отправите HTTP-запрос GET в путь сервлета. Это подтверждает понимание того, что экземпляр Servlet и объекты req/resp не создаются, пока кто-то не вызовет сервлет. How do servlets work?
- Второй и третий вопрос:
Tomcat по умолчанию назначит один поток для каждого соединения (Source). В моей текущей конфигурации моя программа будет максимальной в 6 соединениях. Каждое соединение создаст свой собственный экземпляр сервлета, и пока соединение открыто, оно останется в цикле while. Это было доказано, когда я запускал сервер и открывал отдельные соединения, видя разные времена и последовательность случайных интервалов.Мой цикл while не бесконечен, хотя он ждет, пока соединение не будет закрыто, а затем генерирует исключение и прерывает цикл while. После закрытия соединения сервлет закроется.

Способ, которым я это сделал, очень любительский способ выполнения SSE. Если вы хотите изучить передовые библиотеки для этого я хотел бы проверить jeaSSE

Если кто-то хочет полностью code

Смежные вопросы