Netty实现了Reactor模型,下面两图整体说明了一下netty的处理流程
先贴一下netty常用的编码模式:
public static void main(String[] args) {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new MyServerInitializer());
ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
channelFuture.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
以 EventLoopGroup 为切入口跟一下源码。
类图如上,EventLoopGroup 主要定义了:
//Return the next EventLoop to use
EventLoop next();
//Register a Channel with this EventLoop. The returned ChannelFuture will get notified once the registration was complete.
ChannelFuture register(Channel channel);
NioEventLoopGroup类的初始化:
默认会调用到:
protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
}
static {
DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
"io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
if (logger.isDebugEnabled()) {
logger.debug("-Dio.netty.eventLoopThreads: {}", DEFAULT_EVENT_LOOP_THREADS);
}
}
会默认起2*核心CPU数量的线程(nThreads)。 最终调用的初始化方法:
Create a new instance.
Params:
nThreads – the number of threads that will be used by this instance.
executor – the Executor to use, or null if the default should be used.
chooserFactory – the EventExecutorChooserFactory to use.
args – arguments which will passed to each newChild(Executor, Object...) call
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
if (nThreads <= 0) {
throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
}
if (executor == null) {
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}
children = new EventExecutor[nThreads];
for (int i = 0; i < nThreads; i ++) {
boolean success = false;
try {
children[i] = newChild(executor, args);
success = true;
} catch (Exception e) {
// TODO: Think about if this is a good exception type
throw new IllegalStateException("failed to create a child event loop", e);
} finally {
if (!success) {
for (int j = 0; j < i; j ++) {
children[j].shutdownGracefully();
}
for (int j = 0; j < i; j ++) {
EventExecutor e = children[j];
try {
while (!e.isTerminated()) {
e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
}
} catch (InterruptedException interrupted) {
// Let the caller handle the interruption.
Thread.currentThread().interrupt();
break;
}
}
}
}
}
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);
}
Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
Collections.addAll(childrenSet, children);
readonlyChildren = Collections.unmodifiableSet(childrenSet);
}
启动 nThreads 个EventExecutor,newChild方法在我们的代码中调用的就是 NioEventLoopGroup的newChild方法。
ServerBootstrap 是启动的辅助类,主要是给ServerBootstrap类的成员变量赋值,调用bind的时候会用到。
serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new MyServerInitializer());
指定的NioServerSocketChannel.class通过反射生成类的实例:
@Override
public T newChannel() {
try {
return clazz.getConstructor().newInstance();
} catch (Throwable t) {
throw new ChannelException("Unable to create Channel from class " + clazz, t);
}
}
netty中的不少类都是直接封装的Java类库中的类,比如ByteBuf->ByteBUffer、Future->Future,netty中的Future添加了addListener方法,在future isDone的时候,对应的listener会立即收到通知。
Future的sync方法-->等待future完成。Waits for this future until it is done, and rethrows the cause of the failure if this future failed.