大家好,上一次分析了注册流程 这次就开始分析下接收处理过程。贴图
1,this.defaultEventExecutorGroup = new DefaultEventExecutorGroup(//
nettyServerConfig.getServerWorkerThreads(), //
new ThreadFactory() {
private AtomicInteger threadIndex = new AtomicInteger(0);
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "NettyServerWorkerThread_" + this.threadIndex.incrementAndGet());
}
});
默认事件线程组
1.1,ServerBootstrap childHandler = //
this.serverBootstrap.group(this.eventLoopGroupBoss, this.eventLoopGroupWorker)
.channel(NioServerSocketChannel.class)
//使用NIO selector
.option(ChannelOption.SO_BACKLOG, 1024)
//输入连接指示(对连接的请求)的最大队列长度被设置为 backlog 参数。如果队列满时收到连接指示,则拒绝该连接
.option(ChannelOption.SO_REUSEADDR, true)
//设置了SO_REUSADDR的应用可以避免TCP 的 TIME_WAIT 状态 时间过长无法复用端口
.option(ChannelOption.SO_KEEPALIVE, false)
//设置心跳参数 FALSE为不启用参数
.childOption(ChannelOption.TCP_NODELAY, true)
//开启TCP_NODELAY表示package被忽略size尽快地发送。
.option(ChannelOption.SO_SNDBUF, nettyServerConfig.getServerSocketSndBufSize())
//socket发送缓冲区大小
.option(ChannelOption.SO_RCVBUF, nettyServerConfig.getServerSocketRcvBufSize())
//socket接收缓冲区大小
.localAddress(new InetSocketAddress(this.nettyServerConfig.getListenPort()))
//localAddress方法用于绑定服务器地址和端口
.childHandler(new ChannelInitializer
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
//
defaultEventExecutorGroup, //默认事件接收线程组
new NettyEncoder(), //netty编码器
new NettyDecoder(), //netty×××
new IdleStateHandler(0, 0, nettyServerConfig
.getServerChannelMaxIdleTimeSeconds()),//
空闲链路状态处理
new NettyConnetManageHandler(), //自实现空闲链路处理
new NettyServerHandler());netty服务处理
}
});
1.2,if (nettyServerConfig.isServerPooledByteBufAllocatorEnable()) {
// 这个选项有可能会占用大量堆外内存,暂时不使用。
childHandler.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
}
是否启用推外内存,默认不使用
1.3,ChannelFuture sync = this.serverBootstrap.bind().sync();
InetSocketAddress addr = (InetSocketAddress) sync.channel().localAddress();
this.port = addr.getPort();
绑定netty监听端口
if (this.channelEventListener != null) {
this.nettyEventExecuter.start();
}
启动netty事件处理线程
2,当有请求连接的时候,步骤如下
2.1,public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
final String remoteAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel());
log.info("NETTY SERVER PIPELINE: channelRegistered {}", remoteAddress);
super.channelRegistered(ctx);
}
channel注册
2.2,public void channelActive(ChannelHandlerContext ctx) throws Exception {
final String remoteAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel());
log.info("NETTY SERVER PIPELINE: channelActive, the channel[{}]", remoteAddress);
super.channelActive(ctx);
if (NettyRemotingServer.this.channelEventListener != null) {
NettyRemotingServer.this.putNettyEvent(new NettyEvent(NettyEventType.CONNECT, remoteAddress
.toString(), ctx.channel()));
}
}
channel激活后放入连接事件到NettyEventExecuter.LinkedBlockingQueue
NettyEvent event = this.eventQueue.poll(3000, TimeUnit.MILLISECONDS);
switch (event.getType()) {
case IDLE:当空闲链路达到serverChannelMaxIdleTimeSeconds(默认120秒)会触发这个事件处理.
listener.onChannelIdle(event.getRemoteAddr(), event.getChannel());
break;
this.brokerController.getProducerManager().doChannelCloseEvent(remoteAddr, channel);
this.brokerController.getConsumerManager().doChannelCloseEvent(remoteAddr, channel);
this.brokerController.getFilterServerManager().doChannelCloseEvent(remoteAddr, channel);
通知producer,consumer,filterServer移除channel
case CLOSE:当channel关闭的时候会触发这个事件处理.
listener.onChannelClose(event.getRemoteAddr(), event.getChannel());
break;
this.brokerController.getProducerManager().doChannelCloseEvent(remoteAddr, channel);
this.brokerController.getConsumerManager().doChannelCloseEvent(remoteAddr, channel);
this.brokerController.getFilterServerManager().doChannelCloseEvent(remoteAddr, channel);
通知producer,consumer,filterServer移除channel
case CONNECT:当有新连接的时候会触发这个事件处理.
listener.onChannelConnect(event.getRemoteAddr(), event.getChannel());
break;
case EXCEPTION:当channel发生异常的时候会发生这个事件处理.
listener.onChannelException(event.getRemoteAddr(), event.getChannel());
break;
this.brokerController.getProducerManager().doChannelCloseEvent(remoteAddr, channel);
this.brokerController.getConsumerManager().doChannelCloseEvent(remoteAddr, channel);
this.brokerController.getFilterServerManager().doChannelCloseEvent(remoteAddr, channel);
通知producer,consumer,filterServer移除channel
2.3,this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
ClientHousekeepingService.this.scanExceptionChannel();
this.brokerController.getProducerManager().scanNotActiveChannel();
this.brokerController.getConsumerManager().scanNotActiveChannel();
this.brokerController.getFilterServerManager().scanNotActiveChannel();
通知producer,consumer,filterServer移除未活动,过期channel
}
catch (Exception e) {
log.error("", e);
}
}
}, 1000 * 10, 1000 * 10, TimeUnit.MILLISECONDS);
3,NettyDecoder.decode 解码
ByteBuf frame = null;
try {
frame = (ByteBuf) super.decode(ctx, in);
if (null == frame) {
return null;
}
ByteBuffer byteBuffer = frame.nioBuffer();
return RemotingCommand.decode(byteBuffer);
解码为remotingCommand对象,实现如下:
int length = byteBuffer.limit();获取总length
int headerLength = byteBuffer.getInt();
byte[] headerData = new byte[headerLength];
byteBuffer.get(headerData);获取header数据
int bodyLength = length - 4 - headerLength;body总length
byte[] bodyData = null;
if (bodyLength > 0) {
bodyData = new byte[bodyLength];
byteBuffer.get(bodyData);获取body数据
}
RemotingCommand cmd = RemotingSerializable.decode(headerData, RemotingCommand.class);
内部实现用fastJson序列化为RemotingCommand
cmd.body = bodyData;
return cmd;
4,NettyServerHandler.channelRead0 反序列化后处理过程
final RemotingCommand cmd = msg;
if (cmd != null) {
switch (cmd.getType()) { 根据command type判断是请求
case REQUEST_COMMAND:
proce***equestCommand(ctx, cmd);
break;
case RESPONSE_COMMAND:
proce***esponseCommand(ctx, cmd);
break;
default:
break;
}
}