文章目录
2021SC@SDUSC
本章将讲述基于Netty实现ServerCnxn服务器连接。使用Netty框架来高效处理服务器与客户端之间的通信。
源码分析
(1)属性,与NIO类似。NettyServerCnxn维护了服务器与客户端之间的通道缓冲、缓冲区以及会话等属性。
//获取基于Netty框架服务连接的日志
private static final Logger LOG = LoggerFactory.getLogger(NettyServerCnxn.class);
//连接通道,客户端与服务器连接通道
private final Channel channel;
//通道缓存
private CompositeByteBuf queuedBuffer;
private final AtomicBoolean throttled = new AtomicBoolean(false);
//字节缓冲区
private ByteBuffer bb;
//设置缓冲区为4个字节
private final ByteBuffer bbLen = ByteBuffer.allocate(4);
//客户端与服务器之间会话的ID
private long sessionId;
//客户端与服务器之间会话超时时间,当会话超时时,会自动释放资源结束会话
private int sessionTimeout;
private Certificate[] clientChain;
//关闭连接通道
private volatile boolean closingChannel;
//NettyServerCnxn工厂
private final NettyServerCnxnFactory factory;
//初始化标志
private boolean initialized;
public int readIssuedAfterReadComplete;
//握手状态,即连接状态默认为未连接
private volatile HandshakeState handshakeState = HandshakeState.NONE;
//连接状态分为未连接、开始连接、完成连接
public enum HandshakeState {
NONE,
STARTED,
FINISHED
}
(2)构造函数,与NIOServerCnxn区别在于Netty的构造函数需要用户进行登录验证。其余部位对NIOServerCnxn的部分重要属性进行赋值。
//参数需求存在连接通道,服务器以及已经初始化的NettyServerCnxn工厂
NettyServerCnxn(Channel channel, ZooKeeperServer zks, NettyServerCnxnFactory factory) {
super(zks);
this.channel = channel;
this.closingChannel = false;
this.factory = factory;
//用户登录
if (this.factory.login != null) {
this.zooKeeperSaslServer = new ZooKeeperSaslServer(factory.login);
}
//获取IP地址
InetAddress addr = ((InetSocketAddress) channel.remoteAddress()).getAddress();
//认证信息中添加IP地址
addAuthInfo(new Id("ip", addr.getHostAddress()));
}
(3)核心函数(一)——close(),关闭服务器与客户端之间的连接通道。
//关闭连接通道
public void close() {
//关闭连接通道标志为true
closingChannel = true;
//关闭会话的ID
LOG.debug("close called for session id: 0x{}", Long.toHexString(sessionId));
setStale();
// 关闭时始终取消注册连接,以防止在某些竞争条件下连接bean泄漏。
factory.unregisterConnection(this);
// 如果这连接通道不在cnxns中,那么它已经关闭了
if (!factory.cnxns.remove(this)) {
LOG.debug("cnxns size:{}", factory.cnxns.size());
if (channel.isOpen()) {
channel.close(