美文网首页
来点并发

来点并发

作者: yueyoum | 来源:发表于2014-06-23 02:21 被阅读687次

如何提高吞吐量

快期末考试了,作为学霸的你(对,就是你!)忙的春光满面。
一大波学妹来让你辅导。
你把她们聚集到了大教室里,对她们说:一个一个来。很快一个妹子过来了,但却得等她翻书,找题,整理思路,甚至还要先照照镜子问你她漂亮吗,最后才慢吞吞的开始问你题。你眼看着后面排着长队的妹子在等着你,但你却只能如此缓慢的一个一个亲(禽)手(兽)辅导,效率真低。一天才能接触几个?

这就是 单进程单线程阻塞模式 。 如果遇到哪个妹子缠着你一天,你就别想接触其他妹子了。

改进一号

于是你想这么不行啊,妹子们需要你。于是你学会了分身术,把自己分成N个,同时给N个妹子服务,于是把妹效率提高了N倍。当你还在高兴的时候,问题出来了。

  • 教室就这么大,不可能把自己分身出太多,否则一个教室全是自己的分身,妹子进不来,搞毛啊。 不行,一定要限制分身的数量。此时你内心极度惆怅,唉,难道把妹效率有个不可逾越的鸿沟吗?

  • 尼玛,人可以分身,但水杯只有一个啊。你的分身老是轮流站着你的水杯,你早已饥渴难耐,却拿不到水杯。于是你规定,谁拿了水杯,就在黑板上标记一下。用完了,要及时把标记擦掉。这样其他分身如果看到黑板有标记,那就等等,当发现黑板没有标记的时候,你们就去抢,谁先抢到,他就去做标记,独享水杯。

但后来一些各种蛋疼原因,黑板上的标记没有被清除,于是你和你的分身们渴的实在没法辅导,于是把妹效率降低很多。

这就是 多进程/线程模式。 目前Linux很多经典的服务都是这种模型。

但缺点也显而易见:

  • 多进程/线程的数量在 一台机器 上数量是严重收限制的。

    早期一些服务是动态创建/销毁进程。在当时看起来很不错。链接多了,就多来点进程给那些大爷们服务。于是在大量链接的冲击下,服务不停的创建新进程,最终导致系统资源枯竭,服务器失去响应。(现在的Linux会直接杀死占用内存过多的程序,从而保证系统自身处于可响应状态)

    线程虽然轻量一点,但在Linux系统中,线程会占用8M栈空间,对于要保持长链接的请求,也不可能弄多少线程出来。

  • 来,让我们和锁一起愉快的玩耍
    
     不说了,你们先玩,我走了
    

关于多线程还有 leader-followHalf-Sync/Half-Async 等模式。它们对多线程做了很多优化,可以处理大量链接。但我并不了解,所以这里也不做陈述。

改进二号

恩,你想着要改进,于是先不分身了。
你有了新办法: 你首先请了你的死党,他就站在教室里。
然后你对妹子们说,谁准备好了要我来辅导,就先给我说一下,然后就准备着,等准备好了去给我兄弟说。我知道了就会叫你。

有妹子来到你这儿报名,然后她们就下去准备问题了。你就把她们的名字记在一张纸上,当你空闲的时候,你就把纸给你兄弟说,看看这上面谁准备好了,然后你兄弟告诉你谁好了,你就把那个妹子叫过来,搞定后,再次把名单给你兄弟,不停的这个循环。

但后来又发现问题了。

  • 纸太小,来报名的妹子太多,记录不下。

  • 你在空闲的时候得把整张纸给你兄弟,你兄弟要依次看一边名字,然后找出谁准备好了。最后,还要把纸给你传回去。

    你兄弟要抱怨了,尼玛老子不停的看这密密麻麻的名字,好累啊。跟你传纸的频率比老子lu的频率都高啊!

这是 基于事件的select 模式。(或者叫多路IO复用)
它的限制很多:

  • 你需要把要监听的fd加入一个列表中,Linux系统默认列表大小只有1024

  • 每次你都需要把这个fd列表传递给select调用。select调用再返回给你哪个fd上你感兴趣的事件触发了。也就是每次都需要从用户态->内核态->用户态这样拷贝一次。系统消耗太大
    

改进三号

恩,select方式要不停的轮寻,限制多多,效率也没高哪去。
于是你又改进了一下方式:

妹子还是到你这儿来报道,但你不用纸记录她的名字,而是立即告诉你兄弟,谁谁谁报名了,你留意下,她要是准备好了,你把她名字告诉我。

然后当你没事干的时候,就可以睡睡觉什么的。只要等着你兄弟来叫你就行了。

这就是 epoll/kqueue/ICOP 事件回调 机制.
epoll 对应Linux
kqueue对应BSD
ICOP对应Windows

不用 select 那样的去轮寻,而是注册fd和回调,等待事件通知即可。

libevent, libev 这些库就是将系统提供的事件回调机制的封装,供上层应用程序方便使用。


协程

当然,除了上面那些,还有一种模型,被称为协程。

特点如下:

  • 由程序自己产生,管理,调度,销毁。和OS没一点关系
  • 在一个OS进程中,可以产生百万级别的协程。
  • 基于协程的Actor模型不共享数据,写并发程序得心应手

目前支持协程的语言有

这里也得提一下 Scala,它也有Actor模型,而且akka库也很强大。但应该不属于协程范围。

Python 是通过 Gevent 库来实现的协程。

我在工作和自己的折腾中都用过Erlang和Gevent,从协程角度讲,它们都很好用。

  • Erlang 在各个process之间发送消息,不共享。没有锁的烦恼
  • Gevent可以让你用同步的方式来写异步程序

看起来协程好处多多,那么 它有什么缺点呢?

  • 因为协程还是运行在一个OS进程中,所以协程不能跑阻塞任务,否则就要将整个OS进程阻塞住了。

后面再写个文章具体讲讲我对Erlang和Gevent的看法

相关文章

网友评论

      本文标题:来点并发

      本文链接:https://www.haomeiwen.com/subject/klljtttx.html