记一次多线程异步调取Feign接口失败问题及其解决

记一次多线程异步调取Feign接口失败问题及其解决

在一次线上环境中反馈短信和消息没有发出去,我赶紧排查问题,前面说下我的业务场景:发短信和发消息都是使用多线程异步执行,通过调取Feign来调取push服务的推送接口来进行推送,因为要快速反馈给用户消息,正好前一段时间学会用CompletableFuture,正想小试牛刀的我,依然决然采用之来实现异步推送,本来用起来还蛮好的,简单易懂方便,而且支持线程窃取等一系列功能,简直是如获至宝,但是今天线上突然出现了以下错误,泼了我一脸冷水:

Task java.util.concurrent.FutureTask@68bb4099 rejected from java.util.concurrent.ThreadPoolExecutor@f8b8538[Running, pool size = 10, active threads = 10, queued tasks = 20, completed tasks = 693]

开始一度以为是CompletableFuture的锅,但是经过我百度了会,发现其实我错怪了CompleteFuture了,一开始还去看CompleteFuture的源码,了解到CompletableFuture用的是ForkJoinPool的线程池,默认线程数是系统机的cpu核心数,但这个错误为啥报的是active threads=10,这个我就郁闷了,而且CompletableFuture默认会给每个工作线程分配独立的队列,应该不会出现并发调直接拒绝我的任务的问题啊!思前想后我还是想不通,后来索性把堆栈打出来了,我这才知道是Hystrix的问题:

java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@6900a95d rejected from java.util.concurrent.ThreadPoolExecutor@5d2de59a[Running, pool size = 10, active threads = 10, queued tasks = 20, completed tasks = 54]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
	at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
	at com.netflix.hystrix.strategy.concurrency.HystrixContextScheduler$ThreadPoolWorker.schedule(HystrixContextScheduler.java:172)
	at com.netflix.hystrix.strategy.concurrency.HystrixContextScheduler$HystrixContextSchedulerWorker.schedule(HystrixContextScheduler.java:106)
	at rx.internal.operators.OperatorSubscribeOn.call(OperatorSubscribeOn.java:50)
	at rx.internal.operators.OperatorSubscribeOn.call(OperatorSubscribeOn.java:30)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
	at rx.Observable.unsafeSubscribe(Observable.java:10327)
	....

原来是com.netflix.hystrix下面爆出来的错,o(╥﹏╥)o,找了好久,终于找到了,好了,知道了问题所在,我们开始分析为啥会报这错。之后发现一旦并发量大的时候,就会报,我一想这不就是hystrix熔断机制吗?自己然后查了下资料,发现hystrix调用其他服务的时候核心最大Threadsize=10,如果核心线程达到最大线程则直接拒绝,而且默认没有队列,可能hystrix是为了快速调用才这么设计,但根据我的业务此涉及不太靠谱,所以我就想着直接扩大线程数,但是最大线程数也不能乱调,大了会增加线程上下文切换,小了效率又不高,导致又会拒绝我的任务执行,后来查了下官网,有了如下解决方法,不多说直接贴出一下配置:

hystrix:
  threadpool:
    default:
      coreSize: 16//并发执行的最大线程数,默认10,我这里用cpu核心数
      maxQueueSize: 1000//BlockingQueue的最大队列数,默认值-1
      queueSizeRejectionThreshold: 800 //即使maxQueueSize没有达到,达到queueSizeRejectionThreshold该值后,请求也会被拒绝,默认值5

配置直接放在application.yml中,这样遇到某些场景远程调用并发多的时候可以采用以上配置,但这个配置也不能乱用,因为加了队列,这就意味着你的熔断门槛就比较高了,所以各位同学一定要根据自己的业务场景来设置。

你可能感兴趣的:(经验)