将NGINX和NGINX Plus与Node.js、Socket.IO及WebSocket API结合使用

NGINX | 2014年11月19日

本文将介绍如何将NGINX和NGINX Plus与Node.js及Socket.IO结合使用。我们此前发布的关于使用WebSocket和NGINX构建实时Web应用的文章广受欢迎,因此本文将继续介绍Socket.IO的相关文档和最佳实践。

为什么将NGINX与Node.js和Socket.IO结合使用?

随着Node.js应用的兴起,Socket.IO作为一种WebSocket API已得到广泛应用。该API因能够简化在线游戏或聊天等实时应用的构建而广为人知。NGINX 1.3.13及更高版本以及所有NGINX Plus版本均支持代理WebSocket连接,因此可以使用Socket.IO。WebSocket协议支持通过单个TCP连接进行全双工(即双向)通信。

在生产环境中运行的应用通常需要使用端口 80(HTTP)、端口 443(HTTPS)或同时使用这两个端口。如果应用的多个组件需要与用户交互,或者使用端口 80 上的Web服务器交付其他资源,这可能会带来挑战。因此,需要将请求代理到Socket.IO服务器,而NGINX非常适合完成这项工作。无论后端应用只有一个实例还是数百个实例,使用多个节点时,NGINX还可以对上游服务器进行负载均衡。

Socket.IO配置

要安装Node.js,请下载适用的发行版(或使用包管理器进行安装)。运行npm install socket.io命令以安装Socket.IO。

在本示例中,假设实时应用的Socket.IO服务器在端口5000上运行。以下是server.js Node应用程序文件的模板。该基础程序充当服务器,将传入请求路由到运行Socket.IO服务器的相应端口。

var io = require('socket.io').listen(5000); 
io.sockets.on('connection', function (socket) {
  socket.on('set nickname', function (name) {
    socket.set('nickname', name, function () {
      socket.emit('ready');
    });
  });
 
  socket.on('msg', function () {
    socket.get('nickname', function (err, name) {
      console.log('Chat message by ', name);
    });
  });
});

将如下所示的JavaScript代码添加到交付给客户端的文件中,例如index.html。此示例会请求连接到您的应用,以便与用户的浏览器建立WebSocket连接。

<script src="/socket.io/socket.io.js"></script>
<script>
     var socket = io(); // your initialization code here.
</script>

NGINX 配置

上游声明

如果应用有多个实例,NGINX和NGINX Plus可以对用户会话进行负载均衡,并将其分配到多个节点。在NGINX或NGINX Plus配置的http上下文中,添加一个upstream块,以定义上游组中的节点。

如下例所示,可以在weight参数中添加到server指令,以设置定向到该服务器的流量比例。在此示例中,srv1.app.com接收的会话数是其他服务器的5倍。NGINX Plus通过增强的负载均衡方法,并增加会话持久性、运行状况检查、扩展状态报告以及负载均衡服务器组的即时重新配置功能,扩展了NGINX的反向代理能力。

# in the http{} configuration block
upstream socket_nodes {
    ip_hash;
    server srv1.app.com:5000 weight=5;
    server srv2.app.com:5000;
    server srv3.app.com:5000;
    server srv4.app.com:5000;
}

虚拟主机配置

声明上游服务器组后,需要配置虚拟服务器,将流量定向到该服务器组。配置中至少应包含proxy_pass指令,并指定上游服务器组的名称。由于WebSocket协议使用HTTP/1.1中引入的Upgrade标头,因此还需包含proxy_http_version指令。

server {
    server_name app.domain.com;
    location / {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://socket_nodes;
    }
}

静态文件怎么办?

要交付静态资源,可以让NGINX将请求代理到上游Node.js实例,但在大多数情况下,由NGINX直接提供这些资源效率更高。

结合上述server_name指令所在的server块,以下location块指示NGINX从本地http://app.domain.com/assets/目录提供内容,以响应客户端对/path/to/assets的内容请求。还可以进一步优化静态文件处理,或根据需要设置缓存过期时间。

location /assets {
    alias /path/to/assets;
    access_log off;
    expires max;
}

故障排除

如果收到以下错误,您运行的可能是低于1.3版本的NGINX。NGINX 1.3.13及更高版本支持使用WebSocket。

WebSocket connection to '...' failed: Error during WebSocket handshake: 'Connection' header value is not 'Upgrade': keep-alive socket.io.js:2371

延伸阅读

如需试用NGINX Plus,立即开始30天免费试用,或联系我们,讨论您的使用场景。


分享
标签: API, Node.js, 2014, Tech, F5 NGINX

相关博客文章

NGINX Plus R26 正式发布
NGINX | 2022/02/15

NGINX Plus R26 正式发布

NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。

使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
NGINX | 2022/02/10

使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击

gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。

Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
NGINX | 2021/09/13

Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划

了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。

NGINX Plus R19 正式发布
NGINX | 2019/09/03

NGINX Plus R19 正式发布

NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。

NGINX现已正式加入F5
NGINX | 2019/05/09

NGINX现已正式加入F5

NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。

使用NGINX和NGINX Plus实现高性能缓存
NGINX | 2016/08/24

使用NGINX和NGINX Plus实现高性能缓存

我将介绍NGINX在内容缓存和性能方面的工作原理,并分享一些控制NGINX内容缓存方式的技巧。