Netty - Reactor线程模型解析

  • 阻塞:读取某个资源,等待资源读取完成,再执行后续操作
  • 非阻塞:读取某个资源,立即返回,若无法给出结果,返回一个预定义好的值

一个非阻塞的例子:列表中有三份资源,在 while 循环中不断遍历,如果资源读取成功,从列表移除

list = [resource1, resource2, resource3];
while (!list.Empty()){	// 列表不为空
	for (resource of list) {	// 遍历列表
		data = read(resource);	// 读取资源
		if (data !== null) { 
			list.remove(resource) ;
		} else {
			continue;
		}
	}
}

缺点:在绝大多数情况下,迭代的资源,都还未将数据准备好,因此,白白浪费了 CPU

如何优化?
定义一个监听器,监听列表,当列表中有资源读取成功,发送消息给监听器,监听器执行之后相应操作

while (events = watch(list)) {	// 监听 list,如果有资源读取完成,放入 events 中
	for (event of events) {		// 遍历 events,读取(读取完成的资源)
		events.remove(event);
		list.remove(event);
	}
}

reactor 模式:是一种处理 I/O 操作的模式,如果受监控的某资源产生新事件,那就接触阻塞,对事件做出反应

极简 netty 服务器

NioEventLoopGroup boosGroup = new NioEventLoopGroup();
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
new ServerBootstrap()
    .group(boosGroup, workerGroup)
    .channel(NioServerSocketChannel.class)
    .childHandler(new ChannelInitializer<NioSocketChannel>() {
        protected void initChannel(NioSocketChannel ch) { }
    }).bind(8080);

创建 NioEventLoopGroup 流程

在 MultithreadEventExecutorGroup 中,主要做了 3 件事

  1. 创建 ThreadPerTaskExecutor
  2. 创建 NioEventLoop
  3. 创建线程选择器
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                        EventExecutorChooserFactory chooserFactory, Object... args) {
    // ......
    
    if (executor == null) {
    	// 1 创建 ThreadPerTaskExecutor
        executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
    }

	// 2 创建 NioEventLoop
    children = new EventExecutor[nThreads];
    for (int i = 0; i < nThreads; i ++) {
        try {
            children[i] = newChild(executor, args);
        }
    }
    
	// 3 创建线程选择器
    chooser = chooserFactory.newChooser(children);

    // ......
}

对应流程图如下

看源码时,记得留意类的英文名,对应的中文意思,见名思意

在这里插入图片描述

bind(port) - register

大致如下
bind -> doBind
doBind() 中 有 initAndRegister() 方法,大致行为如下:

  1. 创建服务器 channel:channel = channelFactory.newChannel()
  2. 初始化服务器 channel:init(channel)
  3. 注册服务器 channel:config().group().register(channel)

SingleThreadEventLoop - 单个线程事件循环

在 3 register 中,有如下语句

public abstract class SingleThreadEventLoop extends SingleThreadEventExecutor implements EventLoop {
    public ChannelFuture register(final ChannelPromise promise) {
        // ......
        promise.channel().unsafe().register(this, promise);		// <--- 传入 this,之后通过 this 调用该抽象类的 execute 方法
        return promise;
    }
}

public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
	// 内部类
	protected abstract class AbstractUnsafe implements Unsafe {
		public final void register(EventLoop eventLoop, final ChannelPromise promise) {
			// inEventLoop:当前线程是否是 Netty 的 Reactor 线程,这里返回 false
			if (eventLoop.inEventLoop()) {
			   register0(promise);
			} else {
				try {
				    eventLoop.execute(new Runnable() {		// <--- 调用 SingleThreadEventExecutor # execute()
				        @Override
				        public void run() {
				            register0(promise);
				        }
				    });
			    }
			} 
		}
	}
}

SingleThreadEventExecutor # execute() - 单个线程事件执行器

public abstract class SingleThreadEventExecutor extends AbstractScheduledEventExecutor implements OrderedEventExecutor {
    public void execute(Runnable task) {
        // ......
        boolean inEventLoop = inEventLoop();
        if (inEventLoop) {
            addTask(task);
        } else {
            startThread();		// <--- 调用
            addTask(task);
            // ......
        }
		// ......
    }
    
    private void startThread() {
        if (STATE_UPDATER.get(this) == ST_NOT_STARTED) {
            if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
                doStartThread();		// <--- 调用
            }
        }
    }

    private void doStartThread() {
        assert thread == null;
        executor.execute(new Runnable() {		// <--- 调用 ThreadPerTaskExecutor 的 execute 方法
            @Override
            public void run() {
                thread = Thread.currentThread();
                // ......
                try {
                    SingleThreadEventExecutor.this.run();
                } // ......
            }
        });
    }
    
}

executor 为 NioEventLoop

这里的 executor 就是:创建 NioEventLoopGroup 流程中,第一步,创建的 ThreadPerTaskExecutor,之后在创建 NioEventLoop 时,传入 executor,之后, newChild 的时候,将其存入 SingleThreadEventExecutor 类的 executor

protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                        EventExecutorChooserFactory chooserFactory, Object... args) {
    // ......
    if (executor == null) {
    	// 1 创建 ThreadPerTaskExecutor
        executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
    }

	// 2 创建 NioEventLoop
    children = new EventExecutor[nThreads];
    for (int i = 0; i < nThreads; i ++) {
        try {
            children[i] = newChild(executor, args);		// <----- 传入 ThreadPerTaskExecutor
        }
    }
    // ......
}

// newChild 最后会执行到这里
public abstract class SingleThreadEventExecutor extends AbstractScheduledEventExecutor implements OrderedEventExecutor {
    protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
                                        boolean addTaskWakesUp, int maxPendingTasks,
                                        RejectedExecutionHandler rejectedHandler) {
        // .......
        this.executor = ObjectUtil.checkNotNull(executor, "executor");
        // .......
    }
}

ThreadPerTaskExecutor # execute - 线程的每个任务执行器

于是乎,调用 ThreadPerTaskExecutor 的 execute 方法,如下

public final class ThreadPerTaskExecutor implements Executor {
    private final ThreadFactory threadFactory;

    public ThreadPerTaskExecutor(ThreadFactory threadFactory) {
        if (threadFactory == null) {
            throw new NullPointerException("threadFactory");
        }
        this.threadFactory = threadFactory;
    }

    @Override
    public void execute(Runnable command) {
        threadFactory.newThread(command).start();		// <----- 执行
    }
}
public class DefaultThreadFactory implements ThreadFactory {
    public Thread newThread(Runnable r) {
        Thread t = newThread(new DefaultRunnableDecorator(r), prefix + nextId.incrementAndGet());		// <----- 执行
        // ......
        return t;
    }

    protected Thread newThread(Runnable r, String name) {
        return new FastThreadLocalThread(threadGroup, r, name);		// <----- 执行 FastThreadLocalThread.start()
    }
}

执行 FastThreadLocalThread.start(),会执行对应的 Runnable

public abstract class SingleThreadEventExecutor extends AbstractScheduledEventExecutor implements OrderedEventExecutor {
    private void doStartThread() {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                thread = Thread.currentThread();
                // ......
                try {
                    SingleThreadEventExecutor.this.run();		// <--- 调用 SingleThreadEventExecutor的 run 方法
                } // ......
            }
        });
    }
    
}

// TODO 待完成

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值