在EventLoopGroup执行期间:
DefaultThreadFactory$DefaultRunnableDecorator.run()
private static final class DefaultRunnableDecorator implements Runnable
{
private final Runnable r;
//与Apache mina一样,包装线程
DefaultRunnableDecorator(Runnable r)
{
this.r = r;
}
@Override
public void run()
{
try
{
r.run(); //在服务器启动时,启动的线程.来执行IO Accept操作。
}
finally
{
FastThreadLocal.removeAll();
}
}
}
NioEventLoop.run() 线程逻辑方法地方
protected void run()
{
for (;;) //线程中无限循环来处理
{
boolean oldWakenUp = wakenUp.getAndSet(false);
try {
if (hasTasks())
{
selectNow();
}
else
{
select(oldWakenUp);
// 'wakenUp.compareAndSet(false, true)' is always evaluated
// before calling 'selector.wakeup()' to reduce the wake-up
// overhead. (Selector.wakeup() is an expensive operation.)
//
// However, there is a race condition in this approach.
// The race condition is triggered when 'wakenUp' is set to
// true too early.
//
// 'wakenUp' is set to true too early if:
// 1) Selector is waken up between 'wakenUp.set(false)' and
// 'selector.select(...)'. (BAD)
// 2) Selector is waken up between 'selector.select(...)' and
// 'if (wakenUp.get()) { ... }'. (OK)
//
// In the first case, 'wakenUp' is set to true and the
// following 'selector.select(...)' will wake up immediately.
// Until 'wakenUp' is set to false again in the next round,
// 'wakenUp.compareAndSet(false, true)' will fail, and therefore
// any attempt to wake up the Selector will fail, too, causing
// the following 'selector.select(...)' call to block
// unnecessarily.
//
// To fix this problem, we wake up the selector again if wakenUp
// is true immediately after selector.select(...).
// It is inefficient in that it wakes up the selector for both
// the first case (BAD - wake-up required) and the second case
// (OK - no wake-up required).
if (wakenUp.get()) {
selector.wakeup();
}
}
cancelledKeys = 0;
needsToSelectAgain = false;
final int ioRatio = this.ioRatio;
if (ioRatio == 100)
{
processSelectedKeys();
runAllTasks();
}
else
{
final long ioStartTime = System.nanoTime();
processSelectedKeys();
final long ioTime = System.nanoTime() - ioStartTime;
runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
}
if (isShuttingDown()) {
closeAll();
if (confirmShutdown()) {
break;
}
}
} catch (Throwable t) {
logger.warn("Unexpected exception in the selector loop.", t);
// Prevent possible consecutive immediate failures that lead to
// excessive CPU consumption.
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// Ignore.
}
}
}
}
private void processSelectedKeys()
{
if (selectedKeys != null)
{
//当调用完成select函数,对完成IO读写状态socket进行处理
processSelectedKeysOptimized(selectedKeys.flip()); //SelectionKey[1024] 参数最大为1024.与windows底层有关
} else {
processSelectedKeysPlain(selector.selectedKeys());
}
}
private void processSelectedKeysOptimized(SelectionKey[] selectedKeys)
{
for (int i = 0;; i ++)
{
final SelectionKey k = selectedKeys[i];
if (k == null)
{
break;
}
selectedKeys[i] = null;
//对于SelectionKey相关联的socket进行处理
final Object a = k.attachment();
if (a instanceof AbstractNioChannel) //此时处理事情是public static final int OP_ACCEPT = 1 << 4; (SelectionKey.OP_ACCEPT interestOps 16 )socket接入事件
{
processSelectedKey(k, (AbstractNioChannel) a);
}
}
NioEventLoop.processSelectedKey(SelectionKey, AbstractNioChannel)
AbstractNioMessageChannel$NioMessageUnsafe.read() 该方法内部处理数据读取操作。
private final class NioMessageUnsafe extends AbstractNioUnsafe
{
//申请缓冲区用于存储临时
private final List<Object> readBuf = new ArrayList<Object>();
@Override
public void read()
{
final ChannelConfig config = config();
if (!config.isAutoRead() && !isReadPending())
{
removeReadOp();
return;
}
//每次读取最大数量
final int maxMessagesPerRead = config.getMaxMessagesPerRead();
final ChannelPipeline pipeline = pipeline();
boolean closed = false;
Throwable exception = null;
try {
try
{
for (;;)
{
int localRead = doReadMessages(readBuf);
if (localRead == 0)
{
break;
}
if (localRead < 0)
{
closed = true;
break;
}
// stop reading and remove op
if (!config.isAutoRead())
{
break;
}
if (readBuf.size() >= maxMessagesPerRead)
{
break;
}
}
} catch (Throwable t) {
exception = t;
}
setReadPending(false);
int size = readBuf.size();
//ChannelPipeline中Handler对数据进行处理
for (int i = 0; i < size; i ++)
{ //通知Handler处理每次读取的数据。由于在这里是没有判断分包处理的。所以,在Handler中需要对分包进行处理
pipeline.fireChannelRead(readBuf.get(i));
}
readBuf.clear();
pipeline.fireChannelReadComplete();
}
}
}
}
在ChannelPipeline类中,初始化Handler时候,ServerBootstrap中内部类ServerBootstrapAcceptor作为Handler
ServerBootstrap$ServerBootstrapAcceptor.channelRead(ChannelHandlerContext, Object)
private static class ServerBootstrapAcceptor extends ChannelInboundHandlerAdapter
{
private final EventLoopGroup childGroup;
private final ChannelHandler childHandler;
private final Entry<ChannelOption<?>, Object>[] childOptions;
private final Entry<AttributeKey<?>, Object>[] childAttrs;
ServerBootstrapAcceptor
(
EventLoopGroup childGroup, ChannelHandler childHandler,
Entry<ChannelOption<?>, Object>[] childOptions, Entry<AttributeKey<?>, Object>[] childAttrs) {
this.childGroup = childGroup;
this.childHandler = childHandler;
this.childOptions = childOptions;
this.childAttrs = childAttrs;
}
//在inbound中对读取消息进行读取
@Override
@SuppressWarnings("unchecked")
public void channelRead(ChannelHandlerContext ctx, Object msg)
{
final Channel child = (Channel) msg;//child NioSocketChannel
child.pipeline().addLast(childHandler);
for (Entry<ChannelOption<?>, Object> e: childOptions)
{
try {
if (!child.config().setOption((ChannelOption<Object>) e.getKey(), e.getValue())) {
logger.warn("Unknown channel option: " + e);
}
} catch (Throwable t) {
logger.warn("Failed to set a channel option: " + child, t);
}
}
for (Entry<AttributeKey<?>, Object> e: childAttrs)
{
child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
}
try
{
//NioSocketChannel 在Acceptor线程中,注册NioSocketChannel和EventLoopGroup相关联。
//到此处为止,Acceptor线程完成NioSocketChannel和EventLoopGroup相关联的任务。
//由此而知,Netty 线程模型和Apache Mina线程模型一样
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);
}
}
private static void forceClose(Channel child, Throwable t) {
child.unsafe().closeForcibly();
logger.warn("Failed to register an accepted channel: " + child, t);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
final ChannelConfig config = ctx.channel().config();
if (config.isAutoRead()) {
// stop accept new connections for 1 second to allow the channel to recover
// See https://github.com/netty/netty/issues/1328
config.setAutoRead(false);
ctx.channel().eventLoop().schedule(new Runnable() {
@Override
public void run() {
config.setAutoRead(true);
}
}, 1, TimeUnit.SECONDS);
}
// still let the exceptionCaught event flow through the pipeline to give the user
// a chance to do something with it
ctx.fireExceptionCaught(cause);
}
}