测试技术老大应该有的修养

2018-05-25  开心的小麻花 

  前两篇 文章我们用 面向对象的思想,分析了一个 操作系统的基本构成和设计思路。今天我们继续来聊Web和应用服务器的设计,聊一下怎么高效的利用网络IO和CPU资源。
   Socket对象
  上一篇我们聊到,操作系统通过核心表中的对象来管理网络IO,这个对象就是Socket类。我们来看一下整个读取和发送数据的过程。
  我们把Socket对象比作快递公司,他帮助大家收发各种快件。Socket的IP、端口号和进程ID等信息就是货物的具体地址。当我们寄送快递的时候,快递员上门取货,但是他不会直接送往目的地,而是先送往中转站。为什么要这么做,因为把发往同一个地点的货物合并发送,当然效率更高。Socket发送数据也是如此,他会先将数据发送到缓冲区中,然后再一起发送。
  同样,收快递的时候,货物也会先发送到配送点,然后再由快递员送货上门。Socket接收数据也是如此,会先存在缓冲区中。我们上一篇聊过,核心对象的数据是存在核心态地址空间中,用户进程是没法直接读取的。我们需要把数据从核心态拷贝到用户态,才可以访问。
   高效Socket读取
  Socket的读取和写入默认都是同步的过程,对用户线程来说就是阻塞的。发送数据的情况还好,不会等待多久;读取数据就比较尴尬,因为我们不知道对方什么时候会发送数据,也就不知道要等多久;对一个高性能的Web或者应用服务器来说,解决这个问题就是最重要的。下面我们看看对这块的解决方案是怎么演化的。
   同步阻塞模型
  最简单的方式就是同步阻塞式读取。对应到服务器设计上,每来一个网络请求,我们就生成一个线程来服务。没有请求数据的时候,这个线程就阻塞着。这就是同步阻塞模型。
  同步阻塞模型最大的问题就是,没有数据的时候也要无谓的等待。这种设计的确会浪费线程和Socket资源,但是这种模型足够简单,开发容易。如果并发量并不大的情况,可以考虑采用。
   同步非阻塞模型
  我们改进一下,在读取数据之前,先检测一下,如果这时没有数据,就先去干点别的。这就是同步非阻塞模型。
  采用这个模型,只需要Socket读取数据的时候设置成非阻塞就可以。但是这种模型缺点也很大,每个用户线程总要轮询去检测,如果一直没有数据,就白白浪费了计算资源。
   多路复用模型
  再优化一下,如果我们只用一个线程去做所有Socket的检测工作,当真正有数据到达的时候,再提醒用户线程去处理。这样就很好的解决了同步非阻塞模型的缺点。这就是多路复用模型。 Linux的epoll就是这样的方式。
  这里我们要考虑一点,多路复用模型只有一个线程做检测工作,增加了服务器处理请求的能力,但是如果并发量并不大的时候,其实性能并没有提高。
  异步模型
  前面所说的各种模型,都需要我们自己做大量的工作。有没有一种方式,让操作系统把全部工作承包了呢。当然是有的。操作系统来监听Socket,当有数据到来时,读取这个数据,拷贝数据到用户态进程空间,完成这一切工作后,再来告知我们。这就是异步模型, Windows操作系统的完成端口模式就是这样的方式。
  总结一下,对服务器设计来说,高效管理网络IO和CPU资源很重要,我们聊了4种不同的模型设计。

240°/2400 人阅读/0 条评论 发表评论

登录 后发表评论