Подтвердить что ты не робот

События EventSource/Server-Sent через Nginx

На стороне сервера с использованием 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.

Ничего не помогает: (

Нет постоянных соединений и сообщений, которые не передаются никаким клиентам.

4b9b3361

Ответ 1

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

Вот "волшебное трио", создающее EventSource, работающее через Nginx:

proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;

Поместите их в раздел location, и он должен работать.

Вам также может потребоваться добавить

proxy_buffering off;
proxy_cache off;

Это не официальный способ сделать это.

Я закончил это с помощью "проб и ошибок" + "googling":)

Ответ 3

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

Отъезд https://github.com/wandenberg/nginx-push-stream-module

Как это работает, абонент (браузер с использованием SSE) подключается к Nginx, и соединение останавливается там. Издатель (ваш сервер за Nginx) отправит POST на Nginx по соответствующему маршруту, и в этот момент Nginx немедленно перейдет в ожидающий прослушиватель EventSource в браузере.

Этот метод гораздо более масштабируемый, чем ваш рубиновый веб-сервер, обрабатывающий эти "длинные опросы" SSE-соединений.