看完phxrpc的协程使用方式后,我们拿Tars中的协程和其做个简单对比。
1 Tars中的协程模型
ServantHandle协程调度器.png
在TarsRPC源码解读篇:使用C++重写Tars-RPC主逻辑框架的3.2节中曾聊过Tars的协程切换流程。这里再复习一下。
- Tars协程模型也可以理解为活在同一个线程的几个子线程(协程)在一起协调有序工作,Tars中有明确主协程、从协程概念
- 主从协程都放在链表里
- 主协程是_coroSched->tar_run(),在循环中通过链表切换主协程和不同的从协程
- 从协程是通过_coroSched->createCoroutine创建的,是该方法中绑定的函数
再从链表调度角度看一下Tars的协程模型
- 第一步,将1号从协程加入到_avail链表
- 第二步,进入主协程的循环中,从_avail中取出第一个从协程(即1号从协程)进行切换。1号从协程中又创建了2号从协程放入_avail链表中,然后1号从协程让出当前工作,切换回主协程(注意,1号从协程是没有执行结束的,只是在等待下一次切换回来)
- 第三步,主协程从_avail链表中取出第一个从协程(即2号从协程)进行切换,2号从协程执行结束,从_avail表中删除2号从协程,切换回主协程,这时又回到了第二步进行处理
注意:主协程和1号从协程一直处于循环中,正常接收请求时是不会结束的。2号从协程每次执行完就会从_avail中删除
2 phxrpc协程模型
- phxrpc中主从协程是包装在里面的,没有_coroSched->tar_run()这样的主动调度,是一种顺序流的处理方式
- 上图中标记Yeild的地方,是函数体内在执行到yeild时,需要“跳出”当前函数,继续往下面执行
- 上图中标记Resume地方,是在执行到resume时,需要“跳出”当前流程,返回到yeild的地方继续执行
- 为了保证resume时回到应该去的地方,引入了socket->uthread_id来标记回到的位置
3 总结
- Tars中使用主动调度协程切换方式,phxrpc中使用顺序流切换方式
- Tars中使用链表,保证主协程和从协程的切换是可控和有序的,phxrpc中使用socket->uthread_id和一个vector保证切换到指定的协程中
- 可以看到,协程的引入帮助rpc框架做到了“顺序编写代码,异步执行逻辑”的效果,使得在一个线程中高效完成多个任务,减少了线程切换的开销
- 另一方面,个人感觉追踪协程的处理流程比直接用不同的线程更费劲,可阅读Tars中的协程与非协程方式体会