EC2接入ELB后负载能力下降 频发504网关超时错误求解决方案
核心根因
当前配置存在多处ELB与后端Apache的参数错配,直接导致接入ELB后集群性能腰斩,触发504网关超时:
- 超时参数完全失配:ELB全量响应、健康检查超时设为300秒,Apache全局超时设为600秒,过长的超时会导致大量无实际请求的空闲连接、异常卡死的请求长期占用Apache工作进程,工作线程无法及时释放处理新请求;同时300秒的健康检查超时会让已经过载卡死的实例长时间被判定为健康,持续接收流量触发雪崩。另外Apache超时(600s)长于ELB空闲超时(300s),会在服务器端产生大量
CLOSE_WAIT状态的半开连接,进一步挤占连接资源。 - 路由策略不合理:均等轮询策略完全不感知后端实例的实际负载、空闲连接数,就算某台实例已经被占满,仍会按固定比例转发请求,极易出现单点过载。
- 服务配置未适配反向代理场景:单实例直连承载500用户的参数是适配公网端侧用户连接行为的,接入ELB后连接来源为ELB固定内网IP,连接复用率、请求密度远高于直连场景,原有Apache的工作进程配置、长连接规则未做适配,会导致资源利用率大幅下降。
优化方案
按优先级从高到低调整,改完前两项基本就能解决80%以上的性能问题:
- 第一优先级:修正全链路超时参数
- ELB侧:空闲连接超时(即你说的全量响应超时)按业务实际最长请求时长设置,普通Web业务设为30-60秒即可,大文件上传/长接口场景最高不要超过180秒,禁止无脑设为300秒;健康检查超时调整为5秒,检查间隔10秒,不健康阈值2次,健康阈值3次,保证过载实例能被快速摘除。
- Apache侧:全局
Timeout参数和ELB空闲超时对齐,不要设为600秒;开启KeepAlive的前提下,将KeepAliveTimeout设置为比ELB空闲超时小5秒(比如ELB超时设60秒,该值就设55秒),从根源避免CLOSE_WAIT半开连接堆积。
- 第二优先级:替换ELB路由策略
- 把当前均等轮询策略替换为「最少待处理请求」路由模式,让ELB优先把请求转发给当前空闲工作进程最多的实例,避免无脑平均分配导致的单点过载。
- 开启ELB慢启动功能,给新加入集群、刚重启恢复的实例设置60-120秒的流量爬坡期,避免实例启动阶段就被大流量打挂。
- 第三优先级:调整Apache配置适配ELB代理场景
- 优先把Apache的工作模式从prefork切换为event模式,反向代理场景下event模式的并发承载能力是prefork的2-3倍。
- 开启
mod_status模块实时监控工作进程状态,压测时如果处于KeepAlive等待状态的进程占比超过20%,就进一步调小KeepAliveTimeout值;根据实例内存规格设置合理的MaxRequestWorkers参数,8G内存规格的实例在event模式下设200-300即可,不要盲目调大导致内存溢出。 - 将
MaxConnectionsPerChild设为1000-2000,定期回收工作进程,避免长期运行的进程内存泄漏影响性能。
- 验证步骤
先单台实例挂载ELB做内网压测,确认单实例接ELB时的承载能力恢复到接近直连的500用户水平,再挂载全部3台实例做全集群压测;压测过程中重点监控EC2的CPU、内存、Apache工作进程占用率、CLOSE_WAIT连接数,以及ELB的后端响应时间、5xx错误率指标,根据压测表现微调参数即可。
内容的提问来源于stack exchange,提问作者Kedar Bhat
相关产品推荐
相关产品推荐

