1 长连接还是短连接?大部分的服务框架会选择长连接
1)长连接更节省资源,若每发送一条消息都需要创建链路、发起握手认证、关闭链路释放资源,会损耗大量的系统性能,长连接只在首次创建时或者链路断连重连的时候才会创建链路,创建成功之后服务提供者和消费者会通过业务消息和心跳维系链路,实现多消息复用同一个链路节省资源
2)远程通信是常态,调用时延是关键目标,服务化之后本地调用变成了远程服务调用,大量的本地方法变成了跨进程通信,网络时延称为关键的指标之一,相比于一次简单的服务调用,链路的重建更加耗时
所以,通常会采用长连接
2 BIO还是NIO
BIO常由一个独立的Acceptor线程监听连接,它接收到客户端的连接请求后为每个客户端创建一个新的线程去处理,处理完成之后通过新的输出流返回应答给客户端,线程销毁
缺:缺乏伸缩能力,访问增大之后,由于服务端的线程数和客户端并发访问数成1:1的关系,线程数会急剧膨胀,系统的性能就会快速下降,并发访问数继续增大时,会出现线程创建失败,线程堆栈溢出等问题,最终导致进程宕机,不能进一步提供服务
NIO采用多路复用技术,一个多路复用器Selector可以同时轮询多个Channlel,一个线程专门负责Selector的轮询,可以介入成千上万个客户端
所以,一般都会选择NIO
3 成熟框架Netty
1)API使用简单,开发门槛低
2)功能强大,预置了多种编解码功能,支持多种主流协议
3)定制性强,可以通过ChannelHandler进行灵活扩展
4)成熟稳定,相比其它主流框架,综合性能最有
5)社区活跃,版本迭代周期短,发现的bug可以及时修复
6)经历了大规模的商业应用考验
服务端设计原则:
1)只提供上层的API,不与具体的协议绑定
2)服务端提供给客户端的API要尽量屏蔽底层的通信细节,防止底层的变更一起级联变更
3)功能不要求全,要有良好的可扩展性
可靠性设计:
1)链路有效性检测
a.TCP层面的心跳检测,即TCP的keppalive机制,它的作用域是整个TCP协议栈
b.协议层的心跳检测,主要存在于长连接协议中,如SMPP协议
c.应用层的心跳检测 各业务产品自己约定方式定时给对方发送心跳消息
目的是确定当前链路可用,对方可以正常的收发消息
ping-pong型:一方定时发送ping消息,对方接收并响应pong消息
ping-ping型:不区分心跳请求和应答,由通信双方按照约定的时间向对方发送ping消息
心跳超时:连续发送多个ping都没有收到对方的pong响应或者ping请求消息,说明链路已逻辑失效
心跳失败:直接发生了IO异常,说明链路已失效
超时或者异常都需要关闭链路由客户端发起重连
断连重连:发生以下现象时需要发起重连
1)服务端主动关闭连接,客户端检测到链路被正常关闭
2)服务端因为宕机等故障,强制关闭连接,客户端检测到链路被rest掉
大部分的分布式框架会支持多协议,但是却不是必须支持
协议消息的定义:
crcCode 校验码 固定值(表明私有协议)、主版本号、次版本号
消息长度:包括消息头和消息体
type:消息类型(业务请求、业务响应、握手请求、握手应答、心跳请求/应答)
priority:消息优先级
interfacename:接口名称
methodname:方法名
attachment:扩展消息头
协议栈可靠性设计:
1)客户端失败重连
延时重连、及时释放自身资源、打印异常信息,方便问题定位
2)重复握手保护
连接成功后不允许重复握手,防止客户端异常的情况下,反复连接导致句柄资源被耗尽
3)消息缓存重发 保证消息再连接异常期间的消息不丢失
4)心跳机制 网络空闲时使用心跳检测链路可用性