在代理上启用 ssl 后,服务器发送的事件停止工作 [英] Server sent events stopped work after enabling ssl on proxy

查看:51
本文介绍了在代理上启用 ssl 后,服务器发送的事件停止工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在他面前制作了基于 Tomcat 和 Nginx 的 Web 项目.
必须努力工作才能使其正常工作.
但是,当我将 ssl 添加到 nginx 时.停止工作的服务器发送事件.
如果我直接访问后端服务器 - 它可以工作,那么 nginx 的某个地方就会出现问题.
有人遇到这样的问题吗?
这是配置的相关部分

我的 nginx.conf(我还没有使用启用站点的功能,并将我的应用程序也配置在这里.基本设置在 conf 末尾)./SecurConfig/api/tutorial/listen - 是事件源

user www-data;worker_processes 4;pid/run/nginx.pid;事件{worker_connections 768;# multi_accept on;}http {根/数据/;服务器{听80;# server_name ajaxdemo.in.ua;# proxy_set_header 主机 ajaxdemo.in.ua;地点/{重写 ^(.*)$ https://ajaxdemo.in.ua$1 永久;}}服务器 {#听80;听 443 默认 ssl;#ssl开启;ssl_certificate/etc/nginx/ssl/server.crt;ssl_certificate_key/etc/nginx/ssl/server.key;proxy_set_header 主机 $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;地点/{根/数据/www;add_header 'Access-Control-Allow-Origin' *;add_header 'Access-Control-Allow-Credentials' 'true';add_header 'Access-Control-Allow-Methods' 'GET';if ($http_cookie ~* "jsessionid=([^;]+)(?:;|$)") {设置 $co "jsessionid=$1";}#proxy_set_header Cookie "$co";proxy_pass http://127.0.0.1:1666/SecurConfig/;#proxy_pass http://88.81.229.142:1666/SecurConfig/;add_before_body/header.html;add_after_body/footer.html;}位置/SecurConfig/api/tutorial/listen {add_header 'Access-Control-Allow-Origin' *;add_header 'Access-Control-Allow-Credentials' 'true';add_header 'Access-Control-Allow-Methods' 'GET';##服务器发送事件集proxy_set_header 连接'';proxy_http_version 1.1;chunked_transfer_encoding off;proxy_connect_timeout 300;proxy_send_timeout 300;proxy_read_timeout 300;proxy_buffering 开启;proxy_buffer_size 8k;#proxy_cache 关闭;##if ($http_cookie ~* "jsessionid=([^;]+)(?:;|$)") {设置 $co "jsessionid=$1";}#proxy_set_header Cookie "$co";proxy_pass http://127.0.0.1:1666/;#proxy_pass http://88.81.229.142:1666/;}位置/SecurConfig/{根/数据/www;add_header 'Access-Control-Allow-Origin' *;add_header 'Access-Control-Allow-Credentials' 'true';add_header 'Access-Control-Allow-Methods' 'GET';if ($http_cookie ~* "jsessionid=([^;]+)(?:;|$)") {设置 $co "jsessionid=$1";}#proxy_set_header Cookie "$co";proxy_pass http://127.0.0.1:1666/;#proxy_pass http://88.81.229.142:1666/;add_before_body/header.html;add_after_body/footer.html;}位置 ~ \.css$ {根/数据/css/;}位置/header.html {根/数据/www;}位置/footer.html {根/数据/www;}位置 ~ \.(gif|jpg|png|jpeg)$ {根/数据/图像;}}### 基本设置##发送文件;tcp_nopush 开启;tcp_nodelay 开启;keepalive_timeout 65;types_hash_max_size 2048;client_max_body_size 100m;包括/etc/nginx/mime.types;default_type 应用程序/八位字节流;### 日志设置##access_log/var/log/nginx/access.log;error_log/var/log/nginx/error.log;### Gzip 设置##gzip 上;gzip_disable "msie6";### 虚拟主机配置##包括/etc/nginx/conf.d/*.conf;# 包含/etc/nginx/sites-enabled/*;}

nginx 的错误日志中没有错误条目.但是在访问日志中也提到了对/SecurConfig/api/tutorial/listen 的访问.代码 200 表示一切正常"

<块引用>

"GET/SecurConfig/api/tutorial/listen HTTP/1.1" 200 187 "https://ajaxdemo.in.ua/SecurConfig/api/tutorial/map/11111111" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0"

Tomcat 日志像往常一样显示对/SecurConfig/api/tutorial/listen 的访问(例如检查安全访问,接受它,然后重新发送到控制器).
如果我在 chrome 开发者模式下运行我的页面,我会看到这个错误

GET https://ajaxdemo.in.ua/SecurConfig/api/tutorial/listen net::ERR_EMPTY_RESPONSE


更新


好的.当我在互联网上搜索信息时,我离开了我的页面,并打开了 SSE.10 分钟后,我看到我的数据显示为它必须的样子.我根据缓冲评论了所有设置

<块引用>

 #proxy_buffering on;#proxy_buffer_size 8k;#proxy_cache 关闭;

我也评论了参数

<块引用>

 #proxy_connect_timeout 300;#proxy_send_timeout 300;#proxy_read_timeout 300;

所以这个参数返回了它的默认值(大约 20 秒)我所有的数据都在大约 20 秒后出现.所以我设置了

<块引用>

 proxy_connect_timeout 2;proxy_send_timeout 2;proxy_read_timeout 2;

而且数据出现得更快.但它还是一件(一次3-4个事件),在启用ssl事件之前一一显示.
仍然需要你的帮助和解释,我错在哪里.


更新


这是我的服务器的配置,当我关闭"ssl 并且 SSE 工作时.
ssl 已关闭 - sse 有效
80 端口重定向到 443 ssl - sse 不起作用

解决方案

要使 SSE 正常工作,您必须确保没有缓存或缓冲任何内容:不在您的脚本中(例如,在 PHP 中,我们有 @ob_flush();@flush() 习惯用法),而不是在您的网络服务器上,也不是在任何中间代理或防火墙上.

你说你注释掉了所有与缓冲有关的 nginx 命令,但注释掉意味着它将使用默认值.例如.proxy_buffering 的默认值是 on.我建议明确指定它们以确保关闭所有缓冲和缓存.

proxy_buffering off;proxy_buffer_size 0;proxy_cache 关闭;

我也会考虑明确地将超时设置为高,而不是将它们注释掉.高"的定义取决于您的应用.例如.如果它总是每隔几秒发送一次数据,默认值就可以了.但如果您使用 SSE 处理不规则数据,并且消息之间有时可能会有半小时,请确保超时时间超过半小时.

更新:显然(见评论)添加 response.addHeader("X-Accel-Buffering", "no");(即到服务器端过程,而不是代理配置)解决了这个问题.这是有道理的,因为它是专门为 SSE 和类似的 HTTP 流添加的,请参阅 nginx 文档.它确实意味着上述 Nginx 配置也应该有效(OP 报告说它没有).但是,另一方面,无论如何,使用标头在每个连接的基础上禁用缓冲感觉都是更好的解决方案.

I made web project, that based on Tomcat and Nginx in front of him.
Had to work hard to make it work without errors.
However, when I added ssl to nginx. Stopped working server sent events.
If i acess to backend server directly - it works, so problem somewhere whith nginx.
Have someone with such a problem?
Here is relative parts of configuration

My nginx.conf (im not using sites-enabled yet, and placed my app configured here too. Basic settings at the end of conf). /SecurConfig/api/tutorial/listen - is source of events

user www-data;
worker_processes 4;
pid /run/nginx.pid;

events {
worker_connections 768;
# multi_accept on;
}

http {

root /data/;

server{
listen 80;
#   server_name ajaxdemo.in.ua;
#   proxy_set_header Host ajaxdemo.in.ua;
location / {
rewrite ^(.*)$ https://ajaxdemo.in.ua$1 permanent;
}
}

server {
#listen 80;
listen 443 default ssl;

#ssl on;
    ssl_certificate /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key; 



  proxy_set_header  Host               $host;
  proxy_set_header  X-Real-IP          $remote_addr;
  proxy_set_header  X-Forwarded-For    $proxy_add_x_forwarded_for;
  proxy_set_header            X-Forwarded-Proto $scheme;

location / {
    root /data/www;

    add_header 'Access-Control-Allow-Origin' *;
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Methods' 'GET';

    if ($http_cookie ~* "jsessionid=([^;]+)(?:;|$)") {
        set $co "jsessionid=$1";
        }
    #proxy_set_header Cookie "$co";

    proxy_pass http://127.0.0.1:1666/SecurConfig/;
    #proxy_pass http://88.81.229.142:1666/SecurConfig/;
    add_before_body /header.html;
    add_after_body /footer.html;
}


location /SecurConfig/api/tutorial/listen {

    add_header 'Access-Control-Allow-Origin' *;
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Methods' 'GET';

    ##Server sent events set
    proxy_set_header Connection '';
    proxy_http_version 1.1;
    chunked_transfer_encoding off;

    proxy_connect_timeout 300;
   proxy_send_timeout 300;
   proxy_read_timeout 300;

    proxy_buffering on;
    proxy_buffer_size 8k;
    #proxy_cache off;
    ##


    if ($http_cookie ~* "jsessionid=([^;]+)(?:;|$)") {
        set $co "jsessionid=$1";
        }
    #proxy_set_header Cookie "$co";
    proxy_pass http://127.0.0.1:1666/;
    #proxy_pass http://88.81.229.142:1666/;

}


location /SecurConfig/ {
    root /data/www;

    add_header 'Access-Control-Allow-Origin' *;
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Methods' 'GET';

    if ($http_cookie ~* "jsessionid=([^;]+)(?:;|$)") {
        set $co "jsessionid=$1";
        }
    #proxy_set_header Cookie "$co";

    proxy_pass http://127.0.0.1:1666/;
    #proxy_pass http://88.81.229.142:1666/;
    add_before_body /header.html;
    add_after_body /footer.html;
}

location ~ \.css$ {
root /data/css/;
}

location /header.html {
root  /data/www;
}
location /footer.html {
root  /data/www;
}

location ~ \.(gif|jpg|png|jpeg)$ {
    root /data/images;
}

}


##
# Basic Settings
##

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size 100m;

include /etc/nginx/mime.types;
default_type application/octet-stream;

##
# Logging Settings
##

access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

##
# Gzip Settings
##

gzip on;
gzip_disable "msie6";


##
# Virtual Host Configs
##

include /etc/nginx/conf.d/*.conf;
#   include /etc/nginx/sites-enabled/*;
}

There are no error entries in error logs of nginx. But there is also mention about acess to /SecurConfig/api/tutorial/listen in acess logs. Code 200 means "all is ok"

"GET /SecurConfig/api/tutorial/listen HTTP/1.1" 200 187 "https://ajaxdemo.in.ua/SecurConfig/api/tutorial/map/11111111" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0"

Tomcat log shows acess to /SecurConfig/api/tutorial/listen as usual(e.g. checks security acess, accepts it, and resends to controller).
If i run my page in chrome developer mode, i see this error

GET https://ajaxdemo.in.ua/SecurConfig/api/tutorial/listen net::ERR_EMPTY_RESPONSE


UPD


Okay. While i searched info on internet, i left my page with SSE opened. And after 10 minutes, i saw, that my data appeared just as it must be. I commented all settings according to buffering

    #proxy_buffering on;
    #proxy_buffer_size 8k;
    #proxy_cache off;

And i commented also parameters

     #proxy_connect_timeout 300;
    #proxy_send_timeout 300;
    #proxy_read_timeout 300;

So this parameters returned top its default (about 20 sec) And all my data appeared after ~20 sec. So i setted

  proxy_connect_timeout 2;
    proxy_send_timeout 2;
    proxy_read_timeout 2;

And data appeared faster. But its.s still in one piece(3-4 events at once), before enabling ssl events showed one by one.
Still ned your help, and explanation, where i was wrong.


UPD


Here is conhiguration from my server, when i "turn off" ssl and SSE works.
ssl is off - sse works
80 port redirecting to 443 ssl - sse not works

解决方案

For SSE to work properly, you must make sure nothing is getting cached or buffered: not in your script (e.g. in PHP we have the @ob_flush();@flush() idiom), not at your web server, and not at any intermediate proxies or firewalls.

You say you commented out all the nginx commands to do with buffering, but commenting out means it will use the defaults. E.g. the default for proxy_buffering is on. I would suggest explictly specifying them to make sure all buffering and caching is switched off.

proxy_buffering off;
proxy_buffer_size 0;
proxy_cache off;

I would also consider explicitly setting the timeouts high, rather than commenting them out. The definition of "high" depends on your application. E.g. if it is always sending data every couple of seconds, the defaults will be fine. But if you are using SSE for irregular data, and there might sometimes be half an hour between messages, make sure the timeouts are more than half an hour.

UPDATE: Apparently (see the comments) adding response.addHeader("X-Accel-Buffering", "no"); (i.e. to the server-side process, not to the proxy config) fixes the problem. This makes sense, as that was added specifically for SSE and similar HTTP streaming, see the nginx documentation. It does imply the above Nginx configuration should also work (the OP has reported that it does not). But, on the other hand, using a header to disable buffering on a per-connection basis feels like a better solution anyway.

这篇关于在代理上启用 ssl 后,服务器发送的事件停止工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