我正在尝试从Apache2到NGINX并遇到问题上交所连接。其他一切都运行良好,常规 GET 或 POST 请求均成功通过。请注意,相同的设置在 Apache2 WEB 服务器上运行良好。
但是 SSE 与 NGINX 服务器的连接存在两个关键问题:
- NGINX 会保留响应,直到缓冲区已满
- 如果 SSE 正在进行,NGINX 将阻止对服务器的任何其他请求。
使用 Apache2 时我曾经遇到过问题 #1,但通过以下配置可以轻松解决:
OutputBufferSize 0
问题 #2 确实阻碍了我使用 NGINX。为什么 SSE 进行时服务器会阻止其他连接?如何解决此问题?
这restconf应用程序是一个 HTTP/REST 瘦客户端应用程序,由 WEB 服务器中的 FastCGI 模块调用,为指定的用户或 SSE 流启动单个请求会话。
client <-> WEB server <-> restconf <-> subsystem netconf server
我发现无论我的配置设置如何,NGINX 都会继续缓冲我的 SEE 输出。我尝试使用以下方法:
- 环境fastcgi_buffering 关闭在站点配置位置;
- 环境fastcgi_request_buffering 关闭在站点配置位置;
- 将标头设置为X-Accel-Buffering:无在我的 restconf 应用程序和客户端请求中。
什么都没用。奇怪的是缓冲设置根本不起作用。无论配置如何,缓冲区的大小都保持不变:
- fastcgi_buffer_size 是4k;
- fastcgi_buffers 4 4k;
- fastcgi_busy_buffers_大小:8k;
当我更改上述设置时,实际程序运行中没有任何变化。整个事件流等待在 NGINX 中发送,无论是应用程序完成/终止后还是缓冲区已满(如果缓冲区的大小始终相同,则上述设置不会改变其大小)
nginx -V
nginx version: nginx/1.18.0 (Ubuntu)
built with OpenSSL 1.1.1f 31 Mar 2020 (running with OpenSSL 1.1.1g 21 Apr 2020)
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-5J5hor/nginx-1.18.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC'
--prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf
--http-log-path=/var/log/nginx/access.log
--error-log-path=/var/log/nginx/error.log
--lock-path=/var/lock/nginx.lock
--pid-path=/run/nginx.pid
--modules-path=/usr/lib/nginx/modules
--http-client-body-temp-path=/var/lib/nginx/body
--http-fastcgi-temp-path=/var/lib/nginx/fastcgi
--http-proxy-temp-path=/var/lib/nginx/proxy
--http-scgi-temp-path=/var/lib/nginx/scgi
--http-uwsgi-temp-path=/var/lib/nginx/uwsgi
--with-debug
--with-compat
--with-pcre-jit
--with-http_ssl_module
--with-http_stub_status_module
--with-http_realip_module
--with-http_auth_request_module
--with-http_v2_module
--with-http_dav_module
--with-http_slice_module
--with-threads
--with-http_addition_module
--with-http_gunzip_module
--with-http_gzip_static_module
--with-http_image_filter_module=dynamic
--with-http_sub_module
--with-http_xslt_module=dynamic
--with-stream=dynamic
--with-stream_ssl_module
--with-mail=dynamic
--with-mail_ssl_module
NGINX 服务器配置:
server {
listen 80;
listen [::]:80;
root /var/www/yang-api;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name localhost;
# need to install fcgiwrap to use RESTCONF
# set SCRIPT_FILENAME to the location of the restconf program
location /restconf {
fastcgi_param SCRIPT_NAME restconf;
fastcgi_param SCRIPT_FILENAME /var/www/yang-api/restconf;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
include /etc/nginx/fastcgi_params;
allow all;
# HAS EFFECT
## This is the maximum time limit for request handling.
## If a FastCGI request does not complete within this timeout
## seconds, it will be subject to termination.
## Set to big number if SSE used
fastcgi_read_timeout 120s;
# NO EFFECT
fastcgi_buffering off;
fastcgi_request_buffering off;
}
}
答案1
这里的问题是 fcgiwrap 进程,它一直保留缓冲区,直到应用程序终止或缓冲区已满。我通过在 /location 中添加以下几行解决了这个问题:
### When set (e.g., to ""), disables output fastcgiwrap buffering.
### MUST be set if SEE used
fastcgi_param NO_BUFFERING "";
### When buffering is disabled, the response is passed to a
### client synchronously, immediately as it is received.
### Nginx will not try to read the whole response from the
### FastCGI server.
### MUST be set if SEE used
fastcgi_buffering off;
第二个问题也是由于 fcgiwrap 造成的。正如这里讨论的那样https://stackoverflow.com/a/66099376/5555750
我必须破解 /etc/init.d/fcgiwrap 并更改 DAEMON_OPTS 变量并强制脚本停止,然后在输入时使用新参数重新启动服务:
sudo /etc/init.d/fcgiwrap 重新加载
这将重新加载 fcgiwrap,以便它可以同时处理多个请求。