常见网络服务器并发模型

在这里插入图片描述

来源:微信公众号「编程学习基地」


近些年,随着互联网的大发展,高并发服务器技术也快速进步,从简单的循环服务器模型处理少量网络并发请求,演进到解决C10K,C10M问题的高并发服务器模型。本文结合自己的理解,主要以TCP为例,总结了几种常见的网络服务器模型的实现方式,优缺点,以及应用实例。

单线程循环

在这里插入图片描述

优点:

    简单、易于实现

    没有同步、加锁这些麻烦事,也没有这些开销

缺点:

    1、阻塞模型,网络请求串行处理

    2、没有利用多核cpu的优势,网络请求串行处理

    总之,没有充分利用CPU资源。

适用场景:测试、演示

典型应用:thrift TSimpleServer

多线程/多进程

在这里插入图片描述

解析:

    主要特点是每个网络请求由一个进程/线程处理,线程内部使用阻塞式系统调用,在实际场景中使用预先分配的进程池/线程池,以减少频繁创建销毁线程的开销,往往可以得到更好的性能。

    在线程的职能划分上,可以由一个单独的线程处理accept连接,其余线程处理具体的网络请求(收包,处理,发包);还可以多个进程单独listen、accept网络连接(在linux2.6内核之前会产生惊群,多个进程被唤醒accept建立连接)

优点:

    1、实现相对简单

    2、利用到CPU多核资源

缺点:

    1、线程内部还是阻塞的,举个极端的例子,如果一个线程在handle的业务逻辑中sleep了,这个线程也就挂住了。

典型应用:

单线程IO复用

在这里插入图片描述

解析:linux高并发服务器中常用epoll作为IO复用机制,select和poll等其他机制不展开讨论,区别和特点可以自行搜索。线程将需要处理的socket读写事件都注册到epoll中,当有网络IO发生时,epoll_wait返回,线程检查并处理到来socket上的请求。

优点:

    实现简单

    减少锁开销

    减少线程切换开销

缺点:只能使用单核cpu,handle时间过长会导致整个服务挂死。

适用场景:高IO、低计算,handle处理时间短

典型应用:redis

多线程/多进程IO复用

在这里插入图片描述

解析:每个子进程都监听服务,并且都使用epoll机制来处理进程的网络请求,子进程 accept() 后将创建已连接描述符,然后通过已连接描述符来与客户端通信。

优点:支撑较高并发

缺点:异步编程不直观、容易出错

适用场景:支撑高并发

典型应用:Nginx

多线程划分IO角色

在这里插入图片描述

解析:

    一个accept thread处理新连接建立

    一个IO thread pool处理网络IO

    一个handle thread pool处理业务逻辑

优点:

    按不同功能划分线程,各线程处理固定功能,效率更高

    可以根据业务特点配置线程数量来性能调优

缺点:

    1、线程间通信需要引入锁开销

    2、逻辑较复杂,实现难度大

电销应用:thrift TThreadedSelectorServer

AIO

在这里插入图片描述

linux AIO机制尚不成熟,没有广泛应用,不展开,感兴趣同学可以参考:

http://man7.org/linux/man-pages/man7/aio.7.html

协程

在这里插入图片描述

解析:就是在应用层用户态模拟线程,在用户态管理协程的调度与切换。

优点:

    1、减少上下文切换开销

    2、编程友好,同步的方式写出异步代码

缺点:多个协程运行在一个线程上,一个协程阻塞将导致整个线程阻塞

参考:

golang coroutine

libco

小结:上面介绍了常见的网络服务器模型,现实中可能存在其他的组合和变形,重要的是理解每种场景中所面临的问题和每种模型的特点,设计出符合应用场景的方案才是好方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值