文章摘要
文章讨论了网络服务器编程的两种设计模式:传统模式使用主循环等待事件并分发处理,或通过多线程处理;作者推荐更高效的方案,即利用epoll/kqueue系统调用,每个CPU核心绑定一个线程并独立管理事件,以提高性能。
文章总结
高效网络服务器设计指南
在网络服务器编程领域,存在一种极为普遍的设计模式: 1. 主循环等待事件触发 2. 根据文件描述符及其状态进行任务分发 这种传统设计要么采用fork()创建多线程处理,要么依赖内核调度工作线程。
基于epoll/kqueue的更优方案:
通过合理利用epoll(Linux)和kqueue(BSD)系统调用,可以实现更高效的服务器架构。核心设计原则包括: 1. 每个CPU核心绑定一个独立线程,各自维护专属的epoll/kqueue实例 2. 不同状态转换(如接收连接、读取数据)由专门线程处理 3. 客户端状态迁移时通过传递文件描述符实现线程间协作
性能优势:
• 消除决策分支点 • 采用简单阻塞式I/O调用 • 单页代码即可实现10万QPS的高性能服务
实现要点:
【线程池创建】
- 动态获取CPU核心数,允许人工调整
- 设置线程属性为系统级、分离状态
- 核心代码示例:
c
t=sysconf(_SC_NPROCESSORS_ONLN);
for(i=0;i<t;++i) pthread_create(&id,&a,(void*)run,(void*)i);
【CPU亲和性设置】
- Linux使用pthreadsetaffinitynp()
- macOS需通过Mach线程API实现:
c
thread_policy_set(mach_thread_self(), THREAD_AFFINITY_POLICY, ...);
【监听套接字优化】 - 调整文件描述符上限(建议每线程2048个) - 禁用SOLINGER避免描述符耗尽 - Linux启用TCPDEFER_ACCEPT延迟应答
【连接处理流程】
1. 专用accept循环直接接收新连接
2. 通过轮询算法分配工作线程:
c
int pick(){ static int c; return worker[++c%t].q; }
3. 设置接收超时(SO_RCVTIMEO)和非阻塞模式
【请求处理优化】 - 使用大容量事件数组(如1000个事件/次) - 单文件描述符严格对应单一请求状态 - 复杂操作拆分为多个系统调用时需重新调度
注意事项:
• Linux可组合使用accept4()替代accept()+fcntl() • 特定场景可改进pick()算法实现负载偏好 • 务必通过基准测试验证优化效果
评论总结
以下是评论内容的总结:
关于架构设计的讨论
- 有评论认为这种设计与SEDA架构类似,但现代硬件上传递文件描述符可能导致性能问题(缓存抖动)。
引用:"physically passing file descriptors between different cores... is usually a performance killer" (epicprogrammer)
引用:"separating stages per thread... would waste an entire core" (luizfelberti) - 也有观点认为这种分阶段设计类似Erlang的可扩展模型。
引用:"what Erlang does and how Erlang is so easy to scale" (fao_)
- 有评论认为这种设计与SEDA架构类似,但现代硬件上传递文件描述符可能导致性能问题(缓存抖动)。
技术实现建议
- 建议使用现代技术如iouring替代旧方案。
*引用:"for Linux you'd probably use iouring nowadays" (luizfelberti)* - 提出负载均衡和阶段数量的问题。
引用:"how many stages a typical server might... does it create a load-balancing problem?" (bee_rider)
- 建议使用现代技术如iouring替代旧方案。
其他观察
- 有评论指出图表重复的问题。
引用:"why is the first diagram duplicated at .1 opacity?" (kogus) - 有用户对网站域名表示怀念。
引用:"lovely to see its still around" (rot13maxi)
- 有评论指出图表重复的问题。
参考信息
- 提供了2016年的讨论链接和性能基准测试链接。
引用:"discussed in 2016" (ratrocket)
引用:"review the latest techempower web framework benchmarks" (password4321)
- 提供了2016年的讨论链接和性能基准测试链接。