多线程与并发服务器设计

第一种、循环式/迭代式服务器

多线程与并发服务器设计_第1张图片

每处理完一个请求就关闭连接,这种模式称为短连接。循环式服务器只能够使用短连接,而不能够使用长连接。如果是长连接,处理完一个请求,write完不关闭连接而是循环到read这里接受下一个请求。而整个程序是一个单线程的程序,如果另一个程序请求过来就不能接受请求了,只能处理一个程序。要想处理多个客户端只能够短连接。这种服务器不是真正意义上的并发服务器,decode、compute、encode 不能处理太长,如果太长就会影响其他连接的响应时间。这个程序是单线程的程序,不能利用多核CPU。一个CPU处于繁忙状态其他处于空闲状态。

第二种、并发服务器

一个请求一个线程、一个请求一个进程

多线程与并发服务器设计_第2张图片 

子进程处理客户端请求,子进程是一个长连接 。并发服务器能够处理多个客户端,一个线程一个客户端或者一个进程一个客户端,所以能够处理多个客户端。而且他也支持服务时间较长的客户端请求,不影响其他客户端的请求。 如果是线程主进程就不用close了,因为线程不会复制连接套接字 。子进程要关闭监听套接字的,这里没有画出来。

第三种、预先创建进程或者预先创建线程

多线程与并发服务器设计_第3张图片 

子进程也是接受连接,读取数据处理发送数据 ,和并发服务器是类似的。

这里有个问题,当一个客户端连接过来的时候,多个进程处理accept这样的循环当中,那么这时候就有可能多个accept进程返回了,只有一个进程accet 返回时正确的,其他进程返回是失败的,这种现象称为惊群现象。如何解决惊群现象,看UNP2e 27章。这种服务器有很多的变种。

也可以预先创建线程,这种服务器和第二种并发服务器的区别在哪儿呢?它减少了创建线程或创建进程的开销,因为这些线程或者进程预先创建好了,能提高响应速度。

第四种、反应式(reactive)服务器 (使用了reactor模式)

select实现反应式服务器, 单线程轮询多个客户端。并发处理多个请求,实际是在一个线程中完成的。无法充分利用多核CPU。

多线程与并发服务器设计_第4张图片

单线程的,无法利用多核CPU。但是它的并发量比并发式来的多。因为并发式线程或者进程创建的个数是有限的 。由于是在单线程完成的,所以也不适合执行时间长的服务。 所以为了让客户感觉是并发处理的而不是循环处理,每个请求必须在相对较短的时间内执行。

第五种、reacor + thread per request 

每个请求过来创建一个线程,这个请求可能执行的时间比较长,我们就可以创建一个线程来执行它。如果有很多的请求过来可能就创建很多的线程 ,更好的办法是创建一个线程池。可以利用多核CPU。

第六种、reactor + thread pool

多线程与并发服务器设计_第5张图片

 能够处理计算密集型任务。

第七种、multiple reactors  

能适应更大的突发IO

每个线程都有一个reactor事件循环Event loop,或者每个进程都有一个reactor。

多线程与并发服务器设计_第6张图片

mainReactor 加入accept,当接收到一个连接请求,就轮叫(round robin)的放入subReactor 中 ,保证mainReactor能够均匀的分配到subReactor 中。

什么时候能用到reactor呢?一个reactor能够适应一个千兆网口。如果一个服务器有3个千兆网口,就分配3个reactor。加上mainReactor 4个。

这些reactor也是线程,我们可以把它看成IO线程池。这些IO线程的个数是固定的,一开始就创建好了。根据千兆网卡的数目来确定IO线程数。

如果请求量过大decode\comput\encode ,是否可以放到线程池中处理呢 ,如果放在线程池中处理,既可以应对突发的IO,又可以处理密集计算。这是一个更好的方案。

第九种、multiple  reactor + thread pool 

这里的multiple reactor 是没有办法用进程的,因为进程是没有办法共享线程池的。既可以应对突发的IO,又可以处理密集计算。这种模式是相当完美的一个模型。

多线程与并发服务器设计_第7张图片 有多个subReactor 把reactor的计算丢到线程池中处理,应答包丢到reactor 来应答。多个reactor共享一个线程池。这里相当于两个线程池,IO线程池和计算线程池。

第十种、proactor 服务器 (proactor模式,基于异步IO)

同步IO和异步IO的区别?

异步IO以回调的方式返回,以推的方式从内核到应用层,同步IO是拉的方式从内核到应用层。

充分发挥计算机的DMA特性,IO操作不涉及到CPU的干预。多线程与并发服务器设计_第8张图片

问题

Linux能同时启动多少个线程?

 对于32位的Linux来说,一个进程的地址空间是4G,其中用户能访问的空间是3G左右,而一个线程的栈默认大小是10M,一个进程大约能最多创建300个线程左右。

多线程能提高并发度吗?

如果是一个请求一个线程,并不能提高并发度,比方说上面例子最多300个,如果是reactor轻松几千上万。

你可能感兴趣的:(服务器,运维,http,linux,c++)