跳至主要內容
Hystrix降级逻辑中如何获取触发的异常

通过之前Spring Cloud系列教程中的《Spring Cloud构建微服务架构:服务容错保护(Hystrix服务降级)》一文,我们已经知道如何通过Hystrix来保护自己的服务不被外部依赖方拖垮的情况。但是实际使用过程中经常碰到开发反应“莫名”触发了降级逻辑的情况。为了更精准的定位触发原因,或是在降级逻辑中需要根据不同的异常做不同的处理时,在降级方法中,我们希望可以获取到主逻辑中抛出的异常信息。接下来就来介绍一下Hystrix两种不同实现方式中如何在降级逻辑中获取异常信息的方法。


程序猿DD原创大约 2 分钟Spring CloudHystrixSpring Cloud
Spring Cloud中Hystrix 线程隔离导致ThreadLocal数据丢失

在Spring Cloud中我们用Hystrix来实现断路器,Zuul中默认是用信号量(Hystrix默认是线程)来进行隔离的,我们可以通过配置使用线程方式隔离。

在使用线程隔离的时候,有个问题是必须要解决的,那就是在某些业务场景下通过ThreadLocal来在线程里传递数据,用信号量是没问题的,从请求进来,但后续的流程都是通一个线程。

当隔离模式为线程时,Hystrix会将请求放入Hystrix的线程池中去执行,这个时候某个请求就有A线程变成B线程了,ThreadLocal必然消失了。

下面我们通过一个简单的列子来模拟下这个流程:

public class CustomThreadLocal {
    static ThreadLocal<String> threadLocal = new ThreadLocal<>();
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                CustomThreadLocal.threadLocal.set("猿天地");
                new Service().call();
            }
        }).start();
    }
}
class Service {
    public void call() {
        System.out.println("Service:" + Thread.currentThread().getName());
        System.out.println("Service:" + CustomThreadLocal.threadLocal.get());
        new Dao().call();
    }
}
class Dao {
    public void call() {
        System.out.println("==========================");
        System.out.println("Dao:" + Thread.currentThread().getName());
        System.out.println("Dao:" + CustomThreadLocal.threadLocal.get());
    }
}

尹吉欢大约 8 分钟Spring CloudSpring CloudHystrix
Spring Cloud Hystrix的请求合并

通常微服务架构中的依赖通过远程调用实现,而远程调用中最常见的问题就是通信消耗与连接数占用。在高并发的情况之下,因通信次数的增加,总的通信时间消耗将会变的不那么理想。同时,因为对依赖服务的线程池资源有限,将出现排队等待与响应延迟的情况。为了优化这两个问题,Hystrix提供了HystrixCollapser来实现请求的合并,以减少通信消耗和线程数的占用。

HystrixCollapser实现了在HystrixCommand之前放置一个合并处理器,它将处于一个很短时间窗(默认10毫秒)内对同一依赖服务的多个请求进行整合并以批量方式发起请求的功能(服务提供方也需要提供相应的批量实现接口)。通过HystrixCollapser的封装,开发者不需要去关注线程合并的细节过程,只需要关注批量化服务和处理。下面我们从HystrixCollapser的使用实例,对其合并请求的过程一探究竟。


程序猿DD原创大约 8 分钟Spring CloudSpring CloudHystrix
探讨通过Feign配合Hystrix进行调用时异常的处理

前言

  • 此文所述处理方式为本人在实践过程中研究分析得出的一种解决方案。
  • 本文不仅希望能为 SC 学习者提供一种如题问题的一种解决方案,并且希望通过本文引出各位 SC 的朋友对如题问题的共同探讨和最佳实践方案的分享。

场景及痛点

  • 单个项目是通过 Jersey 来实现 restful 风格的架构
  • 发生异常时异常信息总是提示没有回调方法,不能显示基础服务抛出的异常信息
  • 暂时没有考虑发生异常之后进行回调返回特定内容
  • 业务系统通过 feign 调用基础服务,基础服务是会根据请求抛出各种请求异常的(采用标准http状态码),现在我的想法是如果调用基础服务时发生请求异常,业务系统返回的能够返回基础服务抛出的状态码
  • 当然基础服务抛出的请求异常不能触发 hystrix 的熔断机制

任聪大约 5 分钟Spring CloudSpring CloudFeignHystrix
Spring Cloud构建微服务架构(三)断路器

在微服务架构中,我们将系统拆分成了一个个的服务单元,各单元间通过服务注册与订阅的方式互相依赖。由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身问题出现调用故障或延迟,而这些问题会直接导致调用方的对外服务也出现延迟,若此时调用方的请求不断增加,最后就会出现因等待出现故障的依赖方响应而形成任务积压,最终导致自身服务的瘫痪。

举个例子,在一个电商网站中,我们可能会将系统拆分成,用户、订单、库存、积分、评论等一系列的服务单元。用户创建一个订单的时候,在调用订单服务创建订单的时候,会向库存服务来请求出货(判断是否有足够库存来出货)。此时若库存服务因网络原因无法被访问到,导致创建订单服务的线程进入等待库存申请服务的响应,在漫长的等待之后用户会因为请求库存失败而得到创建订单失败的结果。如果在高并发情况之下,因这些等待线程在等待库存服务的响应而未能释放,使得后续到来的创建订单请求被阻塞,最终导致订单服务也不可用。


程序猿DD原创大约 6 分钟Spring CloudSpring CloudHystrix