并发服务器模型主要有迭代、多进程/多线程、进程池/线程池、I/O多路复用、Reactor/Proactor、协程等,选型取决于连接数、业务计算密度和部署环境。 如果你正在搜“并发服务器模型有哪些”,大概率遇到了连接数上涨、传统多线程扛不住的问题,下面从实现原理到选型成本,一次讲清。
并发服务器模型有哪些?五种主流方案拆解
迭代服务器:最简单,也最容易被压垮
迭代服务器就是单线程循环处理,服务端accept一个连接,处理完再accept下一个,内部小工具、低频管理接口可以用,但连接一多,后面的请求只能排队。
- 优点:代码短,没有锁,没有上下文切换。
- 缺点:一次只能服务一个客户端,吞吐量极低。
- 典型场景:本地调试、一次性脚本、串口通信转发。
多进程模型:隔离好,进程切换贵
多进程模型由主进程fork子进程,每个子进程处理一个连接,Apache的prefork模式就是代表,一个子进程崩溃不会影响其他进程。
- 优点:隔离性强,编程简单。
- 缺点:进程创建和切换开销大,内存占用高。
- 实操观察:
ps -efL查看进程数,pidstat -w看上下文切换。
多线程模型:共享内存,锁竞争是门槛
多线程模型让每个连接对应一个线程,线程共享地址空间,创建比进程轻,但共享数据要加锁,锁竞争会吃掉CPU。
- 优点:内存复用好,适合短连接。
- 缺点:线程安全复杂,一个线程崩溃可能拖垮整个进程。
- 常见坑:线程池大小没调好,任务队列堆积导致超时。
I/O多路复用:select、poll、epoll的进化
I/O多路复用用一个线程管理多个连接。select有文件描述符数量限制,poll改进了限制但仍是线性扫描。epoll用红黑树加就绪链表,适合高并发。
据Linux man-pages说明,epoll在Linux 2.6内核引入,支持水平触发和边缘触发,边缘触发必须配合非阻塞I/O,一次把数据读干净。
-
核心调用:
epoll_create1、epoll_ctl、epoll_wait。 - 典型服务:Nginx、Redis、Node.js底层。
- 场景:十万级长连接推送、API网关。
协程与异步I/O:现代高并发服务器模型
协程是用户态轻量级线程,切换成本远低于内核线程,Go的goroutine、Java虚拟线程、Python asyncio都属于这个思路,异步I/O方面,Windows有IOCP,Linux有io_uring。
- 优点:极高并发,代码接近同步写法。
- 缺点:需要运行时或框架支持,调试难度略高。
- 建议:新项目可以优先评估协程,老项目先优化线程池。
高并发服务器模型怎么选?从业务场景倒推
短连接API服务:线程池加epoll
短连接请求来得快去得快,可以用epoll做事件分发,再把业务逻辑丢给线程池,这样既避免每连接一线程,又不会阻塞事件循环。
- 步骤:主线程
epoll_wait,收到可读事件后封装任务,投递到线程池。 - 注意:线程池大小按CPU核数和阻塞比例调,通常核数乘以2到4。
- 命令:
top -H查看线程CPU占用,ss -s看连接状态。
长连接推送:多Reactor多线程
长连接场景下,连接数可能几十万,单Reactor单线程容易成为瓶颈,多Reactor多线程把监听和读写分开,每个SubReactor管一批连接。
- 主Reactor负责
accept,把新连接分给SubReactor。 - SubReactor各自跑
epoll_wait,处理读写。 - 典型:Netty主从Reactor、Nginx多进程加epoll。
计算密集型:多进程加共享内存
如果业务是视频转码、加解密、压缩,CPU是瓶颈,多进程能利用多核,进程间用共享内存或消息队列通信。
- 优点:避免GIL,避免线程锁。
- 缺点:数据同步复杂,内存拷贝多。
- 场景:转码集群、科学计算服务。
模型对比表
| 模型 | 连接数 | 上下文切换 | 内存开销 | 开发难度 | 典型服务 |
| 迭代 | 极低 | 无 | 低 | 低 | 内部小工具 |
| 多进程 | 中 | 进程切换贵 | 高 | 中 | Apache prefork |
| 多线程 | 中高 | 线程切换 | 中 | 中 | Tomcat BIO |
| epoll Reactor | 高 | 事件回调 | 低 | 高 | Nginx、Redis |
| 协程 | 极高 | 用户态切换 | 低 | 中高 | Go net/http |
| io_uring Proactor | 极高 | 内核异步 | 低 | 高 | 现代数据库 |
行业共识认为,没有一种模型能通吃所有场景,先看连接数,再看单连接计算量,最后看团队技术栈。
Linux下并发服务器模型实战:从epoll到io_uring
先查系统限制,再谈并发
很多并发问题不是模型不行,是系统限制没放开。
- 查看当前进程文件描述符限制:
ulimit -n - 查看系统总限制:
cat /proc/sys/fs/file-max - 查看监听队列:
sysctl net.core.somaxconn - 临时调整:
sysctl -w net.core.somaxconn=65535 - 查看连接状态:
ss -s、ss -lnt
epoll编程最小步骤
- 创建epoll实例:
int epfd = epoll_create1(0); - 添加监听套接字:
epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fd, &ev); - 循环等待:
int n = epoll_wait(epfd, events, MAX_EVENTS, -1); - 对每个就绪事件处理
accept或read。 - 边缘触发下,
accept要用循环直到EAGAIN。
调试命令:strace -e epoll_wait -p PID观察事件触发。
io_uring入门路径
io_uring是Linux新的异步I/O接口,它用提交队列和完成队列减少系统调用,入门可以看liburing库。
- 安装:
apt install liburing-dev - 初始化:
io_uring_queue_init - 提交请求:
io_uring_submit - 收割完成:
io_uring_peek_cqe
适合数据库、存储引擎、高性能代理。
压测与观察
别凭感觉选模型,用wrk或ab压测。
wrk -t4 -c1000 -d30s http://127.0.0.1:8080/- 观察CPU:
pidstat -u 1 - 观察上下文切换:
pidstat -w 1 - 观察内存:
free -m
如果cs上下文切换极高,说明线程或进程模型开销大,如果
%sys高,可能是锁竞争或系统调用过多。
并发服务器模型选型成本:人力和机器怎么算
小团队:优先线程池或协程
小团队人手有限,别一上来手写epoll,用成熟框架更划算,Java用Netty或虚拟线程,Go用net/http,Python用asyncio,招聘有epoll底层经验的工程师成本较高,一线城市和二三线城市差异明显,培训费用和时间也是隐性成本。
大流量:Reactor加多进程
日活上来后,单机连接数可能破十万,Nginx的多进程加epoll是稳妥方案,每个worker绑定一个CPU核,减少切换,配置路径:/etc/nginx/nginx.conf,设置worker_processes auto;和worker_connections 10240;。
云原生:容器与负载均衡
Kubernetes里,Pod本身可以跑多线程或协程,水平扩展靠Deployment副本数,Service做四层负载,Ingress做七层,此时并发模型更多是进程内选型,跨节点靠编排。
业内专家指出,选型要算总拥有成本,包括开发、运维、机器和故障排查。
Q&A:并发服务器模型有哪些常见落地疑问
并发服务器模型有哪些适合Java?
Java常见BIO、NIO、Netty、虚拟线程,BIO适合连接数少的内部服务,NIO基于Reactor,Netty封装了主从Reactor,JDK 21虚拟线程让阻塞式代码也能高并发,选择看团队熟悉度,Netty生态最成熟。
高并发服务器模型怎么选才不踩坑?
先压测再决定,步骤:写最小原型,用wrk压到目标连接数,观察CPU、内存、上下文切换和错误率,如果多线程模型在1000连接时cs已经很高,就换epoll或协程,不要盲目上io_uring,除非有存储或网络异步需求。
Linux并发服务器模型和Windows IOCP有什么区别?
Linux epoll是就绪通知,告诉你哪些文件描述符可读可写,Windows IOCP是完成通知,告诉你异步操作已经完成,Linux的io_uring补齐了完成通知能力,两者编程模型不同,跨平台框架通常会做适配。
并发服务器模型没有银弹,选型要匹配连接规模、计算密度和团队技能。 从epoll到io_uring,核心是减少上下文切换和无效轮询。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/752508.html





