Conexão de longa duração
Eventos enviados pelo servidor (SSE) são uma conexão HTTP de execução longa **, portanto, para iniciantes, precisamos do seguinte:
proxy_http_version 1.1;
proxy_set_header Connection "";
NOTA: As conexões TCP no HTTP / 1.1 são persistentes por padrão, portanto, definir o cabeçalho de conexão como vazio faz a coisa certa e é a sugestão do Nginx.
Codificação de transferência em pedaços
Agora um aparte; As respostas SSE não definem um cabeçalho de comprimento de conteúdo porque não podem saber quantos dados serão enviados; eles precisam usar o cabeçalho de codificação de transferência [0] [1], o que permite uma conexão de streaming. Observe também: se você não adicionar um Comprimento de conteúdo, a maioria dos servidores HTTP definirá Transfer-Encoding: chunked;
para você. Estranhamente, o chunking HTTP alertou e causa confusão.
A confusão decorre de um aviso um tanto vago na seção Notas da descrição W3 EventSource:
Os autores também são alertados que o HTTP chunking pode ter efeitos negativos inesperados na confiabilidade deste protocolo. Sempre que possível, o chunking deve ser desativado para veicular fluxos de eventos, a menos que a taxa de mensagens seja alta o suficiente para que isso não importe.
O que levaria a acreditar que Transfer-Encoding: chunked;
é uma coisa ruim para a SSE. No entanto: esse não é necessariamente o caso, é apenas um problema quando seu servidor da web faz o trabalho por você (sem saber informações sobre seus dados). Portanto, embora a maioria das postagens sugira que chunked_transfer_encoding off;
isso não seja necessário no caso típico [3].
Buffer (o verdadeiro problema)
A origem da maioria dos problemas é ter qualquer tipo de buffer entre o servidor de aplicativos e o cliente. Por padrão [4], o Nginx usa
proxy_buffering on
(também dê uma olhada uwsgi_buffering
e fastcgi_buffering
dependendo do seu aplicativo) e pode optar por armazenar em buffer os pedaços que você deseja enviar ao seu cliente. Isso é ruim porque a natureza em tempo real do SSE é interrompida.
No entanto, em vez de procurar proxy_buffering off
por tudo, é realmente melhor (se você puder) adicionar o X-Accel-Buffering: no
cabeçalho como resposta no código do servidor de aplicativos para desativar o buffer apenas para a resposta baseada em SSE e não para todas as respostas provenientes do seu aplicativo servidor. Bônus: isso também funcionará para uwsgi
e fastcgi
.
Solução
E, portanto, as configurações realmente importantes são, na verdade, os cabeçalhos de resposta do servidor de aplicativos:
Content-Type: text/event-stream;
Cache-Control: no-cache;
X-Accel-Buffering: no;
E potencialmente a implementação de algum mecanismo de ping para que a conexão não fique ociosa por muito tempo. O perigo disso é que o Nginx fechará as conexões inativas conforme definido usando a keepalive
configuração.
[0] https://tools.ietf.org/html/rfc2616#section-3.6
[1] https://en.wikipedia.org/wiki/Chunked_transfer_encoding
[2] https://www.w3.org/TR / 2009 / WD-eventsource-20091029 / # text-event-stream
[3] https://github.com/whatwg/html/issues/515
[4] http://nginx.org/en/docs/http/ ngx_http_proxy_module.html # proxy_buffering
[5] https://tools.ietf.org/html/rfc7230#section-6.3
[6] https://gist.github.com/CMCDragonkai/6bfade6431e9ffb7fe88
X-Accel-Buffering: no
cabeçalho foi a chave para mim, mas o mais importante foi que o @ c4urself escreveu: "adicione o X-Accel-Buffering: no como um cabeçalho de resposta no código do servidor de aplicativos ". A adição desse cabeçalho a uma seção de localização em minha configuração do nginx não funcionou - todo o fluxo de eventos aguardou o envio até depois que o aplicativo foi concluído / finalizado.proxy_http_version 1.1;
necessário? Estou tentando executar mais de 6 fluxos SSE de um navegador e, portanto, preciso de HTTP2.