网络编程的模型与技术模型总结基本结论高效技术模型总结迭代方式并发方式–进程并发–线程并发–线程池/进程池–多核并发(绑定CPU核+流水线)IO模型–阻塞IO–非阻塞IO–IO复用–信号驱动IO–异步IO线程池/进程池缘起并发进程池/线程池技术–基本思想:准备一个池子,容纳预先创建的进程或线程,好处是省去了创建新进程或线程的时间–关键问题是如何把新连接分发给进程池中的一个进程?accept无上锁进程池中的所有空闲进程侦听服务端口,在accept()函数阻塞等待新连接建立,所有进程池中的进程被唤醒。系统调度进程池中的某个进程,从accept函数中返回,该进程为新进客户服务其余进程呢?依次被调度,但是由于listen队列中为空,再次被阻塞4.4BSD中的惊群效应(thunderingherd)accept的另一种方案使用IO复用模型——阻塞在select函数上–基本模型同accept–但是比accept方案更糟糕,原因是事件的发生新连接到达引发的,select更绕行一次accept上锁改进思路:让进程池中的进程依次访问accept函数,从而避免了为获得连接进程的调度开销,也就消除了惊群效应惊群效应的开销转嫁为锁的开销与锁的实现机制有关–文件锁–线程互斥锁进程池,分发连接描述符基本思想:–一个父进程负责侦听,子进程阻塞–当有新的连接,父进程把新socket传递给一个子进程与前述的accept方案相比,父子进程之间分工明确,避免了惊群效应子进程阻塞在进程间通信的管道上(不一定是PIPE)增加了进程间通信的开销,同时父进程必须跟踪子进程的状态,看它是否处于空闲描述符、空闲状态的传递线程池技术与进程池技术类似教材中省去了阻塞在accept函数的情况池技术与即时创建的对比并发的开销——调度+上下文切换+竞争与保护–相对于迭代方式,多出来的开销–调度,Linux的O(1)调度器–上下文切换–公共资源的保护如果连接数超过线程池的size,怎么办?教材中的结论:与其采用进程池/线程池技术,还不如直接采用即时创建线程进程池/线程池的例子apatch服务器Java线程池IO复用与非阻塞IO模型对比12.3sec,selectandblockingI/O(Figure6.13)6.9sec,nonblockingI/O(Figure16.3)8.7sec,fork(Figure16.10)8.5sec,threadedversion(Figure26.2)非阻塞IO程序设计复杂稍微复杂些应该采用多线程技术?C10K问题《ScalableNetworkProgramming》在服务器重负荷的情况下,采用多线程技术存在着如下的问题:–调度开销无法避免–共享资源保护的开销也无法避免–可扩展性受到限制线程控制块栈堆。。。这些开销加在一起,再乘以10000个客户?结论是:–在重负荷的服务器设计中IO复用和AIO模型是一个非常关键的要素。IO复用细节select函数的设计问题–受限于FD_SETSIZE–拷贝数据、O(n)的检查、多次检查poll解决了FD_SETSIZE的问题,但是设计仍然低效最佳的选择是:epoll、kqueue–epoll当前只支持文件上的读、写等事件,eventfd、signalfd、timerfd–kqueue支持文件添加、删除,AIO,进程fork、终止等,是一种更一般的事件通知机制。超时处理三种方法–alarm–select–SO_RCVTIMEO与SO_SNDTIMEO选项alarm采用异步信号机制select是同步机制alarm和select在多客户连接的情况下,如何管理?参考ACE简单的方法,推荐采用SO_RCVTIMEO与SO_SNDTIMEO,可惜与实现相关零拷贝技术应用程序内核网卡,报文零拷贝底层硬件scatter-gather支持内核mbuf/skbufreadv、writev、sendfile、TCP_CORK(Linux),TCP_NOPUSH(BSD)更多的参考C10K网站、《ScalableNetworkProgramming》、libevent、lighttpd、Boostasio库、ACE库。