ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Linux 单机百万并发实战指南:C1000K 内核调优、文件描述符限制与内存评估(Go 夜读讨论实录)

Linux 单机百万并发实战指南:C1000K 内核调优、文件描述符限制与内存评估(Go 夜读讨论实录) 文档教程【免费下载链接】nightWeekly Go Online Meetup via BilibiliGo 夜读通过 bilibili 在线直播的方式分享 Go 相关的技术话题每天大家在微信/telegram/Slack 上及时沟通交流编程技术话题。项目地址https://gitcode.com/gh_mirrors/ni/night点击查看免费下载本文源自「Go 夜读」微信群 2018-07-02 的一场技术讨论原始记录完整还原了单机如何支撑 100 万并发连接这一经典 C1000K 问题的答案脉络从并发概念的澄清到fs.file-max/fs.nr_open内核参数与pam_limits.so模块的层层限制再到按 TCP 连接内存开销推算整机硬件需求。读完本文你将掌握判断一台 Linux 服务器能否扛住百万长连接的完整分析路径以及如何在 Go 长连接服务如 goim、qrpc 一类的推送/IM 框架落地这些内核层面的约束条件。讨论缘起一个错误理解并发的真实提问这场讨论的起因是群里一位同学分享了一篇千万级消息推送服务的文章随后另一位成员提到 goim哔哩哔哩在用的推送框架可以支撑百万级并发连接于是围绕单机百万并发展开了深入探讨。提问者坦诚地描述了之前的认知误区我以前对并发的理解几乎都是错的误以为每有一个客户端连接到服务器上就会多占用服务器的一个新 TCP 端口。这个误解需要首先澄清它是理解后续所有调优动作的前提端口不随连接数增长服务器对外只监听一个或少数几个固定端口所有客户端连接都复用这个监听端口。端口数量从来不是百万连接的瓶颈。连接对应的是文件描述符fd在 Linux 中一切皆文件每个 TCP socket 连接都会占用一个文件描述符。因此支撑并发连接数的第一个硬性约束就是系统与进程允许打开的文件描述符数量。换言之并发连接数的真正瓶颈在于内核允许的文件描述符上限 → 进程/用户的资源限制 → 物理内存能否承载这么多 socket三层缺一不可。第一层约束内核文件描述符参数fs.file-max与fs.nr_open服务能否支撑百万连接首先取决于内核参数。核心是fs.file-max与fs.nr_open两个参数它们的作用范围截然不同参数作用范围含义fs.file-max整个操作系统全系统允许创建的文件描述符数量最大值fs.nr_open单个进程每个进程各自最多可以打开的文件描述符数量两者的层级关系是fs.nr_open从属于fs.file-max它进一步限制了单个进程的上限而这两个值又共同构成了pam_limits.so模块所定义的可打开文件描述符数量的参数上限。查看与调整内核参数在 Linux 上可以通过/proc/sys/fs/伪文件系统直接查看当前生效值# 查看全系统文件描述符上限 cat /proc/sys/fs/file-max # 查看单进程文件描述符上限 cat /proc/sys/fs/nr_open调整方式有两种# 方式一临时生效重启失效 sysctl -w fs.file-max1000000 sysctl -w fs.nr_open1000000 # 方式二永久生效写入 sysctl 配置 echo fs.file-max 1000000 /etc/sysctl.conf echo fs.nr_open 1000000 /etc/sysctl.conf sysctl -p # 重新加载配置说明具体数值需要结合机器内存、文件系统类型和业务场景设定示例值仅供参考在较新的内核版本上调整会有更好的优化效果可优先确认当前内核版本后再实施。第二层约束pam_limits.so模块与用户级资源限制内核参数只是天花板实际生效时还要经过 PAMPluggable Authentication Modules这一层。pam_limits.so模块决定了每个用户和组可用的资源它通过limits.conf配置文件约束登录会话可打开的文件描述符数量从而间接规定了单个用户进程所能创建的 socket 最大数量。pam_limits.so对应的配置文件通常是/etc/security/limits.conf典型配置形如# 语法domain type item value * soft nofile 1000000 * hard nofile 1000000 root soft nofile 1000000 root hard nofile 1000000domain适用范围*表示所有用户也可指定具体用户名或用户组typesoft为软限制可被进程自行提高不超过 hardhard为硬限制仅 root 可提高itemnofile即打开文件描述符的最大数量value具体数值。配置后通常需要重新登录或重启服务使limits.conf生效。与之配套的还有命令行层面的检查工具ulimit# 查看当前 shell 进程的软/硬限制 ulimit -Sn # soft nofile ulimit -Hn # hard nofile # 临时修改当前会话 ulimit -n 1000000一条完整的检查链路应该是/proc/sys/fs/file-max系统级→/proc/sys/fs/nr_open进程级→limits.conf用户级→ulimit -n会话级。服务能否支撑百万连接数首先取决于内核参数然后取决于pam_limits.so模块的限制——任何一层没有放行百万连接都无从谈起。第三层约束内存开销估算——百万连接到底要多少内存文件描述符限制解决的是能不能打开的问题内存则决定扛不扛得住。讨论中对每个 TCP socket 连接占用的内存做了如下估算每个 TCP socket 连接大概占用4 KByte内存维护 100 万连接的裸开销为1000000 × 4KB ≈ 4 GByte这 4GB 还没有计算发送消息的开销保守估算整体需要的内存是16 GByte。据此可以推演两种截然不同的业务场景推送场景服务端主动发消息如果要向这 100 万客户端逐一推送消息每个连接都需要维护发送缓冲区、协议状态等额外内存且同一时刻大量连接同时写数据会对 CPU、带宽和内存形成多重压力非常吃力请求汇聚场景客户端排队发请求如果是 100 万客户端排队发送请求服务端完全可以采用轮询处理队列里的请求的方式内存与带宽的峰值压力远小于前者可行性高得多。这也解释了为什么业界百万连接的经典案例大多集中在长连接 低频心跳 少量下行推送如消息推送、IM 在线状态这类流量模型上而不是高频双向通信。仓库延伸Go 生态下的百万连接实践证据讨论中提到的 goim 正是百万级并发连接在 Go 生态中的代表。本仓库 content/night/45-2019-05-30-goim-reading.md 记录了「Go 夜读」第 45 期《goim 架构设计与源码分析》的专题分享说明 goim 这类基于 Go 实现的 comet/推送框架正是把上面这些内核与内存约束落到工程实践的代表案例。而「Go 夜读」第 73 期《趣头条在长链接方面的实践 - qrpc》content/night/73-2019-12-28-qrpc.md则从工程落地角度给出了几个与本文讨论高度呼应的细节80W 连接如何做到分享中有人问不用 epoll 怎么保持 80W 连接答案是——Go 内部所有连接都已经用 epoll或各平台对应物接管了在 Go 运行时层面网络 I/O 早已是多路复用模型无需业务层再手工集成 epoll协程与连接的取舍qrpc 自己再做集成的好处是可以把闲置的协程释放掉——即长连接数量巨大时每个连接对应一个 goroutine 的朴素模型会产生大量闲置协程工程上需要对协程模型做进一步优化例如分享中提到的通过抢占锁合并写请求、用writev批量写来换取内存与性能收益心跳与可靠性qrpc 在 TCP 层内置心跳TCP 本身已保证传输可靠性上层只需处理连接断开后的重连同步。从这些分享可以看出单机百万连接在 Go 生态中不是理论假设而是推送中台、IM 网关等真实场景的日常需求但它的前提正是本文前面所述的内核参数放行 PAM 用户限制放行 内存预算充足三大条件。结语从能不能到如何设计的分析路径回看这场讨论最值得沉淀的是一套完整的分析路径纠正概念并发连接不占新端口占用的是文件描述符与内存检查内核fs.file-max决定全系统 fd 上限fs.nr_open决定单进程上限检查 PAMpam_limits.so/limits.conf决定用户级可打开 fd 数量配合ulimit -n验证核算内存按每个连接约 4KB 起步估算预留发送缓冲区等开销百万连接保守按 16GB 内存规划选择流量模型优先设计为客户端排队请求 轮询处理或低频心跳长连接模型避免高频全量推送的峰值压力。「Go 夜读」后续相关专题还包括 第 65 期 Go net 包源码阅读、第 68 期《网络知识十全大补丸》 等分享可以作为继续深入网络并发主题的仓库内阅读线索。赞分享文档教程【免费下载链接】nightWeekly Go Online Meetup via BilibiliGo 夜读通过 bilibili 在线直播的方式分享 Go 相关的技术话题每天大家在微信/telegram/Slack 上及时沟通交流编程技术话题。项目地址https://gitcode.com/gh_mirrors/ni/night点击查看免费下载相关推荐深入理解GE推理上下文如何获取算子形状推导的关键信息深入理解GE推理上下文如何获取算子形状推导的关键信息 在昇腾AI处理器开发中图编译器Graph Engine简称GE扮演着至关重要的角色。今天我们要深人工智能深度学习模型编译模型优化编译器Ascend10个Agentic Context Engine (ACE)实用技巧提升智能体性能的完整清单10个Agentic Context Engine ACE 实用技巧提升智能体性能的完整清单 Agentic Context Engine ACE 是一个基于突破百万连接uWebSockets高性能服务器的文件描述符与内核调优指南突破百万连接uWebSockets高性能服务器的文件描述符与内核调优指南 你是否曾因服务器在高并发下频繁崩溃而头疼是否遇到过too many open f后端网络消息路由WebSocket上一篇如何利用OpenCodeEval评估你的代码大模型HumanEval、MBPP、BigCodeBench实战教程下一篇GeoNet训练秘籍从rigid模式到flow模式的参数配置与优化技巧创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表