Server bind之后,就可以对外提供服务了。Netty使用了reactor模式来提升服务的并发处理能力。boss线程负责监听新的连接请求,当有新的连接进来时,将对应的channel指派一个worker线程来处理。Worker线程负责对该Channel的读写操作。
一.Boss线程
1.阻塞Select
- for (;;) {
- try {
- // Boss线程专门负责监听新入连接,所以阻塞select
- selector.select();
- // 如果有新连接,先把key清掉
- selector.selectedKeys().clear();
- // 循环请求队列,处理连接
- for (;;) {
- SocketChannel acceptedSocket = channel.socket.accept();
- if (acceptedSocket == null) {
- break;
- }
- registerAcceptedChannel(acceptedSocket, currentThread);
- }
- ......
for (;;) {
try {
// Boss线程专门负责监听新入连接,所以阻塞select
selector.select();
// 如果有新连接,先把key清掉
selector.selectedKeys().clear();
// 循环请求队列,处理连接
for (;;) {
SocketChannel acceptedSocket = channel.socket.accept();
if (acceptedSocket == null) {
break;
}
registerAcceptedChannel(acceptedSocket, currentThread);
}
......
}
2.注册新连接
- private void registerAcceptedChannel(SocketChannel acceptedSocket, Thread currentThread) {
- ......
- //根据用户自定义的的PipelineFactory创建pipeline
- ChannelPipeline pipeline =
- channel.getConfig().getPipelineFactory().getPipeline();
- //hash分配worker线程,默认使用递增循环worker数组方式
- NioWorker worker = nextWorker();
- //将新的连接注册到worker线程,让worker线程负责后续读写
- //新的channel是主channel的子channel,而PipelineSink和主channel是同一个
- worker.register(new NioAcceptedSocketChannel(
- channel.getFactory(), pipeline, channel,
- NioServerSocketPipelineSink.this, acceptedSocket,
- worker, currentThread), null);
- ......
- }
private void registerAcceptedChannel(SocketChannel acceptedSocket, Thread currentThread) {
......
//根据用户自定义的的PipelineFactory创建pipeline
ChannelPipeline pipeline =
channel.getConfig().getPipelineFactory().getPipeline();
//hash分配worker线程,默认使用递增循环worker数组方式
NioWorker worker = nextWorker();
//将新的连接注册到worker线程,让worker线程负责后续读写
//新的channel是主channel的子channel,而PipelineSink和主channel是同一个
worker.register(new NioAcceptedSocketChannel(
channel.getFactory(), pipeline, channel,
NioServerSocketPipelineSink.this, acceptedSocket,
worker, currentThread), null);
......
}
- void register(AbstractNioChannel<?> channel, ChannelFuture future) {
- synchronized (startStopLock) {
- ......
- //创建注册通道的任务
- Runnable registerTask = createRegisterTask(channel, future);
- //提交任务到阻塞队列
- boolean offered = registerTaskQueue.offer(registerTask);
- //唤醒selector
- if (wakenUp.compareAndSet(false, true)) {
- selector.wakeup();
- }
- }
- }
void register(AbstractNioChannel<?> channel, ChannelFuture future) {
synchronized (startStopLock) {
......
//创建注册通道的任务
Runnable registerTask = createRegisterTask(channel, future);
//提交任务到阻塞队列
boolean offered = registerTaskQueue.offer(registerTask);
//唤醒selector
if (wakenUp.compareAndSet(false, true)) {
selector.wakeup();
}
}
}
3.创建注册任务
- protected Runnable createRegisterTask(AbstractNioChannel<?> channel, ChannelFuture future) {
- boolean server = !(channel instanceof NioClientSocketChannel);
- return new RegisterTask((NioSocketChannel) channel, future, server);
- }
protected Runnable createRegisterTask(AbstractNioChannel<?> channel, ChannelFuture future) {
boolean server = !(channel instanceof NioClientSocketChannel);
return new RegisterTask((NioSocketChannel) channel, future, server);
}
二.worker线程
worker线程负责对应channel的读写操作,一个worker对应一个selector,会同时处理多个channel的读写。
1.主循环
- for (;;) {
- wakenUp.set(false);
- ......
- if (wakenUp.get()) {
- wakenupFromLoop = true;
- selector.wakeup();
- } else {
- wakenupFromLoop = false;
- }
- cancelledKeys = 0;
- //处理注册通道的任务
- processRegisterTaskQueue();
- //处理异步事件,比如writeComplete事件
- processEventQueue();
- //处理写数据任务,如果业务线程有异步写的时候,会有WriteTask放入队列
- processWriteTaskQueue();
- //处理IO准备好的那些channel
- processSelectedKeys(selector.selectedKeys());
- ......
- }