起因:
在某天下班的夜晚,吃完夜饭,准备搞搞手机玩,那微信群炸了,都是APP使用不了,用户反馈按钮不好使用,页面显示不出来。。。准备挨着一个一个回消息。电话轰炸又来了。没法搞手机玩了,只能搞电脑玩了,摊手~无奈!
问题描述:
1、在网关服务提示转发到业务模块请求超时,feign超时,触发hystrix熔断(记得整个项目设置feign超时是60秒,本人亲自搞的,当时研究很久feign和ribbon、hystrix)。通过看日志也没有请求接口也没有60秒,有比较慢的请求(几秒返回),有些请求都只在网关,没转发到服务模块(老奇怪!!!!)
2、网关服务提示报错,报错信息如下:Rejected command because thread-pool queueSize is at rejection threshold
这不是线程池满了吗???
zuul配置针对hystrix配置策略是strategy: THREAD(策略有线程和信号量两种,想了解具体配置,请自行百度,老多帖子)
经过一些列挣扎!!!最后发现网关配置zuul配置fegin超时时间改成了6秒!!!6秒也不短了,毕竟都超过3秒!!业务复杂接口按理也可以正常返回数据(小声逼逼:改成了6秒,老板也不通知一下!头皮发麻~)
排查过程:
1、项目使用阿里云的服务器、MySQL。
(1)检查服务的进程数:ps -efL | grep pid | grep -v grep | wc -l
业务服务的进程数是正常(按理也是正常,在网关已拦下多余的请求)
(2)在阿里云上查MySQL服务监控,数据库出现慢sql预警,MySQL的cpu和内存使用率偏高。
优化出现慢sql,新增索引
解决了慢sql后,数据库压力就降下去了。网关也没报错了,数据查询缓慢,导致请求堆积,api服务拒绝转发,多余请求直接熔断!问题解决了!开心继续搞手机玩!!
等等第二天上班!问题又出现了!!!又来一波轰炸!!头皮发麻,问题不是解决了吗?咋还有报错,错误信息都是一样的。等等~造成这个问题并不是数据库压力大,或者数据库压力只是一方面,还有其他原因。
捋捋!!!跟踪1个报错请求,在api服务提示超时,触发熔断请求,请求已转发到业务模块,该业务模块又调用其他业务模块(幸好没有其他业务模块),顺着查日志,发现其他业务模块,又调三方平台接口。日志显示调三方接口报超时错误,接口响应时长最长有30秒,甚至有1分钟未返回结果,这这。。。跟6秒差了54秒!!!18个3秒。。。
问题可以确认:调用三方接口,三方接口响应时长超过6秒,zuul网关熔断请求,业务接口调用频率很高,因三方响应慢,导致请求线程池占满,zuul网关拒绝接收请求,错误信息:Rejected command because thread-pool queueSize is at rejection threshold
zuul的hystrix线程设置:
解决方案:
1、设置请求超时时间,三方平台响应时间超过3秒,主动断开连接;
项目里使用RestTemplate,具体设置如下:
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setReadTimeout(2000);//设置读数据超时时间
factory.setConnectTimeout(1000);//设置建立连接超时时间
当加上请求超时时间限制后,网关还是出现大理报错,熔断报错信息,抓请求三方接口日志,发现设置超时时间是3秒左右,实际请求超时会10秒,甚至30秒。这是为毛啊!!!!为毛没有在3秒内主动断开!!!
2、反馈三方平台
我:抓到请求三方接口日志,啪~丢群里,各方大佬都圈上,你们接口有问题啊,老板,赶紧解决一下呗。
三方大佬挣扎:我们接口都是毫秒返回!
啪~丢了一张截图!请求统计表截图!
看到发出来截图,我停下敲字了,默默把已准备好怼人的话撤回!主动暂定互怼。捋捋~
我:麻烦根据请求时间和参数信息找一下日志(祈求语气!)
三方开发:没有找到日志。
自言自语:卧槽!服务端都没有请求日志,那是咋回事?是不是对方服务器炸了,超出线程最大排队数?拒绝接收请求!线程最大限制数,最大限制数。。。心里一直念叨。我靠,会不会是RestTemplate初始化的线程池沾满,排队等待超时,肯定是等待时间太长,不然设置超时时间会有效的。
实际现象:等待时间+请求下发后等待时间 =10秒甚至30秒,再熔断!
我靠,找到问题!不过三方系统也有问题,后续三方反馈:请求量偏高,1天请求量有100w。
最终解决方案:
1、我方:
(1)将连接池设置调整,保证请求3秒返回,超过3秒熔断(具体配置参考下方)
(2)获取到数据,做缓存;
2、三方:临时扩容(没有什么服务压力,扩容解决不了的,有钱任性!!!)
RestTemplate配置:
ConnectionRequestTimeout:从连接池获取连接的超时时间
ConnectTimeout:连接建立超时时间,三次握手完成时间限制
SocketTimeout:数据传输过程中,数据包之间间隔时间的限制时间
maxTotal :是设置同时间正在使用的最大连接数,默认值是20。
defaultMaxPerRoute:是设置一个 host(ip或域名):port 同时间正在使用的最大连接数,默认值是2。
总结:
1、网关做限流、熔断机制,防止网关被压垮!!!!这个问题在下有幸遇到过!consul健康检查通不过!头皮发麻!!
2、超时可能原因:
(1)网关设置超时时间和限流机制;
(2)接口业务中慢查询;
(3)接口涉及调三方平台接口;三方接口响应缓慢、请求连接池设置;
3、上述问题,按上面说方案解决了,网关还是会出现超时情况。只能慢慢优化!
备注:
借鉴大佬博客地址有:
1、HttpClient连接池管理 - 简书 (jianshu.com)
2、ConnectTimeout、ConnectionRequestTimeout、SocketTimeout的含义_connecttimeout和sockettimeout-CSDN博客