一、故障过程回顾
2020年1月3日早上7:30收到pay-xx服务连接超时告警,发现问题后马上进行排查,根据链路日志发现,我们请求有通过http发送给第三方,将请求日志发给第三方,但第三方反馈未收到该请求。瞬间懵逼了, 我们有发送请求,但第三方没有收到,请求中途掉包了 ?网络出现了问题?但是我们部分请求是可以送达第三方的,开始怀疑是第三方对我们出口的ip做了白名单限制 ? 7:50 左右我们一个服务节点开始出现波测告警,该告警的意思是一个服务节点已经死机。于是赶快联系运维重新部署,pay-xx服务。 8:30重新部署服务后,整个请求恢复正常。
为了排查问题,我们然运维保留了死机节点,并导出了jvm堆栈。
二、问题排查
1)我将出问题的节点出口ip给第三方排查是否由于网关ip白名单访问限制导致问题,第三运维反馈ip白名单正常。
2)我开始找出问题时候http访问的状态,发现在服务告警前,http请求第三方返回了很多504以后, 我们服务开始出现异常;
3)第三方排查确实7:29至7:30 一段时间没有收到我们的请求,那这个http 504状态表示的超时,是什么地方返回的呢?看第三方网关监控7:30分他们可以正常收到请求,但为什么我们的一个节点会出现死机呢?
4)第三方用的是阿里云cdn加速,进过与阿里一起排查发现7:29至7:30,我们收到的504状态码,是阿里网关内部超时返回的
5)第三方优化了cdn 中tcp 超时时间
6)问题的根源算是找到了,是由于阿里网关内部超时导致,我们服务7:29至7:30大量请求超时。
7)问题起因算是找到了, 但我们的服务为什么没有,没有对连接做超时断开呢 ?于是我开始看项目代码。
public Map<String, String> send(HttpRequest request) throws ClientException, BusinessException {
Stopwatch stopwatch = Stopwatch.createStarted();
logger.info("Start send http request...");
//设置超时时间,如果request没设置超时时间,取profile里的
int socketTimeout = request.getSocketTimeout() > 0 ? request.getSocketTimeout() :10000;
int connectTimeout = request.getConnectTimeout() > 0 ? request.getConnectTimeout() : 10000;
RequestConfig config = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout)
.build();
logger.info("Http request params: uri={}, headers={}, params={} ", request.getUri(),
JSONArray.toJSONString(request.getHeaders()