目录
1.概览
1.1 EventLoop接口
1.1.1 EventLoop类图

1.2 EventLoop接口实现类
通过继承关系图可以看出,EventLoop接口有AbstractEventLoop、SingleThreadEventLoop、EpollEventLoop、ThreadPerChannelEventLoop、DefaultEventLoop、NioEventLoop、EmbeddedEventLoop这7个具体的实现子类。下面对这些实现子类逐个进行分析。
1.2.1 SingleThreadEventLoop
- 官方解释
Abstract base class for EventLoops that execute all its submitted tasks in a single thread.
从官方解释来看,这是一个事件循环提交任务的类,并且是单线程的。
- 方法列表
- 注册Channel
这里边有3个register方法,走码看看,netty是如何注册Channel的。
public ChannelFuture register(Channel channel) {
return this.register((ChannelPromise)(new DefaultChannelPromise(channel, this)));
}
public ChannelFuture register(ChannelPromise promise) {
ObjectUtil.checkNotNull(promise, "promise");
promise.channel().unsafe().register(this, promise);
return promise;
}
可以看到,这里用ChannelPromise封装了下入参Channel,然后再去注册的。那ChannelPromise到底是什么?
先看下类图
DefaultChannelPromise是ChannelPromise接口的默认实现,而ChannelPromise是可写的ChannelFuture。Future模式是多线程开发中非常常见的一种设计模式。它的核心思想是异步调用。当我们需要调用一个函数方法时。如果这个函数执行很慢,那么我们就要进行等待。但有时候,我们可能并不急着要结果。因此,我们可以让被调用者立即返回,让他在后台慢慢处理这个请求。对于调用者来说,则可以先处理一些其他任务,在真正需要数据的场合再去尝试获取需要的数据。
这里走到Channel的unsafe()。涉及到核心组件Unsafe。这里unsafe()方法调用到Channel接口内部接口Unsafe。Channel接口的2个实现类AbstractChannel、AbstractNioChannel分别在内部实现不同的Unsafe接口。这种用法挺奇怪的,为什么用内部接口的形式?这里先mark下,后面再空在回来看看。
先看下Unsafe接口到底是什么?
public interface Unsafe {
Handle recvBufAllocHandle();
SocketAddress localAddress();
SocketAddress remoteAddress();
void register(EventLoop var1, ChannelPromise var2);
void bind(SocketAddress var1, ChannelPromise var2);
void connect(SocketAddress var1, SocketAddress var2, ChannelPromise var3);
void disconnect(ChannelPromise var1);
void close(ChannelPromise var1);
void closeForcibly();
void deregister(ChannelPromise var1);
void beginRead();
void write(Object var1, ChannelPromise var2);
void flush();
ChannelPromise voidPromise();
ChannelOutboundBuffer outboundBuffer();
}
public interface NioUnsafe extends Unsafe {
SelectableChannel ch();
void finishConnect();
void read();
void forceFlush();
}
看下官方解释
Unsafe operations that should never be called from user-code. These methods are only provided to implement the actual transport, and must be invoked from an I/O thread except for the following methods:
这个接口的方法主要用来做实际传输的,并且必须被一个IO线程调用,不能被开发者调用。
刚才也说到了,Unsafe接口被作为Channel接口的内部接口,那要看Unsafe接口的具体实现就必须到Channel接口的各个实现类去看看。
Channel接口的实现类相当多,从idea导出
AbstractChannel (io.netty.channel)
AbstractEpollChannel (io.netty.channel.epoll)
AbstractEpollServerChannel (io.netty.channel.epoll)
EpollServerDomainSocketChannel (io.netty.channel.epoll)
EpollServerSocketChannel (io.netty.channel.epoll)
AbstractEpollStreamChannel (io.netty.channel.epoll)
EpollSocketChannel (io.netty.channel.epoll)
EpollDomainSocketChannel (io.netty.channel.epoll)
EpollDatagramChannel (io.netty.channel.epoll)
LocalChannel (io.netty.channel.local)
AbstractHttp2StreamChannel (io.netty.handler.codec.http2)
Http2StreamChannel in Http2MultiplexCodec (io.netty.handler.codec.http2)
EmbeddedChannel (io.netty.channel.embedded)
AbstractOioChannel (io.netty.channel.oio)
AbstractOioByteChannel (io.netty.channel.oio)
OioByteStreamChannel (io.netty.channel.oio)
OioSocketChannel (io.netty.channel.socket.oio)
RxtxChannel (io.netty.channel.rxtx)
AbstractOioMessageChannel (io.netty.channel.oio)
OioSctpServerChannel (io.netty.channel.sctp.oio)
OioServerSocketChannel (io.netty.channel.socket.oio)
OioSctpChannel (io.netty.channel.sctp.oio)
OioDatagramChannel (io.netty.channel.socket.oio)
AbstractServerChannel (io.netty.channel)
LocalServerChannel (io.netty.channel.local)
AbstractNioChannel (io.netty.channel.nio)
AbstractNioMessageChannel (io.netty.channel.nio)
NioDatagramChannel (io.netty.channel.socket.nio)
NioUdtAcceptorChannel (io.netty.channel.udt.nio)
NioUdtByteAcceptorChannel (io.netty.channel.udt.nio)
NioUdtMessageAcceptorChannel (io.netty.channel.udt.nio)
NioSctpChannel (io.netty.channel.sctp.nio)
NioSctpServerChannel (io.netty.channel.sctp.nio)
NioServerSocketChannel (io.netty.channel.socket.nio)
NioUdtMessageConnectorChannel (io.netty.channel.udt.nio)
NioUdtMessageRendezvousChannel (io.netty.channel.udt.nio)
AbstractNioByteChannel (io.netty.channel.nio)
NioSocketChannel (io.netty.channel.socket.nio)
NioUdtByteConnectorChannel (io.netty.channel.udt.nio)
ServerChannel (io.netty.channel)
ServerSocketChannel (io.netty.channel.socket)
EpollServerSocketChannel (io.netty.channel.epoll)
OioServerSocketChannel (io.netty.channel.socket.oio)
NioServerSocketChannel (io.netty.channel.socket.nio)
ServerDomainSocketChannel (io.netty.channel.unix)
EpollServerDomainSocketChannel (io.netty.channel.epoll)
AbstractEpollServerChannel (io.netty.channel.epoll)
EpollServerDomainSocketChannel (io.netty.channel.epoll)
EpollServerSocketChannel (io.netty.channel.epoll)
SctpServerChannel (io.netty.channel.sctp)
OioSctpServerChannel (io.netty.channel.sctp.oio)
NioSctpServerChannel (io.netty.channel.sctp.nio)
AbstractServerChannel (io.netty.channel)
LocalServerChannel (io.netty.channel.local)
UdtServerChannel (io.netty.channel.udt)
NioUdtAcceptorChannel (io.netty.channel.udt.nio)
NioUdtByteAcceptorChannel (io.netty.channel.udt.nio)
NioUdtMessageAcceptorChannel (io.netty.channel.udt.nio)
SctpChannel (io.netty.channel.sctp)
NioSctpChannel (io.netty.channel.sctp.nio)
OioSctpChannel (io.netty.channel.sctp.oio)
UnixChannel (io.netty.channel.unix)
AbstractEpollChannel (io.netty.channel.epoll)
AbstractEpollServerChannel (io.netty.channel.epoll)
EpollServerDomainSocketChannel (io.netty.channel.epoll)
EpollServerSocketChannel (io.netty.channel.epoll)
AbstractEpollStreamChannel (io.netty.channel.epoll)
EpollSocketChannel (io.netty.channel.epoll)
EpollDomainSocketChannel (io.netty.channel.epoll)
EpollDatagramChannel (io.netty.channel.epoll)
DomainSocketChannel (io.netty.channel.unix)
EpollDomainSocketChannel (io.netty.channel.epoll)
ServerDomainSocketChannel (io.netty.channel.unix)
EpollServerDomainSocketChannel (io.netty.channel.epoll)
DatagramChannel (io.netty.channel.socket)
NioDatagramChannel (io.netty.channel.socket.nio)
OioDatagramChannel (io.netty.channel.socket.oio)
EpollDatagramChannel (io.netty.channel.epoll)
DuplexChannel (io.netty.channel.socket)
DomainSocketChannel (io.netty.channel.unix)
EpollDomainSocketChannel (io.netty.channel.epoll)
AbstractEpollStreamChannel (io.netty.channel.epoll)
EpollSocketChannel (io.netty.channel.epoll)
EpollDomainSocketChannel (io.netty.channel.epoll)
SocketChannel (io.netty.channel.socket)
EpollSocketChannel (io.netty.channel.epoll)
NioSocketChannel (io.netty.channel.socket.nio)
OioSocketChannel (io.netty.channel.socket.oio)
UdtChannel (io.netty.channel.udt)
NioUdtByteConnectorChannel (io.netty.channel.udt.nio)
NioUdtByteRendezvousChannel (io.netty.channel.udt.nio)
NioUdtMessageConnectorChannel (io.netty.channel.udt.nio)
NioUdtMessageRendezvousChannel (io.netty.channel.udt.nio)
UdtServerChannel (io.netty.channel.udt)
NioUdtAcceptorChannel (io.netty.channel.udt.nio)
NioUdtByteAcceptorChannel (io.netty.channel.udt.nio)
NioUdtMessageAcceptorChannel (io.netty.channel.udt.nio)
选几个比较常用的Channel实现类看看对应的Unsafe接口实现。
AbstractChannel抽象类的Unsafe实现AbstractUnsafe
protected abstract class AbstractUnsafe implements Unsafe {
private volatile ChannelOutboundBuffer outboundBuffer = new ChannelOutboundBuffer(AbstractChannel.this);
private Handle recvHandle;
private boolean inFlush0;
private boolean neverRegistered = true;
protected AbstractUnsafe() {
}
private void assertEventLoop() {
assert !AbstractChannel.this.registered || AbstractChannel.this.eventLoop.inEventLoop();
}
public Handle recvBufAllocHandle() {
if(this.recvHandle == null) {
this.recvHandle = AbstractChannel.this.config().getRecvByteBufAllocator().newHandle();
}
return this.recvHandle;
}
public final ChannelOutboundBuffer outboundBuffer() {
return this.outboundBuffer;
}
public final SocketAddress localAddress() {
return AbstractChannel.this.localAddress0();
}
public final SocketAddress remoteAddress() {
return AbstractChannel.this.remoteAddress0();
}
public final void register(EventLoop eventLoop, final ChannelPromise promise) {
if(eventLoop == null) {
throw new NullPointerException("eventLoop");
} else if(AbstractChannel.this.isRegistered()) {
promise.setFailure(new IllegalStateException("registered to an event loop already"));
} else if(!AbstractChannel.this.isCompatible(eventLoop)) {
promise.setFailure(new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName()));
} else {
AbstractChannel.this.eventLoop = eventLoop;
if(eventLoop.inEventLoop()) {
this.register0(promise);
} else {
try {
eventLoop.execute(new Runnable() {
public void run() {
AbstractUnsafe.this.register0(promise);
}
});
} catch (Throwable var4) {
AbstractChannel.logger.warn("Force-closing a channel whose registration task was not accepted by an event loop: {}", AbstractChannel.this, var4);
this.closeForcibly();
AbstractChannel.this.closeFuture.setClosed();
this.safeSetFailure(promise, var4);
}
}
}
}
private void register0(ChannelPromise promise) {
try {
if(!promise.setUncancellable() || !this.ensureOpen(promise)) {
return;
}
boolean t = this.neverRegistered;
AbstractChannel.this.doRegister();
this.neverRegistered = false;
AbstractChannel.this.registered = true;
AbstractChannel.this.pipeline.invokeHandlerAddedIfNeeded();
this.safeSetSuccess(promise);
AbstractChannel.this.pipeline.fireChannelRegistered();
if(AbstractChannel.this.isActive()) {
if(t) {
AbstractChannel.this.pipeline.fireChannelActive();
} else if(AbstractChannel.this.config().isAutoRead()) {
this.beginRead();
}
}
} catch (Throwable var3) {
this.closeForcibly();
AbstractChannel.this.closeFuture.setClosed();
this.safeSetFailure(promise, var3);
}
}
public final void bind(SocketAddress localAddress, ChannelPromise promise) {
this.assertEventLoop();
if(promise.setUncancellable() && this.ensureOpen(promise)) {
if(Boolean.TRUE.equals(AbstractChannel.this.config().getOption(ChannelOption.SO_BROADCAST)) && localAddress instanceof InetSocketAddress && !((InetSocketAddress)localAddress).getAddress().isAnyLocalAddress() && !PlatformDependent.isWindows() && !PlatformDependent.maybeSuperUser()) {
AbstractChannel.logger.warn("A non-root user can\'t receive a broadcast packet if the socket is not bound to a wildcard address; binding to a non-wildcard address (" + localAddress + ") anyway as requested.");
}
boolean wasActive = AbstractChannel.this.isActive();
try {
AbstractChannel.this.doBind(localAddress);
} catch (Throwable var5) {
this.safeSetFailure(promise, var5);
this.closeIfClosed();
return;
}
if(!wasActive && AbstractChannel.this.isActive()) {
this.invokeLater(new Runnable() {
public void run() {
AbstractChannel.this.pipeline.fireChannelActive();
}
});
}
this.safeSetSuccess(promise);
}
}
public final void disconnect(ChannelPromise promise) {
this.assertEventLoop();
if(promise.setUncancellable()) {
boolean wasActive = AbstractChannel.this.isActive();
try {
AbstractChannel.this.doDisconnect();
} catch (Throwable var4) {
this.safeSetFailure(promise, var4);
this.closeIfClosed();
return;
}
if(wasActive && !AbstractChannel.this.isActive()) {
this.invokeLater(new Runnable() {
public void run() {
AbstractChannel.this.pipeline.fireChannelInactive();
}
});
}
this.safeSetSuccess(promise);
this.closeIfClosed();
}
}
public final void close(ChannelPromise promise) {
this.assertEventLoop();
this.close(promise, AbstractChannel.CLOSE_CLOSED_CHANNEL_EXCEPTION, AbstractChannel.CLOSE_CLOSED_CHANNEL_EXCEPTION, false);
}
private void close(final ChannelPromise promise, final Throwable cause, final ClosedChannelException closeCause, final boolean notify) {
if(promise.setUncancellable()) {
final ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;
if(outboundBuffer == null) {
if(!(promise instanceof VoidChannelPromise)) {
AbstractChannel.this.closeFuture.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
promise.setSuccess();
}
});
}
} else if(AbstractChannel.this.closeFuture.isDone()) {
this.safeSetSuccess(promise);
} else {
final boolean wasActive = AbstractChannel.this.isActive();
this.outboundBuffer = null;
Executor closeExecutor = this.prepareToClose();
if(closeExecutor != null) {
closeExecutor.execute(new Runnable() {
public void run() {
try {
AbstractUnsafe.this.doClose0(promise);
} finally {
AbstractUnsafe.this.invokeLater(new Runnable() {
public void run() {
outboundBuffer.failFlushed(cause, notify);
outboundBuffer.close(closeCause);
AbstractUnsafe.this.fireChannelInactiveAndDeregister(wasActive);
}
});
}
}
});
} else {
try {
this.doClose0(promise);
} finally {
outboundBuffer.failFlushed(cause, notify);
outboundBuffer.close(closeCause);
}
if(this.inFlush0) {
this.invokeLater(new Runnable() {
public void run() {
AbstractUnsafe.this.fireChannelInactiveAndDeregister(wasActive);
}
});
} else {
this.fireChannelInactiveAndDeregister(wasActive);
}
}
}
}
}
private void doClose0(ChannelPromise promise) {
try {
AbstractChannel.this.doClose();
AbstractChannel.this.closeFuture.setClosed();
this.safeSetSuccess(promise);
} catch (Throwable var3) {
AbstractChannel.this.closeFuture.setClosed();
this.safeSetFailure(promise, var3);
}
}
private void fireChannelInactiveAndDeregister(boolean wasActive) {
this.deregister(this.voidPromise(), wasActive && !AbstractChannel.this.isActive());
}
public final void closeForcibly() {
this.assertEventLoop();
try {
AbstractChannel.this.doClose();
} catch (Exception var2) {
AbstractChannel.logger.warn("Failed to close a channel.", var2);
}
}
public final void deregister(ChannelPromise promise) {
this.assertEventLoop();
this.deregister(promise, false);
}
private void deregister(final ChannelPromise promise, final boolean fireChannelInactive) {
if(promise.setUncancellable()) {
if(!AbstractChannel.this.registered) {
this.safeSetSuccess(promise);
} else {
this.invokeLater(new Runnable() {
public void run() {
try {
AbstractChannel.this.doDeregister();
} catch (Throwable var5) {
AbstractChannel.logger.warn("Unexpected exception occurred while deregistering a channel.", var5);
} finally {
if(fireChannelInactive) {
AbstractChannel.this.pipeline.fireChannelInactive();
}
if(AbstractChannel.this.registered) {
AbstractChannel.this.registered = false;
AbstractChannel.this.pipeline.fireChannelUnregistered();
}
AbstractUnsafe.this.safeSetSuccess(promise);
}
}
});
}
}
}
public final void beginRead() {
this.assertEventLoop();
if(AbstractChannel.this.isActive()) {
try {
AbstractChannel.this.doBeginRead();
} catch (final Exception var2) {
this.invokeLater(new Runnable() {
public void run() {
AbstractChannel.this.pipeline.fireExceptionCaught(var2);
}
});
this.close(this.voidPromise());
}
}
}
public final void write(Object msg, ChannelPromise promise) {
this.assertEventLoop();
ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;
if(outboundBuffer == null) {
this.safeSetFailure(promise, AbstractChannel.WRITE_CLOSED_CHANNEL_EXCEPTION);
ReferenceCountUtil.release(msg);
} else {
int size;
try {
msg = AbstractChannel.this.filterOutboundMessage(msg);
size = AbstractChannel.this.pipeline.estimatorHandle().size(msg);
if(size < 0) {
size = 0;
}
} catch (Throwable var6) {
this.safeSetFailure(promise, var6);
ReferenceCountUtil.release(msg);
return;
}
outboundBuffer.addMessage(msg, size, promise);
}
}
public final void flush() {
this.assertEventLoop();
ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;
if(outboundBuffer != null) {
outboundBuffer.addFlush();
this.flush0();
}
}
protected void flush0() {
if(!this.inFlush0) {
ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;
if(outboundBuffer != null && !outboundBuffer.isEmpty()) {
this.inFlush0 = true;
if(!AbstractChannel.this.isActive()) {
try {
if(AbstractChannel.this.isOpen()) {
outboundBuffer.failFlushed(AbstractChannel.FLUSH0_NOT_YET_CONNECTED_EXCEPTION, true);
} else {
outboundBuffer.failFlushed(AbstractChannel.FLUSH0_CLOSED_CHANNEL_EXCEPTION, false);
}
} finally {
this.inFlush0 = false;
}
} else {
try {
AbstractChannel.this.doWrite(outboundBuffer);
} catch (Throwable var11) {
if(var11 instanceof IOException && AbstractChannel.this.config().isAutoClose()) {
this.close(this.voidPromise(), var11, AbstractChannel.FLUSH0_CLOSED_CHANNEL_EXCEPTION, false);
} else {
outboundBuffer.failFlushed(var11, true);
}
} finally {
this.inFlush0 = false;
}
}
}
}
}
public final ChannelPromise voidPromise() {
this.assertEventLoop();
return AbstractChannel.this.unsafeVoidPromise;
}
/** @deprecated */
@Deprecated
protected final boolean ensureOpen(ChannelPromise promise) {
if(AbstractChannel.this.isOpen()) {
return true;
} else {
this.safeSetFailure(promise, AbstractChannel.ENSURE_OPEN_CLOSED_CHANNEL_EXCEPTION);
return false;
}
}
protected final void safeSetSuccess(ChannelPromise promise) {
if(!(promise instanceof VoidChannelPromise) && !promise.trySuccess()) {
AbstractChannel.logger.warn("Failed to mark a promise as success because it is done already: {}", promise);
}
}
protected final void safeSetFailure(ChannelPromise promise, Throwable cause) {
if(!(promise instanceof VoidChannelPromise) && !promise.tryFailure(cause)) {
AbstractChannel.logger.warn("Failed to mark a promise as failure because it\'s done already: {}", promise, cause);
}
}
protected final void closeIfClosed() {
if(!AbstractChannel.this.isOpen()) {
this.close(this.voidPromise());
}
}
private void invokeLater(Runnable task) {
try {
AbstractChannel.this.eventLoop().execute(task);
} catch (RejectedExecutionException var3) {
AbstractChannel.logger.warn("Can\'t invoke task later as EventLoop rejected it", var3);
}
}
protected final Throwable annotateConnectException(Throwable cause, SocketAddress remoteAddress) {
return (Throwable)(cause instanceof ConnectException?new AbstractChannel.AnnotatedConnectException((ConnectException)cause, remoteAddress):(cause instanceof NoRouteToHostException?new AbstractChannel.AnnotatedNoRouteToHostException((NoRouteToHostException)cause, remoteAddress):(cause instanceof SocketException?new AbstractChannel.AnnotatedSocketException((SocketException)cause, remoteAddress):cause)));
}
protected Executor prepareToClose() {
return null;
}
}