私有协议栈介绍
使用集群或者分布式部署,各个模块之间需要进行跨节点通信。
传统java中,有四种跨节点通信的方法:
1、通过RMI,进行远程服务调用。就是remote method invocation,允许一个JVM上的对象调用另一个JVM上的对象的方法。使用java的序列化机制来传递方法参数和返回值。通过RMI注册表来查找远程服务的引用。
2、通过java的socket+序列化的方式进行跨节点调用。
3、利用一些开源的RPC框架进行远程服务调用:thrift和avro
4、利用标准的公有协议进行。http+xml,webservice。
私有协议就是包括对请求和响应消息进行编码和解码以及一些其他控制和管理的指令,例如心跳检测,握手请求之类。
netty协议栈功能设计
基于tcp/ip协议栈。
主要功能如下:
1、基于netty的NIO通信框架,提供高性能的异步通信能力。
2、提供消息的编解码框架,可以实现POJO的序列化和反序列化。
3、提供基于ip地址的白名单接入认证机制。
4、链路的有效性校验机制。
5、链路的断链重连机制。
netty通信链路双方可以进行全双工通信。
netty消息定义为消息头和消息体。
消息头包括以下参数:
1、cecCode:netty消息的校验码
编码方法:java.nio.bytebuffer.putint(int value)方法
解码方法:java.nio.bytebuffer.getint方法
2、length:消息长度,包括消息头和消息体
编码方法:java.nio.bytebuffer.putint(int value)方法
解码方法:java.nio.bytebuffer.getint方法
3、sessionID 会话ID:集群节点内全局唯一,由会话ID生成器生成。
编码方法:java.nio.bytebuffer.putlong(long value)方法
解码方法:java.nio.bytebuffer.getlong方法
4、type:0:业务请求信息 1:业务响应信息 2、业务one way信息(即是响应信息又是请求信息)3
:握手请求信息 4、握手应答信息 5、心跳请求信息 6、心跳响应信息
编码方法:java.nio.bytebuffer.put(byte b)方法
解码方法:java.nio.bytebuffer.get方法
5、priority :优先级 0-255
编码方法:java.nio.bytebuffer.put(byte b)方法
解码方法:java.nio.bytebuffer.get方法
6、attachment:可以用来拓展消息头
编码方法:如果attachment为0,用java.nio.bytebuffer.putint(0)方法
如果attachment不为0,编码方法如下:
先编码attachment的长度:java.nio.bytebuffer.putint(attachment.size())。
然后在对Key进行编码,先编码长度,再把它转化为byte数组之后再编码内容:
通过jboss marshalling方法将object序列化为byte数组。
解码方法: 先创建一个attachment对象,调用java.nio.bytebuffer.getint获取附件的长度,如果非空,根据长度用for循环进行解码。
7、body的编码:通过jboss marshalling方法将其序列化为byte数组。然后调用java.nio.bytebuffer.put(byte[]src)把他写到bytebuffer缓冲区里。
body的解码:通过jboss的unmarshaller对其进行解码。
握手请求的消息体为空。
链路的关闭的五种情况:
1、对方需要宕机或者重启,我方也需要关闭连接释放资源。
2、消息读写过程中发生IO异常
3、心跳消息读写过程中发生IO异常
4、心跳超时,需要主动关闭连接
5、发生编码异常
可靠性设计
1、心跳机制:
客户端:网络空闲时间到了T时,客户端主动发送ping消息给服务端。此时在T时间内没有收到服务端的pong信息或者业务信息,心跳失败计时器+1,如果收到则清零。当心跳失败计时器到了N之后,主动关闭链路,间隔interval时间后重连。
服务器端:网络空闲时间到了T时,服务器端的心跳失败计时器就+1,接收到ping或者任务消息后才清零,到了N就断开连接释放资源。等待客户端重连。要清空缓存的半包连接。
2、重连机制:
等待interval时间再重连是为了给服务端充足的时间释放句柄资源。
客户端也要保证自己的资源被释放。
3、重复登陆保护:
在ip校验成功之后,还要再缓存的地址表里看看客户端是否已经登陆,如果登陆了就拒绝重复登陆。
在每次断连的时候,服务端会清空该客户端在地址表里的信息。
4、消息缓存重发:
断连后无论客户端还是服务端缓存在消息列表里的待发送的消息不能丢失,消息缓存队列会设置上限。
netty协议栈的开发
nettymessage类包含header和body两个属性。
心跳消息、握手请求和握手应答消息可以统一由nettymessage承担。
编码和解码
nettymessagedecoder和nettymessageencoder(继承了LengthFieldBasedFrameDecoder支持自动的TCP沾包和半包处理,这样返回的消息就是整包或为空)用于nettymessage消息的编解码。
里面用到了marshallingencoder和marshallingdecoder