nginx反向代理实现websocket负载均衡


任务背景

我们有n台ws服务,但是某些客户他们客户端都是用https,所以就不能用ws协议了,得换成wss。而每台ws服务升级成wss成本太高太麻烦,所以想使用nginx来做这些ws服务的反向代理服务器,并给访问域名部署https以支持wss


解决

解决的方法也是在nginx配置一个upstream,里面可以若干个节点信息,也可以是引入一个文件,这个文件包含的节点信息,这样可能更方便维护节点信息。 然后就是server进行请求转发到upstream。

现在本地开2个soket服务,php需要开启sokets扩展,代码在最下面的 ws.php。

cd D:/www/test
php ws.php  #soket服务1 127.0.0.1:8001
php ws2.php #soket服务2 127.0.0.1:8002

访问2个聊天室,这些都是网上找的demo,方便测试用。 对应打开2个chat.html和chat2.html,分别websoket上面2个soket服务地址。

demo地址:浅谈php中使用websocket


本地配置一个虚拟域名www.wss.com,然后修改nginx配置,想要wss的话,就给域名配置证书就行了,其他不变。

upstream websocket {
    #ip_hash;
    server 127.0.0.1:8001;
    server 127.0.0.1:8002;  
}
server {
    listen        80;
    server_name  www.wss.com;
    location / {
        #反向代理
        proxy_pass http://websocket;
        proxy_set_header Host $host;
        proxy_set_header X-Real_IP $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr:$remote_port;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;   # 升级协议头
        proxy_set_header Connection upgrade;
        proxy_read_timeout 6000s; #超时时间 10分钟
    }
}

重启nginx,新建一个test.html测试:

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<h1>websoket代理测试</h1>
	<script>
		var websocket = null;
		 
        //判断当前浏览器是否支持WebSocket
        if ('WebSocket' in window) {
            websocket = new WebSocket("ws://www.wss.com");
        }
        else {
            alert('当前浏览器 Not support websocket')
        }
 
        //连接发生错误的回调方法
        websocket.onerror = function () {
            console.log("WebSocket连接发生错误");
        };
 
        //连接成功建立的回调方法
        websocket.onopen = function () {
            console.log("WebSocket连接成功");
        }
 
        //接收到消息的回调方法
        websocket.onmessage = function (event) {
            console.log(event.data);
        }
 
        //连接关闭的回调方法
        websocket.onclose = function () {
            console.log("WebSocket连接关闭");
        }
	</script>
</body>
</html>

接下来就可以测试效果了,分别在两个聊天室输入内容,看看test.html控制台输出的是哪个聊天室的内容吧。刷新后,再试试。

我这边是把ip_hash给注释了,就是轮训的策略,具体还是可以参考nginx负载均衡的策略配置。

问题:其实我开始不是用原生的websoket测试,而且部署了wokerman的soketio来测试,必须配置ip_hash,不然连接就会自动关闭等,这个我也纳闷啊。


补充

比如我们需要维护负载的配置,增删改节点,可以这么操作。

1. 将节点信息放入外部文件中,upstream websocket 中引入;

2. 部署一个php脚本,作为api接口,当节点方式变化时带上信息请求该接口。

3. 接口脚本根据请求参数,更新节点文件,并exec调用nginx重载配置的命令,nginx -s reload

4. websocket连接期间可以进行ping的操作,就发消息给服务器,避免连接超时

5. websocket做负载均衡的话,得处理好多个节点间的交互,比如数据到了W1节点,那么连接到其他节点的客户端必须也能收到消息。


继续

关于生产环境的部署测试等,还在摸索中,后续还会更新进行对websocket的压测内容。。


javascript php nginx


上一篇:安卓IOS的APP统一下载地址

PHP项目上传大文件所需配置:下一篇