Серверные отправленные события (SSE) на Sinatra и Thin постоянно отключаются и повторно подключаются

Я сделал небольшое приложение Sinatra для отслеживания некоторых данных нашей компании в более или менее реальном времени.

Настройка очень похожа на dashing.io/:

  • Задания Rufus Scheduler используются для запроса базы данных через определенный интервал.
  • Результат запроса возвращается в поток соединения SSE.
  • Клиенты подписываются на поток (определенный в javascript в представлениях erb) и отображают данные разными способами, например используя highcharts.

Все это работает хорошо, однако я заметил, что если я позволю выполнению задания реже, чем каждую минуту, клиент будет постоянно отключаться и повторно подключаться. Позволь мне объяснить:

Код javascript подписки выглядит так:

<script type="text/javascript">

var source       = new EventSource('/stream/channels-energy');

source.onopen    = function(event) { 
    console.log("Connection opened", event) 
}

source.onerror   = function(event) {
    console.log("Connection error", event) 
}

source.onmessage = function(event) { 
    var data_energy = JSON.parse(event.data);
    console.log("Time: " + event.lastEventId + "Length: " + Object.keys(data_energy).length);
}

</script>

Если я позволю заданию запускаться каждые 30 секунд, все будет работать отлично. Взгляд в консоль в Chrome (или Firefox) показывает следующее:

Connection opened Event
Time: 2016-03-13T13:33:39.625ZLength: 2854
Time: 2016-03-13T13:34:09.656ZLength: 2854
Time: 2016-03-13T13:34:39.698ZLength: 2854
Time: 2016-03-13T13:35:09.395ZLength: 2854
Time: 2016-03-13T13:35:39.493ZLength: 2854
Time: 2016-03-13T13:36:09.592ZLength: 2854
Time: 2016-03-13T13:36:39.674ZLength: 2854

Однако, если я настрою интервал задания на 3 минуты, консоль покажет, что клиент постоянно отключается:

Connection opened Event
Time: 2016-03-13T13:00:16.018ZLength: 2909
Connection error Event
Connection opened Event
Connection error Event
Connection opened Event
Connection error Event
Connection opened Event
Time: 2016-03-13T13:03:15.912ZLength: 2891
Connection error Event
Connection opened Event
Connection error Event
Connection opened Event
Connection error Event
Connection opened Event
Time: 2016-03-13T13:06:15.857ZLength: 2891
Connection error Event
Connection opened Event
Connection error Event
Connection opened Event
Connection error Event
Connection opened Event
...

Кажется, что клиент по-прежнему может получать данные при вводе, поэтому конечный результат от этого не страдает. Мой вопрос: нормальное ли это постоянное отключение / повторное подключение? Разве клиенту не следует просто поддерживать соединение открытым, независимо от того, как часто данные передаются в потоковом режиме?


person Marcus Henningsen    schedule 13.03.2016    source источник
comment
Хотя сервер-отправленные-события также сокращенно SSE, тег SSE относится к другому SSE.   -  person harold    schedule 13.03.2016


Ответы (1)


Да, клиент (браузер) будет держать сокет открытым независимо от отправленных данных.

Вероятно, это связано с тем, что ваш внутренний сервер закрывает сокет, когда он переходит в тишину. Однако это также может быть ваш локальный интернет-провайдер, закрывающий сокет. Возможно, вы сможете определить, что это такое, проверив его из другого физического места.

Однако хорошее решение, которое хорошо покрывает любую причину, - это добавить сигнал keep-alive (также известный как сердцебиение). Он отправляется с сервера клиенту примерно каждые N секунд, например. N = 50.

Для отключений на сетевом уровне достаточно отправить комментарий SSE. Но что мне нравится делать, так это посылать правильное сообщение. Это позволяет клиенту отслеживать, когда он в последний раз слышал от сервера, и инициировать собственное отключение и повторное подключение, если он подозревает, что что-то пошло не так, т.е. если данные не поступили в течение N + 10 секунд. (Это редко, но иногда случается.)

person Darren Cook    schedule 14.03.2016
comment
Отлично, спасибо за ваш ответ, приятно знать, что это ожидаемое поведение и как с этим бороться. Я нашел несколько ресурсов по SSE и сигналам пульса, так что на днях я реализую что-нибудь простое. - person Marcus Henningsen; 14.03.2016