请求量上升时,服务不一定先被算力拖垮。文件描述符耗尽、连接队列溢出或数据库连接被占满,都可能让高并发服务器出现排队、超时,甚至间歇性不可用。以下六项配置适合按层检查;具体值应结合操作系统、应用框架和压测结果调整。
先检查系统能否接住连接
1. 文件描述符上限
Linux 会把网络连接、日志文件等作为文件描述符管理。进程上限过低时,即使机器仍有余量,应用也可能报“Too many open files”。检查进程实际限制及系统服务配置,再按预计并发连接、日志文件和其他句柄留出余量;修改 systemd 服务的 LimitNOFILE 后,需要重新加载配置并重启对应服务。不要只提高 shell 会话里的 ulimit,却遗漏服务进程的限制。
2. 连接队列与监听参数
内核的 net.core.somaxconn 会影响监听队列上限,应用自身也可能另设队列长度。两处不匹配时,单改一项未必有效。检查应用启动参数、内核限制和内核日志中的队列溢出信息,再在测试环境逐步调整。队列变长只能缓冲短暂突发,不能解决持续处理能力不足。
并发要与下游容量匹配
3. 应用工作进程和线程数
Nginx 的 worker 数量、应用线程池大小,都要与可用 CPU 核数、请求耗时和内存占用一起评估。静态响应与需要大量计算的请求,合适的并发规模并不相同。先记录基线,再用逐级增加并发的压测观察吞吐量、延迟和错误率;如果延迟随线程数增加而恶化,应检查锁竞争、上下文切换或下游等待,而不是继续堆线程。
4. 数据库连接池
以 PostgreSQL 为例,连接池限制应结合数据库允许的连接数,以及其他应用实例的连接需求来设定。应用副本数乘以单实例池上限,不能超过留给该服务的连接预算;还要为管理连接和其他业务预留空间。池太小会让请求等待,太大会挤占数据库资源。观察池等待时间、活跃连接和数据库响应时间,再调整上限与空闲回收策略。
避免故障被重试和资源耗尽放大
5. 超时与重试策略
为连接建立、读取响应和整体请求设置有边界的超时,避免请求无限占用工作线程。重试应限制次数,并仅用于适合重试的失败;写入操作还要考虑重复执行的后果。若多层服务都立即重试,短暂故障可能被放大成请求洪峰。高并发服务器应根据下游的正常响应时间分布设置超时,而非复制一组固定值。
6. 监控、限流与降级
至少跟踪请求延迟分位数、错误率、队列等待、进程内存、文件描述符使用量和数据库池等待。为关键资源设置告警阈值,并通过限流、拒绝非关键请求或关闭非核心功能,优先保护主要请求路径。阈值要由压测和日常基线确定,不能仅凭一次峰值拍板。
按顺序验证,避免只改参数
- 记录当前配置、错误日志及延迟和资源指标,确认瓶颈发生在哪一层。
- 一次只改一类参数,在接近预期峰值的测试负载下比较吞吐、延迟和错误率。
- 确认服务重启后配置仍生效,并检查回滚方式;上线后继续观察资源变化。
稳定性来自系统限制、应用并发和下游容量相互匹配。高并发服务器调优不应追求“数值越大越好”,而应找到瓶颈、验证改动,再把保护措施纳入日常监控。
常见问题
提高连接队列能增加处理能力吗?
不能。它主要吸收短时排队,持续超载仍需扩容、优化或限流。
文件描述符上限应设为多少?
没有适用于所有服务的固定值。按连接规模和其他句柄需求估算,并以压测及运行监控验证。
数据库连接池越大越好吗?
不是。池上限要受数据库连接预算约束,过大可能增加数据库竞争。
配置修改后如何确认有效?
检查服务实际生效值,并在相同测试条件下对比延迟、错误率和资源指标。