协议栈

编程

一、关键技术点分析

不同服务在性能上适用不同协议进行传输,如对接异构第三方服务时,通常选择HTTP/Restful等公有协议;而对于内部不同模块之间的服务调用,一般选择性能较高的二进制私有协议。

1.1 是否必须支持多协议

否,这需要根据业务的实际需要来定。但分布式服务框架需要具备通过扩展的方式来支持多协议的能力。

1.2 公有协议还是私有协议

要实现异构系统之间的服务调用,最佳做法就是使用标准的公有协议;
但在性能方面,私有协议往往可以根据业务的具体需求进行针对性优化,性能更优。
因此一般情况下,分布式服务框架默认使用性能更好的私有协议(二进制),在需要与外部对接的服务,可以考虑引入HTTP/Restful等公有协议。

1.3 开源还是自研

私有协议一般是自研的;
公有协议,可以采用业界比较成熟的方案,也可以基于Netty自研。

二、功能设计

2.1 功能描述

私有协议栈承载了业务内部各个模块之间的消息交互和服务调用,主要功能如下:

  1. 定义了私有协议的通信模型和消息定义
  2. 支持服务提供者和消费者之间采用点对点长连接通信
  3. 基于 Java NIO 通信框架,提供高性能的异步通信能力
  4. 提供可扩展的编解码框架,支持多种序列化方式
  5. 握手和安全认证机制
  6. 链路的高可靠性

2.2 通信模型

模型图见 P83 图5-1
服务提供者跟消费者之间采用单链路、长连接的方式进行网络通信,创建流程如下:

  1. 客户端发送握手请求,携带节点ID等有效身份认证信息
  2. 服务端对握手请求消息进行校验,通过校验后发送握手应答消息
  3. 链路创建成功,客户端发送业务消息
  4. 链路创建成功,服务端发送心跳消息
  5. 链路创建成功,客户端发送心跳消息
  6. 链路创建成功,服务端发送业务消息
  7. 服务端退出时关闭连接,客户端感知后被动关闭连接

2.3 协议消息定义

私有协议和公有协议的消息模型是类似的,包含消息头header和消息体body两部分。
消息头通常包含服务调用的相关参数:

  • crcCode,协议栈校验码
  • length,消息长度(整个消息的长度,包括消息头、消息体)
  • type,消息类型,可能是:业务请求消息、业务响应消息、业务ONE WAY消息(既是请求又是响应)、握手请求消息、握手应答消息、心跳请求消息、心跳应答消息
  • priority,消息优先级
  • interfaceName,接口名
  • methodName,方法名
  • attachment,可选字段,用于扩展消息头(比如增加TraceID,进行业务链路追踪)

2.4 协议消息的序列化和反序列化

消息的序列化分为两部分,消息头的序列化和消息体的序列化,两者采用的机制不一样,原因是协议栈可以由不同的序列化框架承载,标识序列化格式的字段在消息头中定义,因此我们要先对消息头做通用解码,获取序列化格式,然后根据类型再调用对应的解码器对消息体解码。

三、可靠性设计

3.1 客户端连接超时

同步阻塞编程模式下,客户端socket发起网络连接,需要指定超时时间,目的是:

  • 在同步阻塞I/O模型中,连接操作是同步阻塞的,若不设置超时时间,客户端I/O线程可能被长时间阻塞,导致系统可用I/O线程数减少
  • 业务层需要,多数系统对业务本身的流程执行时间有要求

3.2 客户端重连机制

客户端监听链路状态,如果链路中断,等待 INTERVAL 时间后,由客户端发起重连,若失败则间隔 INTERVAL 时间后再次发起重连,直到成功。
等待 INTERVAL 时间是为了保证服务端能有足够的时间来释放句柄资源。
客户端也会对重连次数做限制,防止无限重连导致资源损耗。

3.3 客户端重复握手保护

客户端握手成功后,链路处于正常状态下,不允许客户端重复握手,防止客户端在异常状态下反复重连导致句柄资源被耗尽。
服务端收到客户端的握手请求后,先对IP地址进行合法性校验,若检验成功,则在缓存的地址表中查看客户端是否已登录,如果已登录,则拒绝重复登录,关闭TCP链路,并在服务端日志中打印握手失败的原因。
客户端接受到握手失败的应答消息后,关闭客户端的TCP连接,等待 INTERVAL 时间后再次发起 TCP 连接,直到认证成功。
为了防止服务端和客户端对链路状态理解不一致导致的握手失败,当服务端连续N次心跳超时之后需要主动关闭链路,清空该客户端的地址缓存信息,保证后续该客户端可以重连成功,防止被重复登录保护机制拒绝掉。

3.4 消息缓存重发

无论是客户端还是服务端,当链路中断,后再链路恢复之前,缓存在消息队列中待发的消息不能丢失,等链路恢复后,重发这些消息,保证链路中断期间消息不丢失。
消息缓存队列应该设置上限,达到上限之后应该拒绝向该队列添加新的消息,防止内存溢出。

3.5 心跳机制

在凌晨等业务低谷期,如果发生了网络闪断等问题,由于没有业务消息,网络问题难以被发现,等到了白天业务高峰期,大量网络通信失败会导致一段时间内进程无法处理业务消息。
为了解决该问题,在网络空闲时采用心跳机制来检测链路的互通性,一旦发现网络故障,立即关闭链路,主动重连。


 

以上是 协议栈 的全部内容, 来源链接: utcz.com/z/510872.html

回到顶部