Hystrix的入门使用总结

1.概念

学习Hystrix之前,需要先了解几个概念

  • 服务雪崩
  • 服务熔断
  • 服务降级

1.1 服务雪崩

在微服务的架构体系中,我们会将系统拆分成多个服务小单元,通过 HTTP 或者 RPC 进行远程调用。如下图所示:
在这里插入图片描述
在绝大多数情况下,服务消费者都能正常的远程调用服务提供者。但是某一时刻,服务提供者执行逻辑较慢,又或者网络出现抖动的情况,导致服务消费调用服务提供者超时或者失败。

比如当E服务出现异常后,这时候A服务和C服务分别调用了B服务和D服务,但是由于E服务异常了,最后连带了ABCDE都异常了,最后就造成了整体服务雪崩了

针对“服务雪崩”的情况,我们需要进行“服务容错”处理。解决的方向很“简单”,尽量不要去调用故障的服务,避免被拖垮。一般常用的手段有,主要是限流和开关。

  1. 限流
    通过限制调用服务的频率,避免频繁调用故障服务,导致请求任务积压而自身雪崩。

  2. 开关
    通过关闭对故障服务的调用,停止调用故障服务,从而避免服务雪崩。当然,关闭的前提是,不调用故障服务的情况下,业务逻辑依然可以走下去,或者业务数据的完整性不会被破坏。

一般来说,开关会分成手动开关和自动开关。手动开关比较好了解,自动开关是满足指定条件自动进行关闭。

1.2 服务降级

服务降级

这里有两种场景:

  • 当下游的服务因为某种原因响应过慢,下游服务主动停掉一些不太重要的业务,释放出服务器资源,增加响应速度!

  • 当下游的服务因为某种原因不可用,上游主动调用本地的一些降级逻辑,避免卡顿,迅速返回给用户!

其实应该要这么理解:

服务降级有很多种降级方式!如开关降级、限流降级、熔断降级!

服务熔断属于降级方式的一种!!!!!

其中服务熔断的含义为

  • 当下游的服务因为某种原因突然变得不可用或响应过慢,上游服务为了保证自己整体服务的可用性,不再继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。

以业内流行的Hystrix为例

Hystrix 内置断路器 HystrixCircuitBreaker 实现,一共有三种状态:

  • CLOSED :关闭
  • OPEN :打开
  • HALF_OPEN :半开

其中,断路器处于 OPEN 状态时,链路处于非健康状态,命令执行时,直接调用回退逻辑,跳过正常逻辑,就不会去调用服务,而是直接降级

HystrixCircuitBreaker 状态变迁如下图 :
在这里插入图片描述
红线 :初始时,断路器处于 CLOSED 状态,链路处于健康状态。当满足如下条件,断路器从 CLOSED 变成 OPEN 状态:

  • 在一个周期内,总请求数超过额定量,并其中的错误请求占总请求数超过一定比例 。

绿线 :断路器处于 OPEN 状态,命令执行时,若当前时间超过断路器开启时间一定时间,断路器变成 HALF_OPEN 状态,尝试调用正常逻辑,根据执行是否成功,打开或关闭熔断器【蓝线】。

配置

HystrixCommandProperties.default_metricsRollingStatisticalWindow = 10000 ms   #请求周期
HystrixCommandProperties.circuitBreakerRequestVolumeThreshold = 20			  #总请求数
HystrixCommandProperties.circuitBreakerErrorThresholdPercentage = 50% 		  #错误请求比例
HystrixCommandProperties.circuitBreakerSleepWindowInMilliseconds = 5000ms     #睡眠窗口时间

配置类截图HystrixCommandProperties
在这里插入图片描述

1.3 Hystrix资源隔离

Hystrix 使用了“舱壁隔离模式”来隔离和限制各个请求,从而实现资源的隔离。

Hystrix 通过线程池和信号量(Semaphore) 两种模式来实现隔离。

1.线程池模式

  • 默认情况下,Hystrix 采用线程池模式来实现隔离。
  • 针对调用的每一个服务,我们给其单独分配一个线程池。例如说,产品服务的调用分配在 A 线程池,用户服务的调用分配在 B 线程池。这样隔离后,两个服务的调用不会相互影响。

