netty 实现
1. 各组件之间的关系
每个ServerBootstrap与一个事件循环对象(一个线程)都会与一个Channel绑定,如NioServerSocketChannel
2. 如何绑定
在做bind操作时,会执行方法,register进行注册
ChannelFuture regFuture = config).group).registerchannel);
关键接口及类之间的关系:
EventLoopGroup与EventLoop及其类关系图之间形成组合模式。
@Override
public ChannelFuture registerChannel channel) {
return next).registerchannel);//选择一个线程执行器,调用register方法,绑定channel
}
@Override
public ChannelFuture registerChannel channel) {
return registernew DefaultChannelPromisechannel, this));
}
3. 代表客户端的channel创建
注意到ServerBootstrap有两个EventLoopGroup,parent 负责代表客户端channel的分发,child负责代码客户端channel的处理。
Accept事件,创建代表客户端的channel
if readyOps & SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
unsafe.read);
}
try {
do {
int localRead = doReadMessagesreadBuf);
if localRead == 0) {
break;
}
if localRead < 0) {
closed = true;
break;
}
allocHandle.incMessagesReadlocalRead);
} while allocHandle.continueReading));
} catch Throwable t) {
exception = t;
}
int size = readBuf.size);
for int i = 0; i < size; i ++) {
readPending = false;
pipeline.fireChannelReadreadBuf.geti));
}
readBuf.clear);
allocHandle.readComplete);
pipeline.fireChannelReadComplete);
protected int doReadMessagesList<Object> buf) throws Exception {
SocketChannel ch = SocketUtils.acceptjavaChannel));
try {
if ch != null) {
buf.addnew NioSocketChannelthis, 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;
}
注意到doReadMessages会创建代表客户端的channel,创建完成会触发,fireChannelRead 事件。
4. 代表客户端的channel分发
上一节知道,channel创建完成会触发fireChannelRead 事件。在ServerSocketChannel初始化时,会注册ServerBootstrapAcceptor 用户接收代表客户端channel并分发到child EventLoopGroup中执行。
p.addLastnew ChannelInitializer<Channel>) {
@Override
public void initChannelfinal Channel ch) throws Exception {
final ChannelPipeline pipeline = ch.pipeline);
ChannelHandler handler = config.handler);
if handler != null) {
pipeline.addLasthandler);
}
ch.eventLoop).executenew Runnable) {
@Override
public void run) {
pipeline.addLastnew ServerBootstrapAcceptor
ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}
});
@Override
@SuppressWarnings"unchecked")
public void channelReadChannelHandlerContext ctx, Object msg) {
final Channel child = Channel) msg;
child.pipeline).addLastchildHandler);
setChannelOptionschild, childOptions, logger);
for Entry<AttributeKey<?>, Object> e: childAttrs) {
child.attrAttributeKey<Object>) e.getKey)).sete.getValue));
}
try {
childGroup.registerchild).addListenernew ChannelFutureListener) {
@Override
public void operationCompleteChannelFuture future) throws Exception {
if !future.isSuccess)) {
forceClosechild, future.cause));
}
}
});
} catch Throwable t) {
forceClosechild, t);
}
}
5. netty线程模型
不管是客户端还是服务端可以通过一个Channel同时读或者写,不需要阻塞,读写多路复用。