本文将介绍如何将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天免费试用,或联系我们,讨论您的使用场景。
相关博客文章
NGINX Plus R26 正式发布
NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。
使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。
Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。
NGINX Plus R19 正式发布
NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。
NGINX现已正式加入F5
NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。
