nginx 作为 NodeJS+socket.io 的代理:除了大消息外一切正常

Posted

技术标签:

【中文标题】nginx 作为 NodeJS+socket.io 的代理:除了大消息外一切正常【英文标题】:nginx as a proxy for NodeJS+socket.io: everything is OK except for big messages 【发布时间】:2013-05-08 18:28:42 【问题描述】:

正如nginx's website 中解释的那样,我已将这些设置用于我的 nginx 以将 websockets 代理到 NodeJS 服务器:

location /socket.io/ 
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

一切正常,socket.emit() / socket.on() 互相发送消息;直到我发送了一条相当大的短信(26 kB 的 html)。

NodeJS 没有收到这条大消息(所以我猜是 nginx 方面的问题) nginx 日志没有错误 一旦客户端发送了这条大消息,NodeJS 将停止从该客户端接收 socket.io 的心跳。

我做错了什么? 是否有我不知道的 nginx 设置?

【问题讨论】:

你用的是什么版本的nginx? 我使用的是 nginx/1.4.0 我在使用你的配置时遇到了这个问题:Uncaught TypeError: Cannot call method 'onClose' of null 【参考方案1】:

找到的“解决方案”是使用haproxy在nginx和NodeJS之间拆分tcp流。

这不是最优的,因为它在我们的堆栈中添加了另一个程序,但它完成了工作。

在我看来,nginx websocket 支持距离生产就绪还很远。

【讨论】:

【参考方案2】:

尝试在您的配置中添加这些:

proxy_buffers 8 2m;
proxy_buffer_size 10m;
proxy_busy_buffers_size 10m;

原因:proxy_buffer 默认大小为 4K 或 8K。因此,在大消息导致缓冲区溢出后,它可能会丢弃这些连接。检查默认设置here,使其符合您的要求。

【讨论】:

相反,我会用proxy_buffering off 关闭代理缓冲。 Comet 不适用于 nginx 缓冲,我怀疑 WebSockets 也会有同样的问题。你会认为 nginx 会自动禁用缓冲,或者至少在需要时将其置于默认配置中,但我猜有足够多的人使用更大的缓冲区。如果你要走缓冲路线,你还应该添加类似large_client_header_buffers 8 32k; 的东西。有关示例配置,请参阅 this gist。

以上是关于nginx 作为 NodeJS+socket.io 的代理:除了大消息外一切正常的主要内容,如果未能解决你的问题,请参考以下文章

Socket.io 不适用于 nginx

使用 Socket.IO 的 NGINX 配置

当远程但不是本地时,Socket.io 退回到 nginx 代理后面的轮询(websocket 给出 400)

nginx 和 socket.io 解决方法

NodeJS、Express 和多事的 Socket.io

用于生产的 Nodejs 网络服务器