在代理上启用 SSL 后,服务器发送的事件停止工作



我做了一个网络项目,基于他面前的Tomcat和Nginx。
必须努力工作才能使其正常工作而没有错误。
但是,当我将 ssl 添加到 nginx 时。已停止工作服务器发送的事件。
如果我直接访问后端服务器 - 它可以工作,所以在nginx的某个地方出现问题。
有人有这样的问题吗?
这是配置
的相对部分

我的

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

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

nginx的错误日志中没有错误条目。但是在 acess 日志中也提到了/SecurConfig/api/tutorial/listen 的 acess。代码 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;哇64;rv:34.0) 壁虎/20100101火狐/34.0"

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

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


UPD


好。当我在互联网上搜索信息时,我打开了SSE的页面。10分钟后,我看到,我的数据看起来很真实。我根据缓冲评论了所有设置
    #proxy_buffering on;
    #proxy_buffer_size 8k;
    #proxy_cache off;

我还评论了参数

     #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 事件之前逐个显示。
还是你的帮助,解释,我错了。


UPD


这是我的服务器配置,当我"关闭"ssl 和 SSE 工作时。
SSL 已关闭 - SSE 工作正常
80 端口重定向到 443 SSL -
SSE 不起作用

为了使 SSE 正常工作,您必须确保没有缓存或缓冲任何内容:不在脚本中(例如,在 PHP 中我们有@ob_flush();@flush()习语),不在 Web 服务器上,也不在任何中间代理或防火墙中。

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

proxy_buffering off;
proxy_buffer_size 0;
proxy_cache off;

我还会考虑明确设置高超时,而不是将它们注释掉。"高"的定义取决于您的应用程序。例如,如果它总是每隔几秒钟发送一次数据,则默认值会很好。但是,如果您将 SSE 用于不规则数据,并且消息之间有时可能有半小时,请确保超时超过半小时。

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

更新:这是我在OP收集更多信息之前的答案(特别是如果他等待足够长的时间,数据就会到达,即这是一个缓冲问题:请参阅我的另一个答案)。我决定把它留在这里,因为它可能对其他人有用的故障排除想法。(但如果您不同意,请留下评论或标志以进行删除。


在规划"使用HTML5 SSE的数据推送应用程序"时,不幸的是,使用代理服务器是我们划清界限的另一面;如果你读过第9章,你就会知道一个看似简单的标准仍然会变得非常复杂。所以,我很想听听你是否以及如何让它工作。

首先想到的是您使用自签名 SSL 证书。它们不会与 SSE 和 Chrome 配合使用。阿贾克斯也不会。(请参阅错误报告,但它是在 2011 年开放的,所以不要屏住呼吸。但是您说它适用于Firefox,因此不太可能是这样。

下一个想法是你正在使用Access-Control-Allow-Origin:*Access-Control-Allow-Credentials:true,所以我认为这意味着你需要CORS(即你的html页面来源和你的SSE脚本来源在某些方面是不同的),并且涉及cookie。 您是否在 JavaScript 中将{ withCredentials: true }设置为EventSource构造函数的第二个参数?即使这样,请注意Access-Control-Allow-Credentials:true不适用于Access-Control-Allow-Origin:*。您不能指定*,而是必须明确说明允许的原点。

如果这是问题所在,则可以使用服务器端脚本根据客户端的来源动态创建标头。(本书展示了在PHP中执行此操作的代码。如果nginx可以使用用户请求中的环境变量,那么您也可以在那里执行此操作。

但是,我的理解是,这也会被http绊倒。我认为这不应该只是一个https问题。(如果我错了,请告诉我。

(哦,如果你的工作 http SSE 请求来自 http://example.com,并且仍然来自 http://example.com,即使 SSE 请求现在要 https://example.com,那么一切都是有意义的 - 你之前没有遇到 CORS 失败,因为来源是相同的;现在你确实有一个 CORS 问题,你没有正确处理它。

我的第三个猜测是浏览器正在发送预检选项请求,但仅使用 https 请求执行此操作。(预检请求从一个浏览器到另一个浏览器,但当前版本的 Chrome 和 Firefox 的行为方式相同并非不可能。当您收到 OPTIONS 请求时,您需要发回 Access-Control-Allow-Headers: Last-Event-ID, Origin, X-Requested-With, Content-Type, Accept, Authorization 。您还需要发回Access-Control-Allow-Origin:*标头。

您可以通过数据包嗅探来确认或反驳这第三个猜测,以查看来回发送的确切内容。如果上述所有想法都一无所获,无论如何你都应该这样做。

简而言之,nginx检测与后端应用程序的连接是否处于活动状态,并且在SSL的情况下检测可能无法正常工作,如此处所述

http://mailman.nginx.org/pipermail/nginx/2013-March/038120.html

最新更新