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

时间:2015-01-12 09:19:29

标签: ssl nginx server-sent-events

我制作了一个基于Tomcat和Nginx的web项目。
不得不努力工作,没有错误 但是,当我将ssl添加到nginx时。停止工作的服务器发送事件 如果我直接进入后端服务器 - 它可以工作,所以在nginx的某个地方出现问题 有人有这样的问题吗? 这是配置的相对部分

我的nginx.conf(我还没有使用网站启用,并且我的应用也配置在这里。在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的错误日志中没有错误条目。 但是还提到了在访问日志中访问/ 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 developer模式下运行我的页面,我会看到此错误

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 is off - sse works
80 port redirecting to 443 ssl - sse not works

3 个答案:

答案 0 :(得分:7)

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

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

proxy_buffering off;
proxy_buffer_size 0;
proxy_cache off;

我还会考虑明确设置超时,而不是评论它们。 " high"的定义取决于您的申请。例如。如果它总是每隔几秒发送一次数据,那么默认值就可以了。但是,如果您使用SSE处理不规则数据,并且消息之间有时可能会有半小时,请确保超时时间超过半小时。

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

答案 1 :(得分:2)

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


在规划“使用HTML5 SSE的数据推送应用程序”时,遗憾的是使用代理服务器是我们绘制线路的另一面;如果你已经阅读了第9章,你就会知道一个看似简单的标准仍然会变得非常复杂。所以,我很想知道你是否以及如何使用它。

首先想到的是您使用的是自签名SSL证书。它们不适用于使用Chrome的SSE。 Ajax也不会。 (见the bug report,但它在2011年开放,所以不要屏住呼吸。)但是你说它适用于Firefox,所以这不太可能。

下一个想法是你正在使用Access-Control-Allow-Origin:*Access-Control-Allow-Credentials:true,所以我认为这意味着你需要为CORS(即你的html页面起源和你的SSE脚本起源在某些方面有所不同),并且涉及到cookie。您是否将{ withCredentials: true }设置为JavaScript中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问题,而你没有正确处理它。)

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

您可以通过数据包嗅探来确认或反驳此第三个猜测,以查看究竟是来回发送的内容。如果以上所有想法都没有出现,那么无论如何都应该这样做。

答案 2 :(得分:0)

简单地说,nginx检测连接是否与后端应用程序一起存活,并且在SSL情况下检测可能无法正常工作,如此处所述

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