希望看完这篇文章后,会 哦~~ 原来就个这呀~~~
1. 引导服务配置
下面给出常规的服务端netty 服务创建源码,并由此进行分析;
public class Registry {
private int port;
public Registry(int port){
this.port = port;
}
public static void main(String[] args) {
new Registry(8080).start();
}
/**
*
*/
private void start() {
// Reactor模型,Boss,work
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
// NioEventLoopGroup workGroup = new NioEventLoopGroup();
// Netty服务,ServerSocketChannel
ServerBootstrap bootServer = new ServerBootstrap();
bootServer.group(bossGroup)
// 主线程所用Channel定义
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
// 子线程处理类,Handler
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel client) throws Exception {
// 自定义协议解码器
client.pipeline()
// add 长度域解码器 ChannelInboundHandler
.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4))
// add ChannelOutboundHandler
.addLast(new LengthFieldPrepender(4))
// add 编码器
.addLast(new ObjectEncoder())
// add 解码器
.addLast(new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)))
// add 业务处理 ChannelInboundHandler
.addLast(new RegisterHandler())
;
}
})
// .option(ChannelOption.SO_BACKLOG,128)
.childOption(ChannelOption.SO_KEEPALIVE,true);
try {
ChannelFuture future = bootServer.bind(port).sync();
System.out.println(" LPH RPC Register start listen at " + port);
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
bossGroup.shutdownGracefully();
//workGroup.shutdownGracefully();
}
}
}
// Reactor模型,Boss,work
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
1.1. NioEventLoopGroup()
NioEventLoopGroup
/**
* 🍓
*/
public NioEventLoopGroup() {
this(0);
}
/**
*
*/
public NioEventLoopGroup(int nThreads) {
this(nThreads, (Executor) null);
}
public NioEventLoopGroup(int nThreads, Executor executor) {
this(nThreads, executor, SelectorProvider.provider());
}
public NioEventLoopGroup(
int nThreads, Executor executor, final SelectorProvider selectorProvider) {
this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE);
}
public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider,
final SelectStrategyFactory selectStrategyFactory) {
super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());
}
MultithreadEventExecutorGroup
/**
* 创建NIOEventLoop 实例
*/
protected MultithreadEventExecutorGroup(int nThreads, ThreadFactory threadFactory, Object... args) {
this(nThreads, threadFactory == null ? null : new ThreadPerTaskExecutor(threadFactory), args);
}
protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args);
}
/**
* Create a new instance.
*
* @param nThreads 此实例将使用的线程数。
* @param executor 要使用的执行器,null 的话使用默认的
* @param chooserFactory 执行器选择器工厂🏭
* @param args 透传给 newChild 使用的参数
*/
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
// ...
if (executor == null) {// 定义一个执行器,每次调用execute 时,传入执行体,工厂创建一个线程并执行
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}
// 定义chilren 事件执行器数组
children = new EventExecutor[nThreads];
// chilren 数组内容填充
for (int i = 0; i < nThreads; i ++) {
boolean success = false;
try {
children[i] = newChild(executor, args);
success = true;
} catch (Exception e) {
// ...
} finally {
// ...
}
}
// 创建选择器工厂
chooser = chooserFactory.newChooser(children);
// 对结果添加监听,暂不分析
final FutureListener<Object> terminationListener = new FutureListener<Object>() {
@Override
public void operationComplete(Future<Object> future) throws Exception {
if (terminatedChildren.incrementAndGet() == children.length) {
terminationFuture.setSuccess(null);
}
}
};
for (EventExecutor e: children) {
e.terminationFuture().addListener(terminationListener);
}
// 定义一个仅读的chilren 数组
Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
Collections.addAll(childrenSet, children);
readonlyChildren = Collections.unmodifiableSet(childrenSet);
}
1.1.2 newChild()
DefaultEventExecutorGroup#newChild
@Override
protected EventExecutor newChild(Executor executor, Object... args) throws Exception {
return new DefaultEventExecutor(this, executor, (Integer) args[0], (RejectedExecutionHandler) args[1]);
}
DefaultEventExecutor#DefaultEventExecutor
public DefaultEventExecutor(EventExecutorGroup parent, Executor executor, int maxPendingTasks,
RejectedExecutionHandler rejectedExecutionHandler) {
super(parent, executor, true, maxPendingTasks, rejectedExecutionHandler);
}
SingleThreadEventExecutor#SingleThreadEventExecutor
/**
* Create a new instance
*
* @param parent EventExecutorGroup是这个实例的父类,并且属于它
* @param executor 用于执行的执行器
* @param addTaskWakesUp 当且仅当addTask(Runnable)调用被唤醒时为true
* @param maxPendingTasks 创建新任务之前的最大挂起任务数
* @param rejectedHandler 拒绝策略
*/
protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
boolean addTaskWakesUp, int maxPendingTasks,
RejectedExecutionHandler rejectedHandler) {
super(parent);
this.addTaskWakesUp = addTaskWakesUp;
this.maxPendingTasks = Math.max(16, maxPendingTasks);
this.executor = ThreadExecutorMap.apply(executor, this);
taskQueue = newTaskQueue(this.maxPendingTasks);
rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
}
// 这行是生成一个 事件执行器选择器工厂;
// 偶数用:PowerOfTwoEventExecutorChooser (位运算) ,奇数用: GenericEventExecutorChooser (取余)
1.1.3 chooserFactory.newChooser();
public final class DefaultEventExecutorChooserFactory implements EventExecutorChooserFactory {
public static final DefaultEventExecutorChooserFactory INSTANCE = new DefaultEventExecutorChooserFactory();
private DefaultEventExecutorChooserFactory() { }
@Override
public EventExecutorChooser newChooser(EventExecutor[] executors) {
if (isPowerOfTwo(executors.length)) {
return new PowerOfTwoEventExecutorChooser(executors);
} else {
return new GenericEventExecutorChooser(executors);
}
}
private static final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser {
private final AtomicInteger idx = new AtomicInteger();
private final EventExecutor[] executors;
PowerOfTwoEventExecutorChooser(EventExecutor[] executors) {
this.executors = executors;
}
@Override
public EventExecutor next() {
return executors[idx.getAndIncrement() & executors.length - 1];
}
}
private static final class GenericEventExecutorChooser implements EventExecutorChooser {
private final AtomicLong idx = new AtomicLong();
private final EventExecutor[] executors;
GenericEventExecutorChooser(EventExecutor[] executors) {
this.executors = executors;
}
@Override
public EventExecutor next() {
return executors[(int) Math.abs(idx.getAndIncrement() % executors.length)];
}
}
1.2. channel()
/**
* 用来创建Channel实例的类。如果你的Channel实现没有无参数的构造函数,
* 你可以使用这个或者使用channelFactory(io.nety.channel . channelFactory)。
*/
public B channel(Class<? extends C> channelClass) {
return channelFactory(new ReflectiveChannelFactory<C>(
ObjectUtil.checkNotNull(channelClass, "channelClass")
));
}
/**
* @deprecated Use {@link #channelFactory(io.netty.channel.ChannelFactory)} instead.
*/
@Deprecated
public B channelFactory(ChannelFactory<? extends C> channelFactory) {
ObjectUtil.checkNotNull(channelFactory, "channelFactory");
if (this.channelFactory != null) {
throw new IllegalStateException("channelFactory set already");
}
this.channelFactory = channelFactory;
return self();
}
ObjectUtil.checkNotNull(channelFactory, "channelFactory");
这行,看着比较迷惑,实际也比较简单,就是检查传入的对象是否为null,null 的话跑出 text NPE;
注: 不要畏惧,干就完了(😁)
/**
* 检查给定的参数是否为空。如果是,抛出NullPointerException。否则,返回参数。
*/
public static <T> T checkNotNull(T arg, String text) {
if (arg == null) {
throw new NullPointerException(text);
}
return arg;
}
new ReflectiveChannelFactory(ObjectUtil.checkNotNull(channelClass, "channelClass"))
行看着也比较迷惑,我们看一下具体实现,😄就一简单的反射实现创建对象的工厂🏭;
public class ReflectiveChannelFactory<T extends Channel> implements ChannelFactory<T> {
private final Constructor<? extends T> constructor;
public ReflectiveChannelFactory(Class<? extends T> clazz) {
ObjectUtil.checkNotNull(clazz, "clazz");
try {
this.constructor = clazz.getConstructor();
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("Class " + StringUtil.simpleClassName(clazz) +
" does not have a public non-arg constructor", e);
}
}
@Override
public T newChannel() {
try {
return constructor.newInstance();
} catch (Throwable t) {
throw new ChannelException("Unable to create Channel from class " + constructor.getDeclaringClass(), t);
}
}
@Override
public String toString() {
return StringUtil.simpleClassName(ReflectiveChannelFactory.class) +
'(' + StringUtil.simpleClassName(constructor.getDeclaringClass()) + ".class)";
}
}
1.3. childHandler()
设置用于为Channel的请求提供服务的ChannelHandler。
public ServerBootstrap childHandler(ChannelHandler childHandler) {
this.childHandler = ObjectUtil.checkNotNull(childHandler, "childHandler");
return this;
}
1.4. childOption();
允许指定一个ChannelOption,当Channel实例被创建时(在acceptor接受Channel之后),这个选项会被使用。使用null值删除先前设置的ChannelOption。
public <T> ServerBootstrap childOption(ChannelOption<T> childOption, T value) {
ObjectUtil.checkNotNull(childOption, "childOption");
synchronized (childOptions) {
if (value == null) {
childOptions.remove(childOption);
} else {
childOptions.put(childOption, value);
}
}
return this;
}
2. 引导服务启动
ChannelFuture future = bootServer.bind(port).sync();
2.1 bind()
// 根据传入的端口号,生成Socket地址,并绑定
public ChannelFuture bind(int inetPort) {
return bind(new InetSocketAddress(inetPort));
}
// 1) group channelFactory 非null校验, group = new NioEventGroup() 已定义,channelFactory = .channel(NioServerSocketChannel.class)后封装的Factory
// 2) 调用doBind()
public ChannelFuture bind(SocketAddress localAddress) {
validate();
return doBind(ObjectUtil.checkNotNull(localAddress, "localAddress"));
}
private ChannelFuture doBind(final SocketAddress localAddress) {
final ChannelFuture regFuture = initAndRegister();
final Channel channel = regFuture.channel();
if (regFuture.cause() != null) {
return regFuture;
}
if (regFuture.isDone()) {
// At this point we know that the registration was complete and successful.
ChannelPromise promise = channel.newPromise();
doBind0(regFuture, channel, localAddress, promise);
return promise;
} else {
// Registration future is almost always fulfilled already, but just in case it's not.
final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
regFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
Throwable cause = future.cause();
if (cause != null) {
// Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an
// IllegalStateException once we try to access the EventLoop of the Channel.
promise.setFailure(cause);
} else {
// Registration was successful, so set the correct executor to use.
// See https://github.com/netty/netty/issues/2586
promise.registered();
doBind0(regFuture, channel, localAddress, promise);
}
}
});
return promise;
}
}
2.2 initAndRegister()
AbstractBootstrap
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
channel = channelFactory.newChannel();
init(channel);
} catch (Throwable t) {
// ...
}
ChannelFuture regFuture = config().group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}
return regFuture;
}
NioServerSocketChannel()
NioServerSocketChannel
public NioServerSocketChannel() {
this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}
public NioServerSocketChannel(ServerSocketChannel channel) {
super(null, channel, SelectionKey.OP_ACCEPT);
config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}
AbstractNioMessageChannel
public abstract class AbstractNioMessageChannel extends AbstractNioChannel {
protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent, ch, readInterestOp);
}
AbstractNioChannel
/**
*
* 通道实现的抽象基类,使用基于选择器的方法。
*/
public abstract class AbstractNioChannel extends AbstractChannel {
/**
* 创建一个NioChannel 示例
*
* @param parent 创建实例的父通道。可能是null
* @param ch 它操作的基础selectablecchannel
* @param readInterestOp 设置从selectablecchannel接收数据的操作,这里操作是SelectionKey.OP_ACCEPT
*/
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent);
this.ch = ch;
this.readInterestOp = readInterestOp;
try {
ch.configureBlocking(false);
} catch (IOException e) {
// ...
}
}
AbstractChannel
/**
* 一个Channel的骨架实现
*/
public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
// ...
// 创建一个新示例;
// parent : 改通道的父节点,如果没有父节点则为null, 当前分析链路 为null
protected AbstractChannel(Channel parent) {
this.parent = parent;
id = newId();
unsafe = newUnsafe();
pipeline = newChannelPipeline();
}
/**
* 返回一个默认的 Channel 管道
*/
protected DefaultChannelPipeline newChannelPipeline() {
return new DefaultChannelPipeline(this);
}
DefaultChannelPipeline
public class DefaultChannelPipeline implements ChannelPipeline {
protected DefaultChannelPipeline(Channel channel) {
this.channel = ObjectUtil.checkNotNull(channel, "channel");
// 定义成功之后的 回调Channel
succeededFuture = new SucceededChannelFuture(channel, null);
//
voidPromise = new VoidChannelPromise(channel, true);
tail = new TailContext(this);
head = new HeadContext(this);
head.next = tail;
tail.prev = head;
}
final class HeadContext extends AbstractChannelHandlerContext
implements ChannelOutboundHandler, ChannelInboundHandl
private final Unsafe uns
HeadContext(DefaultChannelPipeline pipeline) {
super(pipeline, null, HEAD_NAME, HeadContext.class);
unsafe = pipeline.channel().unsafe();
setAddComplete();
}
// 同时处理字节和消息的特殊的万能处理程序。
final class TailContext extends AbstractChannelHandlerContext
implements ChannelInboundHandler
TailContext(DefaultChannelPipeline pipeline) {
super(pipeline, null, TAIL_NAME, TailContext.class);
setAddComplete();
}
回归主线
initAndRegister
ServerBootstrap#initAndRegister
@Override
void init(Channel channel) {
ChannelPipeline p = channel.pipeline();
p.addLast(new ChannelInitializer<Channel>() {
@Override
public void initChannel(final Channel ch) {
final ChannelPipeline pipeline = ch.pipeline();
ChannelHandler handler = config.handler();
if (handler != null) {
pipeline.addLast(handler);
}
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
pipeline.addLast(new ServerBootstrapAcceptor(
ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}
});
}
// 这里我们进入 addLast方法;
addLast()
DefaultChannelPipeline
@Override
public final ChannelPipeline addLast(EventExecutorGroup executor, ChannelHandler... handlers) {
ObjectUtil.checkNotNull(handlers, "handlers");
for (ChannelHandler h: handlers) {
if (h == null) {
break;
}
addLast(executor, null, h);
}
return this;
}
@Override
public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
final AbstractChannelHandlerContext newCtx;
synchronized (this) {
// 校验此handler 是否已添加过
checkMultiplicity(handler);
// 构建 ChannelHandlerContext
newCtx = newContext(group, filterName(name, handler), handler);
// 将我们自定义的 hanlder 插入到(队尾?) ,
// 实际上是 header --> 自定义处理handler --> tail
addLast0(newCtx);
if (!registered) {
// 首次走这里,待补充。。。
newCtx.setAddPending();
callHandlerCallbackLater(newCtx, true);
return this;
}
EventExecutor executor = newCtx.executor();
if (!executor.inEventLoop()) {
callHandlerAddedInEventLoop(newCtx, executor);
return this;
}
}
callHandlerAdded0(newCtx);
return this;
}
private void addLast0(AbstractChannelHandlerContext newCtx) {
AbstractChannelHandlerContext prev = tail.prev;
newCtx.prev = prev;
newCtx.next = tail;
prev.next = newCtx;
tail.prev = newCtx;
}
register()
这里直接跳转会主线 io.netty.bootstrap.AbstractBootstrap#initAndRegister
ChannelFuture regFuture = config().group().register(channel);
SingleThreadEventLoop
@Override
public ChannelFuture register(Channel channel) {
return register(new DefaultChannelPromise(channel, this));
}
@Override
public ChannelFuture register(final ChannelPromise promise) {
ObjectUtil.checkNotNull(promise, "promise");
promise.channel().unsafe().register(this, promise);
return promise;
}
register()
AbstractChannel
@Override
public final void register(EventLoop eventLoop, final ChannelPromise promise) {
ObjectUtil.checkNotNull(eventLoop, "eventLoop");
if (isRegistered()) {
promise.setFailure(new IllegalStateException("registered to an event loop already"));
return;
}
if (!isCompatible(eventLoop)) {
promise.setFailure(
new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName()));
return;
}
AbstractChannel.this.eventLoop = eventLoop;
if (eventLoop.inEventLoop()) {
register0(promise);
} else { // 注意 我们整体串的是主线程,so 当前线程不在事件循环中,走else 逻辑
try {
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
} catch (Throwable t) {
// ...
}
}
}
private void register0(ChannelPromise promise) {
try {
// 检查通道是否仍然打开,因为当寄存器调用在eventLoop之外时,它可能会同时关闭
if (!promise.setUncancellable() || !ensureOpen(promise)) {
return;
}
boolean firstRegistration = neverRegistered;
doRegister();
neverRegistered = false;
registered = true;
// 确保我们在实际通知promise之前调用了handlerAdded(…)。这是需要的,因为用户可能已经通过ChannelFutureListener中的管道触发了事件。
pipeline.invokeHandlerAddedIfNeeded();
safeSetSuccess(promise);
//
pipeline.fireChannelRegistered();
// 只有在通道从未注册时才触发一个channelActive。这将防止在通道注销和重新注册时触发多个通道活动。
if (isActive()) {
if (firstRegistration) {
pipeline.fireChannelActive();
} else if (config().isAutoRead()) {
// 这个通道在之前注册过,并且设置了autoRead()。这意味着我们需要再次开始读取,以便处理入站数据。
// 参见https://github.com/netty/netty/issues/4805
beginRead();
}
}
} catch (Throwable t) {
// 直接关闭通道,避免FD泄漏。
closeForcibly();
closeFuture.setClosed();
safeSetFailure(promise, t);
}
}
doRegister()
AbstractNioChannel
@Override
protected void doRegister() throws Exception {
boolean selected = false;
for (;;) {
try {
// 把Channel 注册到 Selector 上,这里直接关联的是原生 Selector ,和原生 Channel
selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
return;
} catch (CancelledKeyException e) {
if (!selected) {
// 强制选择器现在选择,因为“取消”的SelectionKey可能仍然被缓存,没有删除,因为还没有调用select .select(..)操作。
eventLoop().selectNow();
selected = true;
} else {
// 我们之前在选择器上强制了一个选择操作,但是由于某种原因,SelectionKey仍然被缓存。JDK错误?
throw e;
}
}
}
}
@Override
public ChannelHandlerContext fireChannelRegistered() {
invokeChannelRegistered(findContextInbound(MASK_CHANNEL_REGISTERED));
return this;
}
private AbstractChannelHandlerContext findContextOutbound(int mask) {
AbstractChannelHandlerContext ctx = this;
EventExecutor currentExecutor = executor();
do {
ctx = ctx.prev;
} while (skipContext(ctx, currentExecutor, mask, MASK_ONLY_OUTBOUND));
return ctx;
}
private static boolean skipContext(
AbstractChannelHandlerContext ctx, EventExecutor currentExecutor, int mask, int onlyMask) {
// 确保我们正确地处理MASK_EXCEPTION_CAUGHT,它不包含在MASK_EXCEPTION_CAUGHT中
return (ctx.executionMask & (onlyMask | mask)) == 0 ||
// We can only skip if the EventExecutor is the same as otherwise we need to ensure we offload
// everything to preserve ordering.
//
// See https://github.com/netty/netty/issues/10067
(ctx.executor() == currentExecutor && (ctx.executionMask & mask) == 0);
}
mask MASK_CHANNEL_REGISTERED : 0000-0000-0000-0010
only Mask MASK_ONLY_INBOUND : 0000-0001-1111-1110
① onlyMask | mask = 0000-0001-1111-1110 即 mask
so ctx.executionMask & (onlyMask | mask)) == 0 等价与②
加入此判断,仅是在异常状态下的兼容处理;分析逻辑时,可以忽略;
② ctx.executionMask & mask ==0, 说明 第二位 为 0 ,即不包含 mask ,跳过
3. 接受用户请求
服务端启动后,最终会注册一个Accept 事件等待客户端的链接;
可以参考2中的分析,核心注册逻辑如下:
@Override
void init(Channel channel) {
ChannelPipeline p = channel.pipeline();
p.addLast(new ChannelInitializer<Channel>() {
@Override
public void initChannel(final Channel ch) {
final ChannelPipeline pipeline = ch.pipeline();
ChannelHandler handler = config.handler();
if (handler != null) {
pipeline.addLast(handler);
}
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
pipeline.addLast(new ServerBootstrapAcceptor(
ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}
});
}
NioServerSocketChannel 将自己注册到 Selector 上,通过run() 方法,不断的获取处理相应的 事件;
@Override
protected void run() {
for (;;) {
try {
switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
case SelectStrategy.CONTINUE:
continue;
case SelectStrategy.SELECT:
select(wakenUp.getAndSet(false));
if (wakenUp.get()) {
selector.wakeup();
}
default:
}
cancelledKeys = 0;
needsToSelectAgain = false;
final int ioRatio = this.ioRatio;
if (ioRatio == 100) {
try {
processSelectedKeys();
} finally {
// Ensure we always run tasks.
runAllTasks();
}
} else {
final long ioStartTime = System.nanoTime();
try {
processSelectedKeys();
} finally {
// Ensure we always run tasks.
final long ioTime = System.nanoTime() - ioStartTime;
runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
}
}
} catch (Throwable t) {
handleLoopException(t);
}
}
}
EventLoop 是一个死循环,在这个循环中做了3件事情:
1)有条件的等待NIO 事件;
2)处理NIO事件;
3)处理消息队列中的任务;
调用链如下:
private void processSelectedKeys() {
if (selectedKeys != null) {
processSelectedKeysOptimized();
} else {
processSelectedKeysPlain(selector.selectedKeys());
}
}
private void processSelectedKeysPlain(Set<SelectionKey> selectedKeys) {
// ...
for (;;) {
final SelectionKey k = i.next();
final Object a = k.attachment();
i.remove();
if (a instanceof AbstractNioChannel) {
processSelectedKey(k, (AbstractNioChannel) a);
} else {
@SuppressWarnings("unchecked")
NioTask<SelectableChannel> task = (NioTask<SelectableChannel>) a;
processSelectedKey(k, task);
}
// ...
}
}
private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
// ...
try {
// ...
if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
unsafe.read();
}
} catch (CancelledKeyException ignored) {
unsafe.close(unsafe.voidPromise());
}
}
这里的 unsafe 是 bossGroup 线程中 NioServerSocketChannel 的AbstractNioMessageChannel$NioMessageUnsafe 类型的对象。我们进入到其read()方法中:
@Override
public void read() {
assert eventLoop().inEventLoop();
final ChannelConfig config = config();
final ChannelPipeline pipeline = pipeline();
final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
allocHandle.reset(config);
boolean closed = false;
Throwable exception = null;
try {
try {
do {
int localRead = doReadMessages(readBuf);
if (localRead == 0) {
break;
}
if (localRead < 0) {
closed = true;
break;
}
allocHandle.incMessagesRead(localRead);
} while (allocHandle.continueReading());
} catch (Throwable t) {
exception = t;
}
int size = readBuf.size();
for (int i = 0; i < size; i ++) {
readPending = false;
pipeline.fireChannelRead(readBuf.get(i));
}
readBuf.clear();
allocHandle.readComplete();
pipeline.fireChannelReadComplete();
// ...
}
}
doReadMessages(readBuf) 方法,其中的变量 readBuf 是一个List,也就是一个容器,该方法的作用是读取 bossGroup 线程中的 NioServerSocketChannel 接收到的请求,并把这些请求放进容器:
@Override
protected int doReadMessages(List<Object> buf) throws Exception {
SocketChannel ch = SocketUtils.accept(javaChannel());
try {
if (ch != null) {
buf.add(new NioSocketChannel(this, ch));
return 1;
}
} catch (Throwable t) {
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;
}
说明:该方法是通过 ServerSocket 的accept()方法获取到一个TCP连接,然后将其封装为Netty的NioSocketChannel对象,最后添加到容器中;
public static SocketChannel accept(final ServerSocketChannel serverSocketChannel) throws IOException {
try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<SocketChannel>() {
@Override
public SocketChannel run() throws IOException {
return serverSocketChannel.accept();
}
});
} catch (PrivilegedActionException e) {
throw (IOException) e.getCause();
}
}
循环 readBuf 这个容器中的所有请求,执行 pipeline.fireChannelRead(readBuf.get(i))
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.handler(new LoggingHandler(LogLevel.INFO))// 将会在每次客户端连接时调用
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
if (sslCtx != null) {
p.addLast(sslCtx.newHandler(ch.alloc()));
}
//p.addLast(new LoggingHandler(LogLevel.INFO));// 将会在每次客户端有事件发生时调用
p.addLast(new EchoServerHandler());
}
});
handler() : 在每次有客户端连接时会调用
childHandler() :在客户端连接建立成功之后有读写等操作时触发。
服务端的代码中,我们仅显示的注册了LoggingHandler, 但netty 会自动的帮我们 注入 Head、LoggingHandler、ServerBootstrapAcceptor、Tail。
这里我们着重看 ServerBootstrapAcceptor,因为它 起到中转的作用,接受用户端的请求,并将链接
转到workGroup, 同时为 每个SocketChannel 注册我们在childHandler() 方法中指定的handler ;
public void channelRead(ChannelHandlerContext ctx, Object msg) {
// ① 将msg 强转为 Channel ,实际上是 NioSocketChannel
final Channel child = (Channel) msg;
// ② 为child 的pepeline 添加自定义的 handler
child.pipeline().addLast(childHandler);
// ③ 设置NioSocketChannel 的各种属性
setChannelOptions(child, childOptions, logger);
for (Entry<AttributeKey<?>, Object> e: childAttrs) {
child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
}
try {
// ④ 将客户端连接注册到workerGroup的线程池中
childGroup.register(child)
.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
forceClose(child, future.cause());
}
}
});
} catch (Throwable t) {
forceClose(child, t);
}
}
至此,针对客户端的连接就完成了,接下来可以监听事件了;
整体流程如下:
- 1)服务端启动时 创建的NioEventLoop 对象 会通过死循环的方式轮询监听有没有新的连接过来;
- 2)监听到有新的连接过来(即 Accept 事件)时,就会创建一个NioSocketChannel ,并将其置于一个容器中;
- 3)遍历上述容器,执行 fireChannelRead() 方法,使每一个新进来的客户端连接都经过我们在handler() 方法中指定的handler的处理(即执行这些handler 的channelRead() 方法),需要特别注意的是,netty 会隐式的为我们注册Head、ServerBootstrapAcceptor、Tail 这三个handler, 因此也会执行这三个handler 的channelRead() 方法;
- 4)在执行ServerBootstrapAcceptor 的channelRead() 方法时,会将2)中创建的NioSocketChannel转交给workerGroup( 将其注册到workGroup 中的EventLoop 中,监听读写等事件),同时为这些NioSocketChannel 绑定我们在 childHandler() 中指定的handler;