内容简介:用Websocket客户端连接本服务,服务端会返回客户端一个唯一的client id,通过这个client id可以知道是哪个连接,客户端拿到这个id之后上报到服务端,服务端根据业务需求可以给这个长连接发送指定信息,或者绑定到分组。维持大量的长连接对单台服务器的压力也挺大的,这里也就要求该服务需要可以扩容,也就是分布式地扩展。分布式对于可存储的公共资源有一套完整的解决方案,但对于WebSocket来说,操作对象就是每一个连接,它是维持在每一个程序中的。每一个连接不能存储起来共享、不能在不同的程序之间共享。所
使用流程
用Websocket客户端连接本服务,服务端会返回客户端一个唯一的client id,通过这个client id可以知道是哪个连接,客户端拿到这个id之后上报到服务端,服务端根据业务需求可以给这个长连接发送指定信息,或者绑定到分组。
分布式方案
维持大量的长连接对单台服务器的压力也挺大的,这里也就要求该服务需要可以扩容,也就是分布式地扩展。分布式对于可存储的公共资源有一套完整的解决方案,但对于WebSocket来说,操作对象就是每一个连接,它是维持在每一个程序中的。每一个连接不能存储起来共享、不能在不同的程序之间共享。所以我能想到的方案是不同程序之间进行通讯。
那么,怎样知道某个连接在哪个应用呢?答案是通过client id去判断。那么通过client id又是如何知道的呢?有以下几种方案:
-
一致性hash算法
一致性hash算法是将整个哈希值空间组织成一个虚拟的圆环,在 redis 集群中哈希函数的值空间为0-2^32-1(32位无符号整型)。把服务器的IP或主机名作为关键字,通过哈希函数计算出相应的值,对应到这个虚拟的圆环空间。我们再通过哈希函数计算key的值,得到一个在圆环空间的位置,按顺时针方向找到的第一个节点就是存放该key数据的服务器节点。
在没有节点的增减的时候,可以满足我们的需求,但如果此时一个节点挂掉了或者新增一个机器怎么办?节点挂点之后,会在圆环上删除节点,增加节点则反之。这时候按顺时针方向找的数据就不准确,在某些业务上来说可以接受,但在WebSocket微服务上来说,影响范围内的连接会断掉,如果要求没那么高,客户端再进行重连也可以。
-
hash slot(哈希槽)
服务器的IP或者主机名作为key,对每个key进行计算CRC16值,然后对16384进行取模,得出一个对应key的hash slot。
HASH_SLOT = CRC16(key) mod 16384
我们根据节点的数量,给每个节点划分范围,这个范围是0-16384。hash slot的重点就在这个虚拟表,key对应的hash slot是永不变的,增减节点就是维护这张虚拟表。
以上两种方案都可以实现需求,但一致性hash算法的方案会使部分key找到的节点不准确;hash slot的方案需要维护一张虚拟表,在实现起来需要有一个功能去判断服务器是否挂了,然后修改这张虚拟表,新增节点也一样,在实现起来会遇到很多问题。
然后我采取的方案是,每个连接都保存在本应用,然后用redis的key value记录每个连接client id对应的服务器IP和端口。对指定client id进行操作时,去redis找出响应的ip和端口,判断是否为本机,不是本机的话进行RPC通讯告诉相应的程序。长连接的连接数据不可迁移,程序挂掉了相应的连接也就挂了,在该程序上的连接也就断开了,这时重连的话会找到另一个可用的程序。
Golang实现的分布式WebSocket微服务
简介
本系统基于Golang、Redis、RabbitMQ、RPC实现分布式WebSocket微服务,也可以单机部署,单机部署不需要Redis、RabbitMQ和RPC。分布式部署可以支持nginx负责均衡、水平扩容部署,程序之间使用RabbitMQ广播、RPC通信。
基本流程为:用ws协议连接本服务,得到一个clientId,由客户端上报这个clinetId给服务端,服务端拿到这个clientId之后,可以给这个客户端发送信息,绑定这个客户端都分组,给分组发送消息。
目前实现的功能有,给指定客户端发送消息、绑定客户端到分组、给分组里的客户端批量发送消息。适用于长连接的大部分场景,分组可以理解为聊天室,绑定客户端到分组相当于把客户端添加到聊天室,给分组发送信息相当于给聊天室的每个人发送消息。
架构图
单机服务
WebSocket单机服务架构图
分布式
WebSocket分布式服务架构图
时序图
单发消息
- 客户端发送连接请求,连接请求通过nginx负载均衡找到一台ws服务器;
- ws服务器响应连接请求,返回client id,记录到redis,保持长连接;
- 客户端拿到client id之后,交给业务系统;
- 业务系统拿到client id之后,通过http发送相关消息,经过nginx负载分配到一台ws服务器;
- 这台ws服务器拿到clinet id和消息,去redis查询到IP地址和端口;
- 拿到IP地址和端口,通过PRC协议给指定ws程序发送信息;
- 该ws程序接收到client id和信息,给指定的连接发送信息;
- 客户端收到信息。
WebSocket微服务单发时序图
群发消息
- 前3个步骤跟单发的一样;
- 业务系统拿到client id之后,通过http给指定分组发送消息,经过nginx负载分配到一台ws服务器;
- 这台ws服务器拿到分组ID和消息,发布给RabbitMQ;
- 所有订阅到RabbitMQ的服务,会收到新信息推送,找到本机所有该分组的连接;
- 给所有这些连接发送消息;
- 客户端收到信息。
WebSocket微服务群发消息时序图
源码
github: https://github.com/woodylan/go-websocket
交流
QQ群:1028314856
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 【分布式锁】07-Zookeeper实现分布式锁:Semaphore、读写锁实现原理
- 原 荐 分布式锁与实现(二)基于ZooKeeper实现
- 分布式实现原理
- 实现分布式锁
- SOFAJRaft 实现原理:SOFAJRaft-RheaKV 分布式锁实现剖析
- RedLock 实现分布式锁
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
现代前端技术解析
张成文 / 电子工业出版社 / 2017-4-1 / 79.00元
这是一本以现代前端技术思想与理论为主要内容的书。前端技术发展迅速,涉及的技术点很多,我们往往需要阅读很多书籍才能理解前端技术的知识体系。《现代前端技术解析》在前端知识体系上做了很好的总结和梳理,涵盖了现代前端技术绝大部分的知识内容,起到一个启蒙作用,能帮助读者快速把握前端技术的整个脉络,培养更完善的体系化思维,掌握更多灵活的前端代码架构方法,使读者获得成为高级前端工程师或架构师所必须具备的思维和能......一起来看看 《现代前端技术解析》 这本书的介绍吧!