功能描述:
- 异步通信
- 消息编解码框架
- 接入认证机制
- 链路有效性校验机制
- 断连重连机制
通信模型
image.png消息定义
消息包含两部分:
- 消息头 : 用于定义消息属性,如协议码,消息长度,会话id,消息类型等。
- 消息体 : 定义了消息的具体内容
消息头
消息头定义.png
在书中的有一句让我醍醐灌顶,消息体,对于请求消息,它是方法的参数,而对于响应消息,它是返回值。
我对这句话的理解是,其实所有的远程调用或者说rpc中,其本质都是为了能让本地应用,像使用本地内部方法一样,使用远程应用的某些功能。
一个方法的基本构成是:返回值、方法名以及参数。
在rpc中这些构成映射为:消息响应,消息请求以及消息内容。
这样说来,其实在设计协议栈和设计底层调用是有异曲同工之妙的,同样是需要考虑调用过程中调用栈、参数压栈出栈等。
只是rpc需要考虑网络与并发的影响,就是连接是否畅通,同时发起的调用是否有效及时。所以才会出现关于链路有效性、可靠性、安全性以及IO模型的设计。
建链断链机制
- 建链 : 握手机制
- 断链 : 出现以下情况,双方需要一起关闭连接
- 一方关机或者重启
- 消息读写中IO异常
- 心跳超时
- 不可恢复异常如编码异常
可靠性设计
由于网络的不可靠性,如超时、闪断、对方僵死或处理缓慢等,我们需要保证协议栈在这种异常情况下正常工作或者自动恢复,类似try-catch,捕获异常,处理异常。
心跳机制
在业务低谷时,如果连接不可用或者服务不可用,由于极少业务消息来往,因此应用不能及时发现并处理这种异常。通过在网络空闲时发送无意义的空消息来检测链路的互通性,也就是心跳机制,一旦发现故障,立即关闭连接,主动重连。
那么,谁来发这个心跳包?
- 两边都要发:适用于长连接(Ping-Pong双向心跳机制)
- 只有一方发:其中一边是被动方式,如果一段时间收不到心跳包就直接断开连接
怎么发?
一种是任何情况下都固定时间发,另一种是一段时间没有收发数据才发。
----参考服务端主动发送心跳包,还是客户端发送比较好?
另外为了防止因为对方繁忙没有及时响应造成误判,双方内部都设置心跳失败计数器,只有连续N次心跳检测失败,才判断连接无效,需要断链重连。
重连机制
链路中断INTERVAL时间后,由客户端发起重连操作,如果重连失败,间隔INTERVAL后再次重连,直至重连成功。
重连需要间隔一段时间,一方面是为了让彼此有时间释放连接资源,另一方面排除网络连接波动导致重连失败,类似硬件中消抖机制。
重连失败,最好打印异常堆栈,方便问题的定位。
重复登录保护
客户端在异常状态下会反复重连,如果不限制重复登录,服务端的连接资源将很快被耗尽。
客户端登录成功后,将连接信息和用户信息缓存在服务器中,如果有同样的客户登录,则拒绝此次登录。
登出或者心跳超时情况下,清空这些缓存的信息,以便下次登录以及重连。
消息缓存重发
无论客户端还是服务端,连接中断之后,缓存在消息队列中待发送的消息不能丢失,在连接恢复后,重新发送这些消息。
常见的做法是提供通知机制,将发送失败的消息通知给业务层,让业务去决定丢弃还是重发。
安全性设计
集群内部:基于IP地址的安全认证机制
公网环境:基于密钥和AES加密的用户名+密码或者SSL/TSL安全传输
网友评论