调度中心UThreadEpollScheduler也是一个基于epoll的模型。与Tars RPC不同的两点是:
- UThreadEpollScheduler将管道操作符注册到了epoll,外部对epoll的调度都是通过往管道里写入字符完成的。
- UThreadEpollScheduler在一个线程里完成了请求的处理和结果的发送。这得益于协程的引入。
1 调度中心概览
刚开始读协程部分的代码时,感觉有点别扭。虽然在HshaServerIO::IOFunc函数里看似顺序的处理了请求和发送了结果,但在数据流程跟踪上还是要不停的来回切换。为了方便刚开始阅读代码的同学快速了解,奉献出下面这张宝图。
phxrpc-调度中心.jpg
几个关键点:
- 为了理解方便,可以把三个紫色框EpollNotifier::Func、epoll_wait、HshaServerIO::IOFunc理解为活在一个线程里的三个子线程。
- 这三个子线程之间的有序工作是依靠Yield和Resume来调度的。
- epoll_wait的激活条件是通过向管道操作符写入数据,见图中两个椭圆对话框。
2 协程间切换逻辑说明
- EpollNotifier::Func将管道操作符socket1注册到epoll中,让出当前工作,切换到epoll_wait等待中
- 外部客户端成功建立链接时,会向socket1中写入数据,激活epoll,这时会再切换回EpollNotifier::Func
- 在EpollNotifier::Func中将socket1从epoll中删除,进入下一个循环,重新注册socket1,让出当前工作,切换回epoll_wait中
- epoll_wait中,在ConsumeTodoList里处理HshaServerIO::IOFunc函数,切换到HshaServerIO::IOFunc函数中
- HshaServerIO::IOFunc开始接收请求数据,并放到请求队列中,接着让出当前工作,回到epoll_wait中
- Worker处理完请求,把结果放入结果队列后,同样会向管道操作符写入数据,激活epoll
- 这时会重复上面2、3步骤操作
- 在epoll_wait中,处理HshaServerIO::ActiveSocketFunc(),Resume到socket2在的HshaServerIO::IOFunc中,完成结果的发送