F0731189e3aa80bb0a372431e6b5d671
关于协程的思考

场景

海量互联网服务端和一般的计算机程序相比,特点是:

  • 高并发:每秒钟需要处理成千上万的用户请求
  • 周期短:每个用户处理耗时越短越好,经常是ms级别的
  • 高网络IO:经常需要从其它机器上进行网络IO、如Redis、Mysql等等
  • 低计算:一般CPU密集型的计算操作并不多

过去的方案

为了避免频繁的上下文切换,还有一种异步非阻塞的开发模型。那就是用一个进程或线程去接收一大堆用户的请求,然后通过IO多路复用的方式来提高性能(进程或线程不阻塞,省去了上下文切换的开销)。Nginx和Node Js就是这种模型的典型代表产品。

  • 好处:从程序运行效率上来,这种模型最为机器友好,运行效率是最高的(比下面提到的协程开发模型要好)。所以Nginx已经取代了Apache成为了Web Server里的首选。
  • 坏处:这种编程模型的问题在于开发不友好,说白了就是过于机器化,离进程概念被抽象出来的初衷背道而驰。人类正常的线性思维被打乱,应用层开发们被逼得以非人类的思维去编写代码,代码调试也变得异常困难。

协程的出现

就有一些聪明的脑袋们继续在应用层又动起了主意,设计出了不需要进程/线程上下文切换的“线程”,协程。用协程去处理高并发的应用场景,既能够符合进程涉及的初衷,让开发者们用人类正常的线性的思维去处理自己的业务,也同样能够省去昂贵的进程/线程上下文切换的开销。因此可以说,协程就是Linux处理海量请求应用场景里的进程模型的一个很好的的补丁。

根据这篇文章(协程究竟比线程能省多少开销?)当中的测试

平均每次协程切换的开销是(655035993-415197171)/2000000=120ns。相对于前面文章测得的进程切换开销大约3.5us,大约是其的三十分之一。比系统调用的造成的开销还要低。

协程内存开销
在空间上,协程初始化创建的时候为其分配的栈有2KB。而线程栈要比这个数字大的多,可以通过ulimit 命令查看,一般都在几兆,作者的机器上是10M。如果对每个用户创建一个协程去处理,100万并发用户请求只需要2G内存就够了,而如果用线程模型则需要10T。

top Created with Sketch.