单体式架构
根据基于golang的gin框架开发的web项目所展开
如果一个Web项目采用单体式架构且配备了websocket通讯的功能,那么在单个实例中是能够正常运行的
在我的项目中,用户可以通过websocket来进行实时通讯和实时消息通知,同时如果在web业务中通过触发条件可以实现实时系统通知
注意:本文的分布式思想不考虑微服务
单台websocket
单台消息互传实现十分简单,通过websocket中转就可以了,不再多加赘述。
但是随着业务的发展必将同时部署多个实例来分担压力,但此时处于不同实例之间的用户并不能互相通讯
1.服务拆分
一提到服务拆分就会联想到微服务,但是为了这个我们可能要付出重构的代价,凭着合适才是王道的想法,我放弃用微服务重构而是采用服务拆分的思想,以下将不考虑微服务拆分。
我们首先考虑将websocket和web业务进行拆分,用消息队列(以NSQ为例)进行主web业务与websocket业务的下发通讯
服务拆分后,虽然能够分解一定的压力,但是终究会遇到瓶颈,但是也会面临多实例部署的情况
2.服务拆分后的多实例部署
下列图中 client1和client3/client4 就无法进行通讯
解决方案
1.使用全局redis存储客户端与服务端的关系,即用户连接到了哪台websocket服务器上;
2.webscoket服务器各自订阅以其他服务器为生产者的消息队列。
发消息流程:
Client与服务器创建连接后会先在本地的map中注册自己的信息,然后在redis中存储Client连接到的服务器编号
情况一:
clientA 给 clientB 发消息时,先从redis中读取clientB在哪个服务器上,如果发现clientA 与clientB 在同一服务器时,会话消息直接在本地上处理发送给clientB
情况二:
clientB 给 clientC 发消息时,从reids中读到clientC和clientB并不在同一服务器上,例如clientC在wsB,那么clientB的消息会被wsA发送到消息队列进行推送,然后消息被推送到wsB,wsB给clientC发送消息。
我所采用的架构
所有ws实例都会去订阅以所有web实例为生产者的消息队列,以此来实现通过web触发的实时消息推送通知
所有ws实例会互相订阅以ws为生产者的消息队列,实现跨服务器的websocket通讯。
本文到这里就结束了,欢迎各位小伙伴点赞文章留言讨论,一块儿学习,一块儿进步。
本文思路参考:
分布式websocket解决方案
分布式websocket服务器