2.信号量模式

  • 使用线程池模式来隔离时,需要进行上下文的切换,带来一定的性能损耗。因此,如果对性能有较高要求,且能够接受信号量模式不支持超时的情况,可以考虑采用信号量模式。

2.入门案例

案例是基于Nacos的服务,不详细贴出,可参考
https://blog.csdn.net/weixin_38650898/article/details/106796136

2.1 搭建一个服务提供者

  • 控制器
@RestController
@RequestMapping("provider")
@Slf4j
public class ProviderController {

    @Value("${server.port}")
    private String port;

    @GetMapping("/index/{name}")
    public String testProvider(@PathVariable("name") String name) {
        log.warn("testProvider: 服务提供者");
        int i = 10 / 0;  //为了测试hysrix断路器
        return name + "端口号:" + port;
    }

}

2.2 搭建一个服务消费者

  • 依赖引入
     <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
     </dependency>
  • 控制器

@HystrixCommand 注解的参数:

  • fallbackMethod:指定 fallback 服务降级的处理方法,处理相应的异常。
  • ignoreExceptions :指定忽略指定的异常 Class,不进行 fallback 服务降级。
  • commandKey :命令键,默认未配置情况下,使用方法名。
  • groupKey :命令分组键,用于 Hystrix 根据不同的分组来统计命令的统计、告警、仪表盘信息。默认未配置情况下,使用方法所在类名。
  • threadPoolKey :属性线程池名,用于划分不同的线程池,进行资源隔离。默认未配置情况下,相同 groupKey 的 Hystrix Command 使用同一个线程池。
@RestController
@RequestMapping("consumer")
@AllArgsConstructor
//@DefaultProperties(defaultFallback = "hystrixFallBack")
public class ConsumerController {


    private final RestTemplate restTemplate;

    @GetMapping("/hystrix/{name}")
    @HystrixCommand(fallbackMethod = "hystrixFallBack")
    public String hystrixConsumer(@PathVariable("name") String name) {
        return restTemplate.getForObject("http://cloud-provider/provider/index/" + name, String.class);
    }
    
     /**
     * 容错回调方法必须要含有调用服务的方法参数
     *
     * @param name
     * @return
     */
    public String hystrixFallBack(@PathVariable("name") String name, Throwable throwable) {
        return "consumer 服务熔断,Reason:" + ExceptionUtils.getRootCauseMessage(throwable);
    }
}
  • 启动类

@EnableCircuitBreaker:开启断路器

@EnableDiscoveryClient
@SpringBootApplication
@EnableCircuitBreaker
public class ConsumerApplication8082 {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication8082.class, args);
    }
}

2.3 测试

由于服务提供者异常,会服务降级直接使用fallBack方法返回结果
在这里插入图片描述
疯狂点击后,满足熔断条件后就不会尝试调用服务,而是直接返回结果
在这里插入图片描述

3.Hystrix请求缓存

Hystrix 支持在同一个 HystrixRequestContext 上下文中,提供缓存的功能,以提升高并发场景下的性能,同时也带来相同缓存键返回相同结果的特性。

通过 Hystrix 主要提供了 @CacheResult 和 @CacheRemove 注解,我们可以使用 Hystrix 请求缓存功能。

@CacheResult :添加在方法上,声明将方法的执行结果进行缓存,并后续从缓存中获取结果。

  • cacheKeyMethod 属性:设置缓存键的生成方法。

也可以使用 @CacheKey 注解,直接设置缓存键的字符串,它的优先级比 @CacheResultcacheKeyMethod 属性高。

@CacheRemove :添加在方法上,声明移除指定 Hystrix Command 生成的缓存。

  • commandKey 属性:设置 Hystrix Command 键,一般是方法名。
  • cacheKeyMethod 属性:设置缓存键的生成方法。

下面的项目都是基于上面的基础上修改的

3.1创建HystrixRequestContextFilter

/**
 * @author :xiao7
 * @date :Created in 2020/7/10 21:57
 * @description:hystrix请求缓存过滤器
 */
@Component
@WebFilter(urlPatterns = "/")
public class HystrixRequestContextFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 初始化 HystrixRequestContext
        HystrixRequestContext context = HystrixRequestContext.initializeContext();
        // 继续过滤器
        try {
            chain.doFilter(request, response);
        } finally {
            // 销毁 HystrixRequestContext
            context.close();
        }
    }

}

3.1创建请求缓存服务

