背景
websocket在长连接应用场景中用的越来越多,随着业务量和应用场景的增加单台服务器所能提供的连接数达不到需求,所以多台服务器分布运行是日渐趋势。



实现思路
本次使用swoole来提供websocket服务,所需要服务器两台,nginx一台,mqtt服务全部用docker实现。两个服务分别开的端口是9091和9092来,nginx负载均衡监听9093端口,将来自不同客服端的连接转发到不同的服务上。
当使用点对点聊天的时候,发送消息内携带对方用户的fd和服务id。消息发送到连接的服务端,服务端解析目标服务id,并同过mqtt将消息发布到目标服务器对应的主题,当目标服务器订阅到该消息,并解析消息中目标fd。然后将消息发给对应的fd客户端。
用swoole搭建分布式的websocket服务器_服务端



1.nginx负载均衡
关于nginx负载均衡相关配置的可以参考我另一篇文章 ​​nginx配置负载均衡​



2.mqtt搭建
同样适用docker搭建mqtt服务。



docker pull

docker run -d --hostname my-rabbit --name some-rabbit -p 15672:15672 -p 
5672:5672 -p 1883:1883 -p 15675:15675 daocloud.io/library/rabbitmq:3.7.4


docker exec <容器ID> rabbitmq-plugins enable rabbitmq_mqtt

执行三个命令后,基本mqtt服务就搞定了,然后测试一下发布与订阅。

用swoole搭建分布式的websocket服务器_服务端_02

首先设置连接,然后客户端一个发布,一个订阅 同一个主题

用swoole搭建分布式的websocket服务器_服务器_03

测试时没有问题的。

  • 3.websocket服务
    使用使用swoole开启端口分表为9091和9092的服务。服务id分别为serverid:1和serverId:2。具体代码如下
    用swoole搭建分布式的websocket服务器_服务器_04
    另外一个文件server_slave.php里的内容一样只是端口改成了9092。
    在docker容器里分别启动两个文件。用swoole搭建分布式的websocket服务器_docker_05
    用swoole搭建分布式的websocket服务器_服务端_06
    然后使用工具测试连接,注意在nginx配置里面是使用9093端口对外,然后分别负载在9091和9092端口。
    用swoole搭建分布式的websocket服务器_websocket_07

测试连接。

用swoole搭建分布式的websocket服务器_websocket_08

可以看到两个客服端A和B分别连接到了serverId=1 (127.0.0.1:9051 的服务) 和serverId=2 (127.0.0.1:9052 的服务)

其实多连接几次两个客户端也有可能连上同一台服务。



消息分发
想要将消息从客服端A发到客服端B,首先在发消息的时候要确定给谁发,并且,知道B客服端连接在了哪台服务上。所以为了简单处理,每个客服端携带连接的fd和他所连接的服务id,这是在他连接上服务端的时候返回的。



1.当客服端A将消息发送到服务端A的时候,服务端A解析消息要分发的对象的服务id,然后找到要发布消息的mqtt服务的主题(这个主题是提前配置好),将消息发布到该主题后。服务端B订阅该主题后,获取到消息中要发送消息的客服端fd,然后将消息发推给这个客服端,整个流程就完了。



2.或者服务端A使用消息通知直接将消息推送给服务B,比如rpc,或者http请求都行。



用swoole搭建分布式的websocket服务器_服务端_09

这里消息接收后交给Message类里的shotSend()方法处理,并返回给客服端消息处理结果

用swoole搭建分布式的websocket服务器_服务端_10

如果使用http请求方式通知的话,服务端可以提供request方法接收请求,具体操作看下图。

用swoole搭建分布式的websocket服务器_docker_11

这样就可以了。我们试一下

用swoole搭建分布式的websocket服务器_websocket_12

可以看到服务B (serverId=2)上的客服端fd=6收到了来自服务A(serverId=1)的客服端fd=2的用户的消息。

至此 多服务器实现websocket部署功能以及基本实现,这只是一个dome用来学习的示例,仅提供思路。在现实使用场景中依然会有更多的问题。dome和产品的差距还是很大的,大家加油。