Події EventSource / Server-Sent через Nginx


78

На стороні сервера за допомогою Sinatra з streamблоком.

get '/stream', :provides => 'text/event-stream' do
  stream :keep_open do |out|
    connections << out
    out.callback { connections.delete(out) }
  end
end

На стороні клієнта:

var es = new EventSource('/stream');
es.onmessage = function(e) { $('#chat').append(e.data + "\n") };

Коли я використовую додаток безпосередньо, через http://localhost:9292/, все працює ідеально. З’єднання постійне, і всі повідомлення передаються всім клієнтам.

Однак, коли він проходить через Nginx, http://chat.devз'єднання розривається, і повторне підключення запускається щосекунди або близько того.

Налаштування Nginx мені здається нормальним:

upstream chat_dev_upstream {
  server 127.0.0.1:9292;
}

server {
  listen       80;
  server_name  chat.dev;

  location / {
    proxy_pass http://chat_dev_upstream;
    proxy_buffering off;
    proxy_cache off;
    proxy_set_header Host $host;
  }
}

Пробували keepalive 1024в upstreamрозділі, як і proxy_set_header Connection keep-alive;в location.

Нічого не допомагає :(

Жодні постійні зв’язки та повідомлення не передаються жодному клієнту.

Відповіді:


191

Ваша конфігурація Nginx правильна, ви просто пропустите кілька рядків.

Ось "магічне тріо", яке EventSourceпрацює за допомогою Nginx:

proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;

Розмістіть їх у locationрозділі, і це має спрацювати.

Можливо, вам також доведеться додати

proxy_buffering off;
proxy_cache off;

Це не офіційний спосіб зробити це.

Я закінчив із цим "спробами та помилками" + "гуглинням" :)


2
Працює так добре. Чоловіче, це було важко налагодити. Дуже дякую!
Кріс Кейс

2
Якщо сервер відповість заголовком "X-Accel-Buffering: no", це дуже допомагає! (див .: wiki.nginx.org/X-accel#X-Accel-Buffering )
Зробив

15
Це не спрацювало у мене, поки я також не додав наступне: - proxy_buffering off; proxy_cache вимкнено;
Малкольм Спаркс,

4
Ваші спроби та помилки + моє перше звернення до Google = Я люблю переповнення стека. Дякую!
Chris Ray

2
Ви щойно зробили ОФІЦІЙНИЙ ШЛЯХ, чудова робота! nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive
Weihang Jian


9

Не пишіть це з нуля самі. Nginx - чудовий парний сервер і має модулі, які оброблятимуть SSE для вас без будь-якого погіршення продуктивності вашого сервера вище.

Перевірте https://github.com/wandenberg/nginx-push-stream-module

Принцип роботи - абонент (браузер, що використовує SSE), підключається до Nginx, і зв’язок там припиняється. Видавець (ваш сервер, який стоїть за Nginx) надішле POST до Nginx за відповідним маршрутом, і в цей момент Nginx негайно перенаправить очікуваному слухачеві EventSource у браузері.

Цей метод набагато масштабніший, ніж використання веб-сервера ruby ​​для обробки цих "довгоописуваних" з'єднань SSE.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.