如下是8月18日 aws
网关系统报错 502 Bad GateWay
问题定位、追踪、方案确认等:
一、现象:
周 6 下午 1 点 25 分左右系统报警 5xx 错误;
二、定位:排查过程
- 查看ELB日志确认错误来源于(商户API:查询支付结果及创建跨境支付单);
- 查询Pinpoint、Grafana及日志系统各项指标正常;
三、跟踪及分析:
查看ELB监控面板发现,502错误一直都存在,分布比较零散(大概的发生概率:万分之一(一万个请求约1次502错误)]);
-
确认调用链路确认错误区域:商户 —> ELB —> 业务系统;通过ELB日志发现,商户 —> ELB链路正常,ELB到业务系统链路不正常。可参考:Troubleshoot Elastic Load Balancer HTTP 502 Bad Gateway Errors ,大致猜测可能请求还没有达到业务系统就已经502了(因此业务系统各项监控指标正常)
-
验证猜想:ELB的TCP连接空闲存活时间60秒,业务系统Tomcat配置默认20秒,因此可能发生在极端的情况,业务系统关闭连接时,ELB刚好使用该连接,然后连接已关闭,ELB认为业务系统出现错误,包装错误:502 返回给调用方。
-
实验组验证:(验证环境压测环境)
第一组:ELB 60秒配置,Tomcat 存活时间配置1毫秒,200个并发请求,发现ELB监控502错误;
第二组:ELB 60秒配置,Tomcat 存活时间配置70秒,200个并发请求,未发现ELB监控502错误;
该验证过程,确认了因为配置的原因导致了此次的502问题,进一步验证是否TCP连接在这种情况下关闭;通过抓取TCP包,发现的确关闭了连接,因此基本可以确认,是由于该问题导致。
四、结论及方案:
结论:502 Bad GateWay 基于AWS ELB的环境部署下,有两种错误可能性:
- 配置问题(本次502报警问题):在Tomcat KeepAliveTimeOut的时间 < ELB的KeepAliveTimeOut时间,导致极端情况下的连接不可用,ELB 返回502错误码; 解决方案,确保:Tomcat KeepAlive的时间 >= ELB的KeepAlive时间,理论上可彻底消除。
- 服务不可用或错误:常规的502问题是主要因为服务此刻存在问题导致,此类502无法一次性解决,因为每次发生的情况都可能不一致,并且此类问题,会引起业务监控指标异常,属于长期观察及逐case解决的,能做到的是预防和监控。
将发布收单服务,修改
Tomcat
的KeepAliveTimeOut
参数为70
秒,解决此次502的问题。
通过修改 Spring Boot 容器工厂 EmbeddedServletContainerFactory
来修改 Tomcat
的 KeepAliveTimeOut
参数。
TomcatConnectorConfig.java
@Configuration
@Slf4j
public class TomcatConnectorConfig {
@Value("${tomcat.keep.alive.timeout:7000}")
private int tomcatKeepAliveTimeout;
@Bean
public EmbeddedServletContainerFactory createEmbeddedServletContainerFactory() {
TomcatEmbeddedServletContainerFactory tomcatFactory = new TomcatEmbeddedServletContainerFactory();
tomcatFactory.addConnectorCustomizers(connector -> {
ProtocolHandler protocolHandler = connector.getProtocolHandler();
if (protocolHandler instanceof Http11NioProtocol) {
Http11NioProtocol protocol = Http11NioProtocol.class.cast(protocolHandler);
log.info("TomcatConnectorConfig.customize setKeepAliveTimeout begin");
protocol.setKeepAliveTimeout(tomcatKeepAliveTimeout);
log.info("TomcatConnectorConfig.customize setKeepAliveTimeout end");
}
});
return tomcatFactory;
}
}