1. 概述
前段时间,线上的服务不知道为啥,突然全部的服务都超时,所有的请求经过网关都超时,后来进行链路追踪排查,发现有一个服务链接 RDS 数据库,一个查询花费了 20S 的查询时间,导致后续调用该服务的应用都超时。然后超时的连接占满了 zuul 的转发池,最终导致了所有经过 gateway 的服务都在等待,导致全体服务全部超时。
原因找出来之后,我就在纳闷,为何一个服务超时会导致所有服务都延时,作为一个高可用的网关, zuul 的设计应该不会这么差吧,并且,当时系统的 QPS 也不是很高,所以,必须找出这次超时的问题所在,于是,我就开始了此次网关超时的排查和优化!
下图是出现问题的相关监控
因为公司的服务是 java 和 node 应用都存在,所以使用的 zuul 是简单路由转发,未使用 服务注册中心之类的,所以,熔断器和
2. 问题分析
首先,因为网关的相关配置都是之前填的,有些参数不是特别的清楚,下面的配置文件是我当时系统的相关配置。
zuul:host:connect-timeout-millis: 30000socket-timeout-millis: 60000ribbon:ConnectTimeout: 300000ReadTimeout: 60000eureka:enabled: falsehystrix:command:default:execution:isolation:thread:timeoutInMilliseconds: 70000
2.1 zuul 参数解释
connect-timeout-millis
此参数为 zuul 网关连接服务的时间,单位为毫秒,我这里配置的是 30S,如果 30S 之内未连接到待转发的下一服务,则转发将报错,此请求也就将结束。这段时间为下图的第 1 步的时间
如下图所示:
socket-timeout-millis
zuul 网关连接到服务并且服务返回结果这一部分时间,单位为毫秒,我这里配置的是 60S,如果 60S 之内下一服务还没有返回, gateway 将报转发超时。
此时间为上图的 1+2+3 三部分时间
ribbon.ConnectTimeout
此为 ribbon 转发的连接时间,如果 zuul 使用的服务调用,则将采用此时间
ribbon.ReadTimeout
此为 ribbon 转发到返回的时间,如果 zuul 使用的是服务调用,则将采用此时间
超时时间采用哪个?
以上四个都是 zuul 的超时时间,但是问题来了,四个时间,到底采用哪两个呢?
我通过阅读 zuul 的相关文档,了解到,如果 zuul 使用的服务发现,则将会使用 rebbon进行负载均衡,即 ribbon.ConnectTimeout
和 ribbon.ReadTimeout
。如果 zuul 使用的是简单路由(通过配置 url 进行路由转发),则将采用 socket-timeout-millis
和 connect-timeout-millis
。
If you want to configure the socket timeouts and read timeouts for requests proxied through Zuul, you have two options, based on your configuration:
If Zuul uses service discovery, you need to configure these timeouts with the ribbon.ReadTimeout and ribbon.SocketTimeout Ribbon properties.
If you have configured Zuul routes by specifying URLs, you need to use zuul.host.connect-timeout-millis and zuul.host.socket-timeout-millis.
2.2 问题分析
因为我的服务未使用服务注册中心,所以,很明显, 配置的 ribbon 并未生效,zuul 超时时间使用的 socket-timeout-millis
和 connect-timeout-millis
。
但是问题又来了,我 zuul 的超时时间为 60S,为何我的服务相应时间平均达到了 3 分钟,远远超过了我设置的 60S,所以肯定是 z