深入浅出Netty之三 Server请求处理

Server bind之后,就可以对外提供服务了。Netty使用了reactor模式来提升服务的并发处理能力。boss线程负责监听新的连接请求,当有新的连接进来时,将对应的channel指派一个worker线程来处理。Worker线程负责对该Channel的读写操作。

一.Boss线程

1.阻塞Select

Java代码 复制代码 收藏代码
  1. for (;;) {
  2. try {
  3. // Boss线程专门负责监听新入连接,所以阻塞select
  4. selector.select();
  5. // 如果有新连接,先把key清掉
  6. selector.selectedKeys().clear();
  7. // 循环请求队列,处理连接
  8. for (;;) {
  9. SocketChannel acceptedSocket = channel.socket.accept();
  10. if (acceptedSocket == null) {
  11. break;
  12. }
  13. registerAcceptedChannel(acceptedSocket, currentThread);
  14. }
  15. ......
 	for (;;) {
                    try {
                        // Boss线程专门负责监听新入连接,所以阻塞select
                        selector.select();
                        // 如果有新连接,先把key清掉
                        selector.selectedKeys().clear();

                        // 循环请求队列,处理连接
                        for (;;) {
                            SocketChannel acceptedSocket = channel.socket.accept();
                            if (acceptedSocket == null) {
                                break;
                            }
                            registerAcceptedChannel(acceptedSocket, currentThread);

                        }
		......
	}
2.注册新连接
Java代码 复制代码 收藏代码
  1. private void registerAcceptedChannel(SocketChannel acceptedSocket, Thread currentThread) {
  2. ......
  3. //根据用户自定义的的PipelineFactory创建pipeline
  4. ChannelPipeline pipeline =
  5. channel.getConfig().getPipelineFactory().getPipeline();
  6. //hash分配worker线程,默认使用递增循环worker数组方式
  7. NioWorker worker = nextWorker();
  8. //将新的连接注册到worker线程,让worker线程负责后续读写
  9. //新的channel是主channel的子channel,而PipelineSink和主channel是同一个
  10. worker.register(new NioAcceptedSocketChannel(
  11. channel.getFactory(), pipeline, channel,
  12. NioServerSocketPipelineSink.this, acceptedSocket,
  13. worker, currentThread), null);
  14. ......
  15. }
    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);
            ......
        }
Java代码 复制代码 收藏代码
  1. void register(AbstractNioChannel<?> channel, ChannelFuture future) {
  2. synchronized (startStopLock) {
  3. ......
  4. //创建注册通道的任务
  5. Runnable registerTask = createRegisterTask(channel, future);
  6. //提交任务到阻塞队列
  7. boolean offered = registerTaskQueue.offer(registerTask);
  8. //唤醒selector
  9. if (wakenUp.compareAndSet(false, true)) {
  10. selector.wakeup();
  11. }
  12. }
  13. }
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.创建注册任务

Java代码 复制代码 收藏代码
  1. protected Runnable createRegisterTask(AbstractNioChannel<?> channel, ChannelFuture future) {
  2. boolean server = !(channel instanceof NioClientSocketChannel);
  3. return new RegisterTask((NioSocketChannel) channel, future, server);
  4. }
 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.主循环

Java代码 复制代码 收藏代码
  1. for (;;) {
  2. wakenUp.set(false);
  3. ......
  4. if (wakenUp.get()) {
  5. wakenupFromLoop = true;
  6. selector.wakeup();
  7. } else {
  8. wakenupFromLoop = false;
  9. }
  10. cancelledKeys = 0;
  11. //处理注册通道的任务
  12. processRegisterTaskQueue();
  13. //处理异步事件,比如writeComplete事件
  14. processEventQueue();
  15. //处理写数据任务,如果业务线程有异步写的时候,会有WriteTask放入队列
  16. processWriteTaskQueue();
  17. //处理IO准备好的那些channel
  18. processSelectedKeys(selector.selectedKeys());
  19. ......
  20. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值