Untuk Server-Sent Events (SSE) konfigurasi Nginx apa yang sesuai?


20

Saya telah membaca banyak pertanyaan berbeda tentang konfigurasi Nginx yang sesuai untuk SSE dan menghasilkan beberapa hasil membingungkan mengenai pengaturan apa yang harus digunakan:

Jadi apa jawaban yang benar?

Jawaban:


45

Koneksi berjalan lama

Server-Sent Events (SSE) adalah koneksi HTTP yang sudah berjalan lama **, jadi untuk permulaan kita membutuhkan ini:

proxy_http_version 1.1;
proxy_set_header Connection "";

CATATAN: Koneksi TCP dalam HTTP / 1.1 persisten secara default, jadi mengatur header Koneksi untuk mengosongkan melakukan hal yang benar dan merupakan saran Nginx.

Transfer-Pengkodean Terpotong

Di samping itu; Respons SSE tidak menetapkan header Panjang Konten karena mereka tidak tahu berapa banyak data akan dikirim, sebaliknya mereka perlu menggunakan header Transfer-Pengkodean [0] [1], yang memungkinkan koneksi streaming. Perhatikan juga: jika Anda tidak menambahkan Panjang Konten, sebagian besar server HTTP akan mengaturnya Transfer-Encoding: chunked;untuk Anda. Anehnya, HTTP chunking memperingatkan dan menyebabkan kebingungan.

Kebingungan berasal dari peringatan yang agak kabur di bagian Catatan dari deskripsi W3 EventSource:

Penulis juga diperingatkan bahwa chunking HTTP dapat memiliki efek negatif yang tidak terduga pada keandalan protokol ini. Jika memungkinkan, chunking harus dinonaktifkan untuk melayani aliran acara kecuali jika laju pesannya cukup tinggi sehingga hal ini tidak menjadi masalah.

Yang akan membuat orang percaya Transfer-Encoding: chunked;adalah hal buruk bagi SSE. Namun: ini belum tentu demikian, itu hanya masalah ketika server web Anda melakukan chunking untuk Anda (tidak mengetahui informasi tentang data Anda). Jadi, sementara sebagian besar posting akan menyarankan menambahkan chunked_transfer_encoding off;ini tidak perlu dalam kasus khas [3].

Buffering (masalah sebenarnya)

Di mana sebagian besar masalah berasal adalah memiliki segala jenis buffering antara server aplikasi dan klien. Secara default [4], Nginx menggunakan proxy_buffering on(juga melihat uwsgi_bufferingdan fastcgi_bufferingtergantung pada aplikasi Anda) dan dapat memilih untuk buffer potongan yang ingin Anda sampaikan kepada klien Anda. Ini adalah hal yang buruk karena sifat SSE yang realtime pecah.

Namun, alih-alih beralih proxy_buffering offuntuk semuanya, lebih baik (jika Anda bisa) menambahkan X-Accel-Buffering: nosebagai header respons dalam kode server aplikasi Anda untuk hanya mematikan buffering untuk respons berbasis SSE dan tidak untuk semua respons yang datang dari aplikasi Anda server. Bonus: ini juga akan bekerja untuk uwsgidan fastcgi.

Larutan

Dan pengaturan yang sangat penting sebenarnya adalah header respons aplikasi-server:

Content-Type: text/event-stream;
Cache-Control: no-cache;
X-Accel-Buffering: no;

Dan berpotensi penerapan beberapa mekanisme ping sehingga koneksi tidak tinggal diam terlalu lama. Bahaya dari ini adalah bahwa Nginx akan menutup koneksi idle sebagaimana diatur menggunakan keepalivepengaturan.


[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


Bisakah Anda menguraikan apa mekanisme ping itu? Apakah itu hanya mendorong pesan kosong ke saluran? Saya telah mengatur header level aplikasi dan nginx tetapi saya masih mendapatkan timeout 504 dari nginx untuk setiap titik akhir sumber-acara.
wgwz

ping hanya berupa data (palsu) yang dikirim pada suatu interval melalui koneksi, pada klien Anda dapat menangani ping ini dan mengabaikannya. CATATAN: jika koneksi Anda tidak berfungsi sama sekali, ping tidak akan membantu, ada hal lain yang salah.
c4urself

2
Saya menambahkan header respons seperti yang disarankan dan berfungsi. Saya tidak membuat perubahan pada konfigurasi nginx v1.12 dan sejauh ini tidak ada masalah.
Mikkel

1
Menambahkan X-Accel-Buffering: noheader adalah kunci bagi saya, tetapi yang penting, saya harus melakukan seperti yang ditulis oleh @ c4urself: "tambahkan X-Accel-Buffering: tidak sebagai header respons dalam kode server aplikasi Anda ". Menambahkan header ini ke bagian lokasi di konfigurasi nginx saya tidak berfungsi - seluruh aliran acara menunggu untuk dikirim sampai setelah aplikasi selesai / dihentikan.
MDMower

Apakah proxy_http_version 1.1; perlu? Saya mencoba menjalankan lebih dari 6 SSE stream dari browser dan karenanya saya perlu HTTP2.
Bilal Fazlani
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.