Linux服务器框架设计思路

Linux服务器框架设计思路

关键词:进程池、线程池、协程、IO多路复用

多进程(进程池)

主进程侦听socket,将客户端socket分配给子进程去处理。这样编程简单,可能需要用到进程间的通信,但进程开销很大,并发量非常小。

多线程(线程池)

主线程侦听socket,将客户端socket分配给每一个线程去处理。这样编程较简单,但线程的创建和切换同样开销较大,并发量较小。

无论是进程池还是线程池,其作用都是为了减少进程/线程频繁创建和回收带来的性能损失,本质上依然是一个CPU指向单元在请求的生命周期内,只能服务这一个请求,就是说这个进程/线程被这个请求独占。而进程/线程的创建和管理需要消耗一定的操作系统资源,当进程/线程数量过多时,会导致系统资源耗尽,并且大量线程的切换也会有很大的开销,最终会使得服务不可用。
为了解决上述问题,有两种思路:第一种,在一个进程/线程中处理多个连接(IO多路复用,方式有select、poll、epoll)。第二种,使用比线程更细小的执行单元,例如协程。第一种需要使用异步的方式进行编程,第二种则可以使用同步的方式。现在主流的方式是将两种方法结合起来使用。
当有特别多的闲置连接或长连接时,IO多路复用的优势更为明显,因为能够节省更多的系统资源。如果是大量短连接的话,IO多路复用和多线程性能差距应该不大。

单个epoll+单线程

将侦听socket和连接客户端的socket都绑定在一个epoll上,且只有一个线程来应对这个epoll。当连接数比较多、来往数据比较多的时候,可能一个线程会忙不过来。

每个线程一个epoll

将侦听socker挂在线程A的epollA上,连接客户端的socket以某种策略分别挂载到线程B、线程C…上的epollB、epollC上,每个线程处理各自的连接和数据处理。

网络线程组+业务线程组

在上面两种情况下,如果业务逻辑处理过程比较耗时,会导致很久才能处理到下一个就绪的socket。这种情况下可以将一部分任务拆分出来,交给业务线程组去做。然而当网络线程组和业务线程组的线程数和超过CPU线程数时,网络线程组和业务线程组是不能并行执行的,同样会导致上述问题,这时还不如把任务全都在网络线程中做完。

主流做法:

按CPU核心数量开多线程,线程数量恒定不变,等于epoll数量。在每个线程中epoll收到连接后,不要另开线程去处理,而是用协程处理。
emmm…如果并发量不是特别大并且机器资源充足,使用多线程的方式处理高并发也是可以的,这样做的优点是开发简单,易于维护。

猜你喜欢

转载自blog.csdn.net/qq_38600065/article/details/108543014