@Service
@Slf4j
public class CacheService {

    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "hystrixFallBack")
    @CacheResult(cacheKeyMethod = "genCacheKey")
    public String getProvider(String name) {
        return restTemplate.getForObject("http://cloud-provider/provider/index/" + name, String.class);
    }

    @HystrixCommand
    @CacheRemove(commandKey = "getProvider", cacheKeyMethod = "genCacheKey")
    public void updateProvider(String name) {
        log.info("[updateProvider][更新服务提供者({})详情]", name);
    }

    public String hystrixFallBack(@PathVariable("name") String name, Throwable throwable) {
        return "consumer 服务熔断,Reason:" + ExceptionUtils.getRootCauseMessage(throwable);
    }

    public String genCacheKey(String name) {
        return "PROVIDER_" + name;
    }
}

3.3 新增控制层

一个请求多次调用同一个服务,同一个上下文请求中会调用缓存

    @GetMapping("/getProvider/{name}")
    public String getProvider(@PathVariable("name") String name) {
        String a = cacheService.getProvider(name);
        String b = cacheService.getProvider(name);
        String c = cacheService.getProvider(name);
        return c;
    }

    @GetMapping("/updateProvider/{name}")
    public String updateProvider(@PathVariable("name") String name) {
        String a = cacheService.getProvider(name);
        cacheService.updateProvider(name);
        String c = cacheService.getProvider(name);
        return c;
    }

3.4 测试

调用getProvider接口,调用了三次服务提供者,只有第一次是真的调用,其他都是缓存
在这里插入图片描述
调用updateProvider接口,update会清空请求缓存,重新调用
在这里插入图片描述

4.搭建Hystrix Dashboard 监控

修改Consumer消费者的配置文件

management:
  endpoints:
    web:
      exposure:
        include: "hystrix.stream" # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。

新建项目,引入包

        <!-- 实现对 Hystrix Dashboard 的自动配置 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>

开启面板注解

@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApplication {
    public static void main(String[] args) {
        SpringApplication.run(HystrixDashboardApplication.class, args);
    }
}

5.相关文档

《Spring Cloud Netflix 官方文档 —— Hystrix Clients》
《Spring Cloud Netflix 官方文档 —— Hystrix Dashboard》
《Spring Cloud Netflix 中文文档 —— Hystrix Clients》
《Spring Cloud Netflix 中文文档 —— Hystrix 仪表板》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Hystrix是一个用于处理分布式系统间的错误和延迟的库。它提供了一些机制来保护你的系统免受故障的影响,并且帮助你优雅地处理这些故障。 以下是使用Hystrix的步骤: 1. 添加依赖 在你的项目中添加Hystrix的依赖,例如: ```xml <dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-core</artifactId> <version>1.5.18</version> </dependency> ``` 2. 定义命令 Hystrix的核心是命令模式。你需要定义一个继承自HystrixCommand的类,例如: ```java public class MyCommand extends HystrixCommand<String> { private final String name; public MyCommand(String name) { super(HystrixCommandGroupKey.Factory.asKey("MyGroup")); this.name = name; } @Override protected String run() throws Exception { // Do something that might fail return "Hello, " + name; } @Override protected String getFallback() { return "Fallback"; } } ``` 在这个例子中,我们定义了一个MyCommand类,它接收一个字符串作为参数,并返回一个字符串。在run()方法中,我们可以执行一些可能失败的操作,并在getFallback()方法中定义降级逻辑。 3. 执行命令 执行MyCommand命令的代码如下: ```java String result = new MyCommand("World").execute(); ``` 这将执行MyCommand命令,并返回结果。如果命令执行失败或超时,Hystrix将触发降级逻辑并返回fallback值。 4. 配置Hystrix 你可以使用Hystrix的配置来调整不同参数的值,例如: ```java HystrixCommandProperties.Setter() .withExecutionTimeoutInMilliseconds(1000) .withCircuitBreakerRequestVolumeThreshold(10) .withCircuitBreakerErrorThresholdPercentage(50) .withCircuitBreakerSleepWindowInMilliseconds(5000) ``` 这些配置参数可以控制Hystrix的行为,例如设置命令的超时时间、熔断器的触发条件等。 以上就是使用Hystrix的基本流程,你可以根据自己的需求来使用Hystrix来保护你的分布式系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值