Hystrix feign线程模型

本文探讨了Hystrix通过线程隔离防止服务雪崩的机制,特别是当Feign启用Hystrix时,如何启动新线程在HystrixContextScheduler线程池中执行命令。Hystrix将不同业务请求封装为不同Command,每个Command对应一个线程池,通过Scheduler.Worker调度任务,实现线程隔离,确保服务稳定性。
摘要由CSDN通过智能技术生成

最近cat埋点因为hystrix的异步执行走了好大的坑,所以希望把hystrix的线程模型摸摸清楚

先讲个大概,然后再看代码

如果feign启用hystrix就会用hystrix的client来访问

feign:
  hystrix:
    enabled: true    # 启用熔断

hystrix的client会启动一个线程 来执行hystrixcommend 这个runable会放入HystrixContextScheduler 的线程池当中执行

然后SynchronousMethodHandler 会对返回值的结果进行判断

AbstractCommand.executeCommandAndObserve 则会对异常进行判断

如果超时会进入fall方法 如果是hystrixbadrequest方法就不会进入fall方法

那么hystrix为什么要做线程隔离呢 

比如我们现在有3个业务调用分别是查询订单、查询商品、查询用户,且这三个业务请求都是依赖第三方服务-订单服务、商品服务、用户服务。三个服务均是通过RPC调用。当查询订单服务,假如线程阻塞了,这个时候后续有大量的查询订单请求过来,那么容器中的线程数量则会持续增加直致CPU资源耗尽到100%,整个服务对外不可用,集群环境下就是雪崩。

但是如果我控制了对服务的线程 那么服务的线程就不容易快速增加 防止雪崩

 

 

 

 

但是首先来看下这个feign是怎么启用hystrix的话

 

大概流程是 在开启hystrix配置 那么spring会在bean加载时通过FactoryBean增强加载方法,为每个@feginClient 注解的类 增强配置 然后在远程调用发生是 通过切面拦截 增强调用的方法

第一步

FeignClientsConfiguration

feign的配置类 如果配置文件里面指定了feign.hystrix.enabled 那么会使用hystrix的hystrixfeign

HystrixTargeter 的target 是干嘛的后面说

第二步

主类上声明@EnableFeignClients 代表使用声明式feign调用, 然后去找所有@feign的bean然后读取属性和配置 然后注册FeignClientFactoryBean 注意这个是factoryBean 是spring的拓展点

第三步

有了factoryBean就要知道他是如何getObject()的  拓展了什么

也就是我们在@Autowired完了之后在做什么

然后其实就是spring的依赖加载过程

还是要看看FeignClientFactoryBean 在做什么 (这个类不仅做了下面的时候还装饰了编码器等等)

因为是factorybean所以看直接看getObject 看看拓展了什么

getobject里就一个方法getTarget

<T> T getTarget() {
 FeignContext context = this.applicationContext.getBean(FeignContext.class);
Feign.Builder builder = feign(context); //先取上下文 利用上下文构造一个feign builder 
 if (!StringUtils.hasText(this.url)) {
  if (!this.name.startsWith("http")) {
   this.url = "http://" + this.name;
  }
  else {
   this.url = this.name;
  }
  this.url += cleanPath();//希望把url拼装为即将调用的服务名
  return (T) loadBalance(builder, context,
    new HardCodedTarget<>(this.type, this.name, this.url)); //上进入loadbalance方法
 }
 if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
  this.url = "http://" + this.url;
 }
 String url = this.url + cleanPath();
 Client client = getOptional(context, Client.class);
 if (client != null) {
  if (client instanceof LoadBalancerFeignClient) {
   // not load balancing because we have a url,
   // but ribbon is on the classpath, so unwrap
   client = ((LoadBalancerFeignClient) client).getDelegate();
  }
  builder.client(client);
 }
 Targeter targeter = get(context, Targeter.class);
 return (T) targeter.target(this, builder, context,
   new HardCodedTarget<>(this.type, this.name, url));
}

protected <T> T loadBalance(Feign.Builder builder, FeignContext context,
  HardCodedTarget<T> target) {
 Client client = getOptional(context, Client.class);
 if (client != null) {
  builder.client(client);
  Targeter targeter = get(context, Targeter.class);
  return targeter.target(this, builder, context, target);//可以看到主要还是这里,HystrixTargeter 实现了targeter.target的接口 所以会走到hystrix
 }
 throw new IllegalStateException(
   "No Feign Client for loadBalancing defin
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值