69 votes

EventSource / Événements envoyés par le serveur via Nginx

Du côté du serveur, en utilisant Sinatra avec un fichier de type stream bloc.

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

Du côté client :

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

Lorsque j'utilise l'application directement, via http://localhost:9292/ tout fonctionne parfaitement. La connexion est persistante et tous les messages sont transmis à tous les clients.

Cependant, quand il passe par Nginx, http://chat.dev la connexion est interrompue et une reconnexion a lieu toutes les secondes environ.

La configuration de Nginx me semble correcte :

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;
  }
}

Essayé keepalive 1024 en upstream ainsi que proxy_set_header Connection keep-alive; en location .

Rien n'y fait :(

Aucune connexion persistante et aucun message n'est transmis aux clients.

229voto

Votre configuration Nginx est correcte, il vous manque juste quelques lignes.

Voici un "trio magique" qui fait EventSource à travers Nginx :

proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;

Placez-les dans location et cela devrait fonctionner.

Vous devrez peut-être aussi ajouter

proxy_buffering off;
proxy_cache off;

Ce n'est pas une façon officielle de faire.

J'ai fini par trouver ceci par "essais et erreurs" + "google" :)

23voto

E1. Points 13

Une autre option consiste à inclure dans votre réponse un en-tête "X-Accel-Buffering" avec la valeur "no". Nginx le traite de manière spéciale, voir http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering

11voto

Martin Konecny Points 7328

Ne l'écrivez pas vous-même à partir de zéro. Nginx est un merveilleux serveur événementiel et possède des modules qui géreront l'ESS pour vous sans aucune dégradation des performances de votre serveur en amont.

Vérifiez https://github.com/wandenberg/nginx-push-stream-module

La façon dont cela fonctionne est que l'abonné (navigateur utilisant SSE) se connecte à Nginx, et la connexion s'arrête là. L'éditeur (votre serveur derrière Nginx) enverra un POST à Nginx à une route correspondante et à ce moment, Nginx transmettra immédiatement à l'écouteur EventSource en attente dans le navigateur.

Cette méthode est beaucoup plus évolutive que celle qui consiste à laisser votre serveur Web ruby gérer ces connexions SSE "à long sondage".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X