使用Socket.io搭建WS服务并通过Nginx反向代理
Nodejs、Express、Socket.io、Nginx
使用Express框架和Socket.io库将websocket搭建起来,并监听同一个端口,参考官方例子[1]就可以,非常简单。
1 | var app = require('express')(); |
Nginx同时作为Web Server和WebSocket Reverse Proxy
在配置Nginx的时候,遇到了很多的问题,并且在网上现在找不到一篇对这个问题讲解的非常清楚的文档。
比如:
- Nginx是否支持http/websocket在同一个端口。答案是可以的。
- Nginx支持支持代理socket.io。 结论:支持。
- var socket = io(); 初始化的时候,io()要不要传入地址参数。 结论:不需要传入参数。
- Nginx配置的URL匹配规则是什么。
全部代码请跳转Github.
经过试验和参考Nginx的文档[2],Nginx配置如下:
1 | server { |
为什么nginx上配置的Location必须是固定的,通过调试socket.io的机制就清楚了,见下。如果将nginx location中的规则修改成其他的,前端将无法连接socket.io服务。
除了Socket.io之外,是否还要其他选择?
可以使用ws库来搭建一个websocket服务。这个和socket.io的区别在于socket.io做了额外的很多工作,比如某些浏览器上不支持websocket,那么socket.io会通过轮询的方式来模拟websocket.
如果使用nodejs, 可以参考Nginx官方的文档[3]
配置Nginx
申请SSL证书
先申请SSL证书,有付费的,有免费的,一般来说,如果购买了腾讯云/阿里云的域名都可以申请到免费证书。也可以到Let’s Encrypt网站上申请。这个网站的服务是由互联网安全研究工作组ISRG提供的。
不过我使用Caddy软件一键自动部署(代理)和自动申请证书。不过从使用体验上来看,似乎Caddy要稍微性能要慢一些。
Caddy自动申请的证书存放的位置[5]在:
~/.caddy/acme/acme-v01.api.letsencrypt.org/sites/xxx.xxx(域名)/
所以,如果有Caddy已经自动申请了证书,那么nginx可以直接使用该证书。
配置nginx, 开启HTTPS
默认nginx的配置目录在/etc/nginx下面。
可以通过DigitalOcean提供的免费Nginx的配置工具[6]来生成配置文件,这个网站非常棒,提供了很丰富的配置。生成出来的配置按照Site进行了分组。比如我的域名node-nj.typedefine.cn, 我只需要打开sites-available下面的node-nj.typedefine.cn.conf配置进行查看就行了。
nginx依然通过nginx.conf来加载配置,但是nginx.conf->sites-enabled->sites-available。基本上只需要关注sites-available中每个站点的独立的配置就可以了。
如果需要将SSL证书共用,也可以配置到Global Config中。具体使用参考说明。
配置nginx到Systemd中
新增nginx.service到/etc/systemd/system目录下
1 | [Unit] |
重新加载systemd
systemctl daemon-reload
启动服务
systemctl start nginx
查看服务状态
systemctl status nginx
查看日志
sudo journalctl -u nginx
配置反向代理:
按照如下配置即可[4]:
1 | location /wsapp/ { |
完整的站点配置:
1 | server { |
- 1.https://socket.io/docs/#Using-with-Express ↩
- 2.https://www.nginx.com/blog/nginx-nodejs-websockets-socketio/ ↩
- 3.https://www.nginx.com/blog/websocket-nginx/ ↩
- 4.http://nginx.org/en/docs/http/websocket.html ↩
- 5.https://www.cmsky.com/caddy-proxy-shell/ ↩
- 6.https://www.digitalocean.com/community/tools/nginx ↩