定时任务与feign超时的纠葛,该咋优化?
1 背景
业务定时器应用半夜经常会触发熔断异常的告警邮件
根据邮件提示的类找到归纳以下表格
编号 | 报错方法 | 接口所属应用 | 所属定时任务类 |
---|---|---|---|
A | VipTradeReportFeignService#getShopTradeReportByDate | pinka-mod-stats | ShopOrderSturctureTask |
B | VipMemberStatsFeignService#statMemberRecord | pinka-mod-stats | MemberStatTask |
C | VipPartnerWalletFeignService.handlePartnerWithdraw | pinka-mod-customer | PartnerWithdrawCheckTask |
D | VipWeixinBabyActivityFeignService.getBabyActivityNoticePage | pinka-mod-weixin | VipWeixinBabyNoticeTask |
以上AD都是在一个分布式定时器事件处理应用(pinka-mod-scheduler)中对外的feign微服务调用产生的,相当于4类任务,每类都会调1次或多次外部feign微服务接口,而其中的AD接口发生了问题
其中A和B都是如下形式的异常
com.netflix.hystrix.exception.HystrixTimeoutException
at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$1$1.run(AbstractCommand.java:1154)
at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:45)
at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:41)
...
而C和D都是如下形式的异常
feign.RetryableException: 10.13.32.111:56000 failed to respond executing POST http://pinka-mod-customer/vip/partner/wallet/handlePartnerWithdraw
at feign.FeignException.errorExecuting(FeignException.java:67)
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:104)
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76)
at feign.hystrix.HystrixInvocationHandler$1.run(HystrixInvocationHandler.java:114)
...
Caused by: org.apache.http.NoHttpResponseException: 10.13.32.111:56000 failed to respond
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:141)
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:56)
at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259)
...
2 追查
2.1 HystrixTimeoutException超时异常
A与B的异常几乎每天都发生,且提示很明显,是Hystrix中设置了超时时间(目前为10s),并且执行超时导致的。为何会超时?去接口实现发现是有for循环场景的耗时逻辑
通过Kibana日志系统查历史执行耗时,也可以发现都基本>13s,所以这类异常基本确因
2.1.1 解决与思考
这其实是一个很典型场景,定时器任务执行并且处理逻辑是在另外一个微服务中,而处理逻辑属于复杂耗时,怎么办?
A. 增加超时时间,这是个粗暴的思路,因为设长了可能导致更大的问题,因为超时本来就是为了fastfail,设20s那之后可能还会遇到要30s甚至更久的场景。所以这个方案不能用在所有调用的公共默认超时时间上;
但是可以考虑用在某些接口上,比如VipTradeReportFeignService#getShopTradeReportByDate接口评估正常耗时就是要15s以上,那就单独为其设置。相关配置方式:
#默认公共超时
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
#单独为某个feign接口设置超时
hystrix.command."FeignService#sayHello(String)".execution.isolation.thread.timeoutInMilliseconds=15000
B. 优化接口提供方的逻辑执行时间。比如上述VipTradeReportFeignService#getShopTradeReportByDate中的for循环,能否移到接口调用方,相当于接口提供方每次只执行for循环的1次操作。说白了就是确保接口返回要在超时时间内,这也符合微服务接口的设计原则。
C. 还有种思路是接口处理异步化,即接口提供方立刻返回,自己再用异步线程去处理最终逻辑。但是单纯这样会导致任务执行不可靠,即接口返回成功不代表真实一定执行成功了,如果此时接口提供方重启或异常导致耗时的异步逻辑执行一半就中断了,反而无法利用分布式定时任务调度的机制去重试执行等。所以使用此思路时,接口立刻返回但不能立刻将任务也作为成功执行完毕,需要配合一些异步通知机制,即接口提供方真实成功结束耗时操作,通知给接口调用方,接口调用方再将任务作为成功返回上报。
2.2 feign.RetryableException failed to respond executing 异常
这是C和D的异常,是随机低频告警。看字面意思是接口请求无响应,再结合邮件中的“熔断”字眼就自然推测是接口提供应用的问题了(事后证明被“熔断”字眼坑了)。所以去追查接口所属应用pinka-mod-customer在告警前后的监控指标,发现tcp连接、CPU、内存、网络流量表现都没什么异常状况。另外如果是熔断,那此接口必然得是调用失败多次呀,而每次定时任务对该接口调用却只有一次。
这时候查看接口提供方Controller层日志,发现告警时刻确实提供方没进入controller处理。
由此推测,提供方应用本身并无问题。而查看调用方应用日志和性能指标,在那个时刻也无异常情况,还在不断向其他应用调用产生日志。再结合这个异常日志,推测原因是由于调用方与提供方某次调用的网络闪断导致的(所以是随机低频)。
但为何会开启“熔断”,这个还无法解释。此时去追查邮件告警的代码源头,告警本质是通过重写了openfeign官方的HystrixCommand创建逻辑中的getFallback方法实现的,即进入fallback逻辑就会发邮件
此时真相大白了,其实只是进了fallback降级,并不代表开启熔断,比如在HystrixCommand的run中抛出异常会进fallback,run执行超时会进fallback,熔断也会进fallback。即A~D这些异常,虽然邮件写的是熔断,但其实都没开启熔断,而只是进了fallback降级!
所以feign.RetryableException failed to respond executing这个其实只是一次偶然的调用失败进了fallback而已,并没之前猜想的那么复杂。
2.2.1 解决与思考
邮件告警逻辑自然是要修改,区分熔断和降级。如果要判断熔断,可以用如下方法
protected Object getFallback() {
if (this.isCircuitBreakerOpen()) {
// 熔断告警方式
sendExceptionEmail(...);
}else{
// 非熔断降级告警,如果无需告警也可不写
sendExceptionEmail(...);
}
....
}
“架构人生,迭代生命” ——深邃老夏,搜索summer_deep微信公众号可获取更多帮助
定时任务与feign超时的纠葛,该咋优化?的更多相关文章
- Hystrix配置实战及feign超时配置失效
一.feign超时配置失效 最近项目上遇见feign超时配置总是失效.导致feign调用超过2s之后就会超时,会进行自动重试,重复调用两次服务,并且还是指定接口.这就更加奇怪.最后通过观察以及源码调试 ...
- .NET 纯原生实现 Cron 定时任务执行,未依赖第三方组件 (Timer 优化版)
在上个月写过一篇 .NET 纯原生实现 Cron 定时任务执行,未依赖第三方组件 的文章,当时 CronSchedule 的实现是使用了,每个服务都独立进入到一个 while 循环中,进行定期扫描是否 ...
- springcoud feign超时的问题
配置 #开启超时控制 打开feign-hystix feign.hystrix.enabled=true ribbon.ReadTimeout= ribbon.ConnectTimeout= #如果e ...
- Feign超时设置
转-原文:https://xli1224.github.io/2017/09/22/configure-feign/ 在分析 Feign 源码的时候,我们看到 Feign 构建代理对象是分了几层的,一 ...
- Feign 超时设置
问题描述 微服务之间使用 Feign 调用,偶发超时问题,配置如下: feign: client: config: default: connectTimeout: 10000 readTimeout ...
- Feign超时不生效问题
使用Feign作为RPC调用组件,可以配置连接超时和读取超时两个参数 使用Feign配置超时需要注意:Feign内部使用了负载均衡组件Ribbon,而Ribbon本身也有连接超时和读取超时相关配置一. ...
- mysql事件(定时任务)处理超时失效订单
MySQL事件(定时任务) https://blog.csdn.net/pan_junbiao/article/details/86489237 UPDATE wz_mer_goods_spec as ...
- springcloud 设置feign超时时间
转载网址:http://www.pianshen.com/article/187038775/
- java 异步查询转同步多种实现方式:循环等待,CountDownLatch,Spring EventListener,超时处理和空循环性能优化
异步转同步 业务需求 有些接口查询反馈结果是异步返回的,无法立刻获取查询结果. 正常处理逻辑 触发异步操作,然后传递一个唯一标识. 等到异步结果返回,根据传入的唯一标识,匹配此次结果. 如何转换为同步 ...
随机推荐
- YouCompleteMe unavailable: requires Vim compiled with Python 2.x support
问题:YouCompleteMe unavailable: requires Vim compiled with Python 2.x support 解决:重新编译,加入--enable-pytho ...
- Java实现树形结构的数据转Json格式
在项目中难免会用到树形结构,毕竟这是一种常用的组织架构.楼主这里整理了两个实现的版本,可以直接拿来使用,非常方便. 楼主没有单独建项目,直接在以前的一个Demo上实现的.第一种,看下面代码: pack ...
- 【转】Camera 简介
一.摄像头(CAMERA)又称为电脑相机.电脑眼等,它作为一种视频输入设备,在过去被广泛的运用于视频会议.远程医疗及实时监控等方面. 近年以来,随着互联网技术的发展,网络速度的不断提高,再加上感光成像 ...
- vps的搭建
最近一直想自己搭建一款vps使用,但是苦于一直没有时间,直到今天得空,与大家一起分享下. 服务商的选择 因为自己之前在 vultr 上还留有余额(60$呢,好几百块大洋呢),所以我的服务商就选择 vu ...
- 用Python的Pandas和Matplotlib绘制股票KDJ指标线
我最近出了一本书,<基于股票大数据分析的Python入门实战 视频教学版>,京东链接:https://item.jd.com/69241653952.html,在其中给出了MACD,KDJ ...
- 03 . Go开发一个日志平台之Elasticsearch使用及kafka消费消息发送到Elasticsearch
Elasticsearch使用 详细使用请看我写的Go操作Elasticsearch专篇 https://www.cnblogs.com/you-men/p/13391265.html example ...
- angular实现地区三级联动
<!DOCTYPE html><html ng-app="myapp"> <head> <meta charset="UTF-8 ...
- vue的computed属性的理解
computed: { selectedQuestions() { let selectedQuestions = this.editedItem.questions; return this.que ...
- js中map()、some()、every()、filter()的区别
js的Array对象有map.some.every.filter几个方法都能对数组中的每个对象进行处理,但是他们之间的功能又各有差别,所以在记下. map():通过指定函数处理数组的每个元素,并返回处 ...
- Educational Codeforces Round 68 (Rated for Div. 2)-D. 1-2-K Game
output standard output Alice and Bob play a game. There is a paper strip which is divided into n + 1 ...