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超时的纠葛,该咋优化?的更多相关文章

  1. Hystrix配置实战及feign超时配置失效

    一.feign超时配置失效 最近项目上遇见feign超时配置总是失效.导致feign调用超过2s之后就会超时,会进行自动重试,重复调用两次服务,并且还是指定接口.这就更加奇怪.最后通过观察以及源码调试 ...

  2. .NET 纯原生实现 Cron 定时任务执行,未依赖第三方组件 (Timer 优化版)

    在上个月写过一篇 .NET 纯原生实现 Cron 定时任务执行,未依赖第三方组件 的文章,当时 CronSchedule 的实现是使用了,每个服务都独立进入到一个 while 循环中,进行定期扫描是否 ...

  3. springcoud feign超时的问题

    配置 #开启超时控制 打开feign-hystix feign.hystrix.enabled=true ribbon.ReadTimeout= ribbon.ConnectTimeout= #如果e ...

  4. Feign超时设置

    转-原文:https://xli1224.github.io/2017/09/22/configure-feign/ 在分析 Feign 源码的时候,我们看到 Feign 构建代理对象是分了几层的,一 ...

  5. Feign 超时设置

    问题描述 微服务之间使用 Feign 调用,偶发超时问题,配置如下: feign: client: config: default: connectTimeout: 10000 readTimeout ...

  6. Feign超时不生效问题

    使用Feign作为RPC调用组件,可以配置连接超时和读取超时两个参数 使用Feign配置超时需要注意:Feign内部使用了负载均衡组件Ribbon,而Ribbon本身也有连接超时和读取超时相关配置一. ...

  7. mysql事件(定时任务)处理超时失效订单

    MySQL事件(定时任务) https://blog.csdn.net/pan_junbiao/article/details/86489237 UPDATE wz_mer_goods_spec as ...

  8. springcloud 设置feign超时时间

    转载网址:http://www.pianshen.com/article/187038775/

  9. java 异步查询转同步多种实现方式:循环等待,CountDownLatch,Spring EventListener,超时处理和空循环性能优化

    异步转同步 业务需求 有些接口查询反馈结果是异步返回的,无法立刻获取查询结果. 正常处理逻辑 触发异步操作,然后传递一个唯一标识. 等到异步结果返回,根据传入的唯一标识,匹配此次结果. 如何转换为同步 ...

随机推荐

  1. JavaScript学习系列博客_10_JavaScript中的while语句

    循环语句 - while循环 - 语法: while(条件表达式){ 语句... } - 执行流程: while语句在执行时,会先对条件表达式进行求值判断, 如果判断结果为false,则终止循环 如果 ...

  2. JavaScript学习系列博客_2_JavaScript编写位置

    JavaScript代码一般编写在哪里呢? 看到这个问题,第一个反应就是,JavaScript那当然是编写在<Script></Script>这对标签中啊!然而! 1.可以编写 ...

  3. C++ Templates (1.4 默认模板实参 Default Template Arguments)

    返回完整目录 目录 1.4 默认模板实参 Default Template Arguments 1.4 默认模板实参 Default Template Arguments 可以为模板参数定义默认值,这 ...

  4. golang 判断前缀后缀、包含关系

    HasPrefix 判断字符串 s 是否以 prefix 开头:strings.HasPrefix(s, prefix string) bool HasSuffix 判断字符串 s 是否以 suffi ...

  5. C#中WebService的创建、部署和调用的简单实例

    webservice 可以用于分布式应用程序之间的交互,和不同程序之间的交互. 概念性的东西就不说太多,下面开始创建一个简单的webservice的例子. 一:WebService的创建开发 先新建一 ...

  6. day40:python操作mysql:pymysql模块&SQL注入攻击

    目录 part1:用python连接mysql 1.用python连接mysql的基本语法 2.用python 创建&删除表 3.用python操作事务处理 part2:sql注入攻击 1.s ...

  7. [CSP-S2019]Emiya 家今天的饭 题解

    CSP-S2 2019 D2T1 很不错的一题DP,通过这道题学到了很多. 身为一个对DP一窍不通的蒟蒻,在考场上还挣扎了1h来推式子,居然还有几次几乎推出正解,然而最后还是只能打个32分的暴搜滚粗 ...

  8. javaScript高级含Es6

    JavaScript高级第01天笔记 1.面向过程与面向对象 1.1面向过程 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次调用就可以了. 1.2 ...

  9. FileZilla Server FTP服务器失败

    使用Filezilla Server配置FTP服务器https://blog.csdn.net/chuyouyinghe/article/details/78998527 FileZilla Serv ...

  10. Mc小冰总结的Android开发工程师面试题以及答案,android程序员必备,详解

    1.请谈一下Android系统的架构. 答:Android系统采用了分层架构,从高层到低层分别是应用程序层.应用程序框架层.系统运行库层和linux核心层. 2.谈谈android大众常用的五种布局. ...