【JAVA 网络编程系列】Netty -- Netty 服务接受连接处理分析
【1】ServerBootstrapAcceptor 类型 ChannelHandler 加入 Pipeline
public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerChannel> {
@Override
void init(Channel channel) throws Exception {
...
p.addLast(new ChannelInitializer<Channel>() {
@Override
public void initChannel(final Channel ch) throws Exception {
...
// 这样调用可以启动一个主循环并在启动完毕后执行Runnable任务
// 此处实现了将ServerBootstrapAcceptor类ChannelHandler加入到ChannelPipeline中
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
pipeline.addLast(new ServerBootstrapAcceptor(
ch, currentChildGroup, currentChildHandler
, currentChildOptions, currentChildAttrs));
}
});
...
}
});
...
}
}
ch.eventLoop().execute 的处理过程详见 【JAVA 网络编程系列】Netty -- ch.eventLoop().execute分析
【2】主循环中处理 Accept 事件
public final class NioEventLoop extends SingleThreadEventLoop {
private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe();
...
try {
// 检索此键的就绪操作集
int readyOps = k.readyOps();
...
// 处理 Read / Accept 事件
if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
unsafe.read();
}
} catch (CancelledKeyException ignored) {
// 处理异常
unsafe.close(unsafe.voidPromise());
}
}
}
【3】Accept 事件的处理流程
【3.1】处理连接请求时的 unsafe 继承结构
针对 NioServerSocketChannel 其 unsafe 对应的是 NioMessageUnsafe 类;
【3.2】NioMessageUnsafe -- public void read() 方法
public abstract class AbstractNioMessageChannel extends AbstractNioChannel {
private final class NioMessageUnsafe extends AbstractNioUnsafe {
private final List<Object> readBuf = new ArrayList<Object>();
@Override
public void read() {
assert eventLoop().inEventLoop();
// 获取 ServerSocketChannel 中的 ChannelConfig 实例
final ChannelConfig config = config();
// 获取 ServerSocketChannel 中的 ChannelPipeline 实例
final ChannelPipeline pipeline = pipeline();
// 初始化内存分配器
final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
// 重置已累积的所有计数器,并建议下一个读取循环应读取多少消息/字节
allocHandle.reset(config);
boolean closed = false;
Throwable exception = null;
try {
try {
do {
// 读取消息,doReadMessages 为抽象方法由子类覆写
// protected abstract int doReadMessages(List<Object> buf) throws Exception;
int localRead = doReadMessages(readBuf);
if (localRead == 0) {
break;
}
if (localRead < 0) {
closed = true;
break;
}
// Increment the number of messages that have been read for the current read loop
// 增加当前读取循环已读取的消息数
allocHandle.incMessagesRead(localRead);
// Determine if the current read loop should should continue
// 确定当前读取循环是否应继续
} while (allocHandle.continueReading());
} catch (Throwable t) {
// 处理异常
exception = t;
}
int size = readBuf.size();
for (int i = 0; i < size; i ++) {
readPending = false;
// 触发 ChannelHandler 的 channelRead() 方法
// 此处 pipeline 实际上是 NioServerSocketChannel 对应的 ChannelPipeline
// 服务启动完成后则该 ChannelPipeline 中的双向链表为
// head<=>LoggingHandler<=>ServerBootstrapAcceptor<=>tail
// 其中 ServerBootstrapAcceptor 这个 ChannelHandler 会往子 ChannelPipeline 中
添加子 ChannelHandler
pipeline.fireChannelRead(readBuf.get(i));
}
// 清空 Buffer
readBuf.clear();
// The read has completed
// 标记读取已完成
allocHandle.readComplete();
// 触发 ChannelHandler 的 channelReadComplete() 方法
pipeline.fireChannelReadComplete();
// 处理异常
if (exception != null) {
// 即使发生IOException也不应关闭ServerChannel,因为它通常可以继续接受传入的连接
closed = closeOnReadError(exception);
// 触发 ChannelHandler 的 exceptionCaught() 方法
pipeline.fireExceptionCaught(exception);
}
// 若需要关闭则关闭Channel
if (closed) {
inputShutdown = true;
if (isOpen()) {
close(voidPromise());
}
}
} finally {
// 当没有未读信息并且Channel不是AutoRead的
if (!readPending && !config.isAutoRead()) {
// 移除与读相关的兴趣事件集
removeReadOp();
}
}
}
}
}
【3.3】NioServerSocketChannel -- protected int doReadMessages(List<Object> buf) throws Exception
public class NioServerSocketChannel extends AbstractNioMessageChannel
implements io.netty.channel.socket.ServerSocketChannel {
@Override
protected int doReadMessages(List<Object> buf) throws Exception {
// JAVA 原生方法接受连接
SocketChannel ch = SocketUtils.accept(javaChannel());
try {
if (ch != null) {
// 构造了一个Netty的NioSocketChannel并把Java原生SocketChannel传入
// 此时创建了一个 NioSocketChannel
// 此时该 NioSocketChannel 实例的 pipeline 中还是只有 head 和 tail 两个 Handler,还无法处理消息
buf.add(new NioSocketChannel(this, ch));
return 1;
}
} catch (Throwable t) {
// 处理异常,发生异常后会关闭 Channel
logger.warn("Failed to create a new channel from an accepted socket.", t);
try {
ch.close();
} catch (Throwable t2) {
logger.warn("Failed to close a socket.", t2);
}
}
return 0;
}
}
public final class SocketUtils {
public static SocketChannel accept(final ServerSocketChannel serverSocketChannel) throws IOException {
try {
// 调用Java原生的aacept()方法创建一个SocketChannel
// Netty 最终还是调用的 Java 原生的 SeverSocketChannel 的 accept () 方法来创建一个 SocketChannel,
// 并把这个 SocketChannel 绑定到 Netty 自己的 NioSocketChannel 中
return AccessController.doPrivileged((PrivilegedExceptionAction<SocketChannel>)
() -> serverSocketChannel.accept());
} catch (PrivilegedActionException e) {
throw (IOException) e.getCause();
}
}
}
【3.4】ServerBootstrapAcceptor 类中的处理逻辑
public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerChannel> {
private static class ServerBootstrapAcceptor extends ChannelInboundHandlerAdapter {
@Override
@SuppressWarnings("unchecked")
public void channelRead(ChannelHandlerContext ctx, Object msg) {
// msg 为 Channel 类型的变量
// 此处的msg即为readBuf.get(i),即NioSocketChannel,也就是子Channel
// 见 AbstractNioMessageChannel 类中
// public void read() 方法中的调用 pipeline.fireChannelRead(readBuf.get(i));
final Channel child = (Channel) msg;
// 添加子ChannelHandler此处同样是以ChannelInitializer的形式添加的
child.pipeline().addLast(childHandler);
// 设置子Channel的配置等信息
// 将 childOptions 设置到 Channel 中
setChannelOptions(child, childOptions, logger);
// 将 childAttrs 设置到 Channel 中
for (Entry<AttributeKey<?>, Object> e: childAttrs) {
child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
}
try {
// 将子Channel注册到workerGroup中的一个EventLoop上
childGroup.register(child).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
// 关闭该Channel
forceClose(child, future.cause());
}
}
});
} catch (Throwable t) {
// 关闭该Channel
forceClose(child, t);
}
}
}
}
【3.5】子 Channel 的注册逻辑
public abstract class SingleThreadEventLoop extends SingleThreadEventExecutor implements EventLoop {
@Override
public ChannelFuture register(Channel channel) {
// 创建一个默认的 ChannelPromise 类实例
return register(new DefaultChannelPromise(channel, this));
}
@Override
public ChannelFuture register(final ChannelPromise promise) {
ObjectUtil.checkNotNull(promise, "promise");
// 调用的是channel的unsafe的register()方法
// 调用 io.netty.channel.AbstractChannel.AbstractUnsafe
// public final void register(EventLoop eventLoop, final ChannelPromise promise) 方法
// 此后的流程与 initAndRegister() 方法中的逻辑一致
promise.channel().unsafe().register(this, promise);
return promise;
}
}
参考致谢
本博客为博主学习笔记,同时参考了网上众博主的博文以及相关专业书籍,在此表示感谢,本文若存在不足之处,请批评指正。
【1】慕课专栏,网络编程之Netty一站式精讲
【2】极客时间,Netty源码剖析与实战