11.1 I/O模型概览

        在1.3 C/S模式中,server端只有一个进程,等待连接时先进行阻塞accept系统调用,新连接到来时阻塞解除,然后进程使用read、write系统调用进行数据收发,最后调用close系统调用关闭新连接的socket。这种模式在server新建连接数和并发连接很多、吞吐量都很大的情况下效率会非常低,因为只有一个进程无法及时应对多条连接。为了使server端能更高效地处理更多的连接,就必须使用多进程(多线程),这时需要考虑一些问题:

(1)怎样组织这些进程(线程)使它们高效地工作?

(2)使用多进程还是多线程?

(3)进程怎样才能更及时的收到读写事件?

       下面来一一探讨这些问题,先考虑一下进程(线程)组织方法。

11.1.1 生产者-消费者模式

        将新连接的接受(accept)和处理(read、write、close)分开,执行接受任务产生新连接的称为生产者,使用新连接进行数据I/O的称为消费者。生产者调用accept系统调用生成新的socket,再将socket传递给消费者。使用这个模式就只能用多线程,不能用多进程,因为需要在生产者和消费者之间共享数据。生产者可以是多线程,消费者也可以是多线程。这种模式的优点是可以通过动态调整生产者线程和消费者线程的数量来更好地适应新建连接和数据I/O的任务量的变化,但缺点也很大:生产者与消费者之间的数据交互需要并发保护以防止数据不一致,而并发保护就需要线程间互斥,这就会产生性能损耗(很多时候线程需要等待),也会导致代码复杂度增大而影响稳定性(容易产生死锁);另外,还需要实现比较复杂的算法来避免消费者“饿死”和“撑死”的现象。

11.1.2 平等模式

        使用多进程(线程),每个进程(线程)负责接受一个新连接,完成数据收发任务,关闭连接,再接受下一个新连接。多个进程(线程)可以并发执行各自的任务,它们的任务是相同的,地位是平等的,这种模式称为平等模式。这种模式下各个进程(线程)间的数据共享很少甚至没有(除非相应的业务需要多个连接之间共享数据),也不需要任务分配,从而避免的生产者-消费者模式的问题。很多重要的网络应用(如果Nginx)使用的就是平等模式。

11.1.3 多进程 vs 多线程

        生产者-消费者模式只能使用多线程,平等模式既可以使用多进程也可以使用多线程。使用多进程的优点:

(1)一个进程崩溃不会影响其它进程

(2)进程间地址空间独立,多个进程可以同时打开更多的文件描述符

        缺点:

(1)进程的创建与销毁的开销较大,最好不要频繁进行

(2)进程间数据共享不便(可以使用共享内存,但比较麻烦,而且需要并发保护;使用其它进程间通信方法可能效率低,或无法满足需求)

        使用多线程的优点是:

(1)创建和销毁线程的代价比较小

(2)多线程间地址空间共享,数据传递方便

        缺点:

(1)多线程间的数据共享可能需要并发保护,这会增加代码复杂度,影响稳定性

(2)一个线程崩溃会导致所有线程退出,从而使服务中止

(3)一个进程能同时打开的文件描述符是有限的(理论上是65535个),使用多线程无法突破这个限制,即一个进程只能支持最多65535条并发连接

        究竟使用多进程还是多线程得看具体的应用需求。

11.1.4 轮询 vs 阻塞唤醒

        等待事件通知有两种方法:轮询和阻塞唤醒。

        轮询是指进程(线程)将socket设置为非阻塞,然后不断的循环进行accept系统调用或read系统调用,如果有事件则处理,否则一直循环。

        阻塞唤醒是指进程(线程)进行accept系统调用或read系统调用读取事件,如果没有事件则会阻塞,直到有事件被内核唤醒,处理完事件后再次阻塞等待唤醒。

        轮询的优点是进程能够及时处理事件,避免了睡眠-唤醒导致的状态切换;但缺点是进程(线程)会占用一个CPU导致其它进程无法使用这个CPU。

        阻塞唤醒的优点是有事件才响应,不会浪费CPU资源。缺点是睡眠-唤醒导致的状态切换会有一定的开销。不过当事件频繁到来时进程(线程)阻塞的机会也会比较少,所以状态切换的开销并不大。

        综合来看,阻塞唤醒机制通常要比轮询更好。

11.1.5 TCP高效I/O

        以上介绍了那么多,归根结底是要回答一个重要的问题:TCP如何进行高效的I/O?基于以上的分析,可以得出一种比较通用的高效I/O模型:平等模式 + 多进程 + 阻塞唤醒。阻塞唤醒可以使用epoll系统调用来完成,TCP也提供了支持epoll系统调用的机制,下节我们通过分析epoll系统调用的原理来了解一下TCP高效I/O是如何完成的。

发布了79 篇原创文章 · 获赞 46 · 访问量 22万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章