美文网首页
Hystrix入门篇:如何在项目中使用断路器(一)

Hystrix入门篇:如何在项目中使用断路器(一)

作者: 明逸读书 | 来源:发表于2022-10-28 02:13 被阅读0次

Hystrix简介

背景

在微服务架构的分布式系统中,众多微服务有复杂的依赖关系,这些依赖在某些情况下不可避免的会出现一些请求失败。当一个依赖由于延迟高出现阻塞,调用该依赖的服务线程就会发生排队阻塞。如果这个时候出现大量的业务流量打过来,就可能会出现服务器资源被消耗殆尽导致服务宕机。


大量请求阻塞在依赖服务导致服务宕机

对于上图的情况,每个请求都占用了系统的CPU、内存、网络等资源,如果当前服务业务请求量较高,那么所有的服务资源会被快速消耗完毕,直至应用挂掉。

对于这种情况,就需要有一个服务的保护机制——服务隔离和熔断机制,当依赖应用出现问题,不会导致下游服务出现阻塞而导致一些列的雪崩效应。

Hystrix主要功能

服务隔离

服务隔离是给每一个服务分配一定的资源,超过这个资源范围变会直接释放资源,并不会占用其他服务的资源,以达到保护其他服务的目的。
Hystrix 提供了线程和信号量两种隔离方式,以减少不同服务之间资源竞争带来的相互影响。

服务熔断

服务熔断是在高并发下,如果达到一定的极限,流量如果超过了阈值后,直接拒绝访问,从而保护当前服务。

服务降级

高并发场景下,防止某一个用户在一直等待情况,比如当超过一直的阈值时长情况,直接 fallback 返回一个相对友好的提示。

请求缓存

请求缓存保证在一次请求中多次调用同一个服务提供者接口,在 cacheKey 不变的情况下,后续调用结果都是第一次的缓存结果,而不是多次请求服务提供者,从而降低服务提供者处理重复请求的压力。

请求合并

Hystrix 的请求合并用于应对服务器的高并发场景,通过合并多个请求,减少线程的创建和使用,降低服务器请求压力,提高在高并发场景下服务的吞吐量和并发能力。

快速开始

Maven配置

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    <version>2.2.6.RELEASE</version>
</dependency>

项目启动类添加注解 @EnableCircuitBreaker

package com.venky.hystrix;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;

@SpringBootApplication
@EnableCircuitBreaker
public class HystrixApplication {

    public static void main(String[] args) {
        SpringApplication.run(HystrixApplication.class, args);
    }
}

方法上使用断路器注解

package com.venky;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 工单统计Service
 *
 * @author venky
 * @date 2022/10/24
 */
@Service
@Slf4j
@DefaultProperties(groupKey = HystrixConfigProperties.TICKET_STAT_GROUP_KEY)
public class TicketStatCommand {
    /**
     * 业务服务http客户端
     */
    @Autowired
    private TicketClient ticketClient;

    /**
     * 工单统计查询
     *
     * @param request
     * @return
     * @throws Exception
     */
    @HystrixCommand(fallbackMethod = "getTicketStatisticsResponseFallback",
                    commandKey = "getTicketStatisticsResponse")
    public TicketStatisticsResponse getTicketStatisticsResponse(TicketStatisticsRequest request) throws Exception {
        return ticketClient.getResponseModel(request);
    }

    /**
     * 工单统计查询回调接口
     *
     * @param request
     * @param t
     * @return
     */
    private TicketStatisticsResponse getTicketStatisticsResponseFallback(TicketStatisticsRequest request, Throwable t) {
        log.error("getTicketStatisticsResponseHystrix --> enterpriseId:{},clientId:{},queueIds:{}", request.getEnterpriseId(), request.getClientId(), request.getQueueIds(), t);
        return null;
    }
}

其中 @DefaultProperties 是为当前断路器指定全局默认的配置。

groupKey 指定当前断路器的所在组key, 用来统计、报告,默认取类名,可不配置。相同的组的断路器会共享同一个线程池。

commandKey 用来标识一个 Hystrix 命令,默认会取被注解的方法名。需要注意:Hystrix 里同一个键的唯一标识并不包括 groupKey,建议取一个独一二无的名字,防止多个方法之间因为键重复而互相影响。

fallbackMethod 方法执行时熔断、错误、超时时会执行的回退方法,需要保持此方法与 Hystrix 方法的签名和返回值一致。

如果需要指定其他全局默认属性,可以在配置文件中新增。

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
hystrix.command.default.circuitBreaker.requestVolumeThreshold=20

circuitBreaker.requestVolumeThreshold 启用熔断器功能窗口时间内的最小请求数。此配置项的值需要根据接口的 QPS 进行计算,值太小会有误打开熔断器的可能,值太大超出了时间窗口内的总请求数,则熔断永远也不会被触发。建议设置为 QPS * 窗口秒数 * 60%

execution.isolation.thread.timeoutInMilliseconds 方法执行超时时间,默认值是 1000,即 1秒,此值根据业务场景配置。

给单个方法指定断路器参数。

hystrix.command.getTicketStatisticsResponse.execution.isolation.thread.timeoutInMilliseconds=10000
hystrix.command.getTicketStatisticsResponse.circuitBreaker.requestVolumeThreshold=20

以上方式是为了方便后续根据线上统计情况,可以动态调整配置参数,而无需改代码重启服务,方便后续调整。当然也可以直接在代码中添加。

/**
     * 测试
     *
     * @return
     */
    @HystrixCommand(fallbackMethod = "fallback",
            groupKey = "test",
            commandProperties = {
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"),
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
            }
    )
    public String test() {
        return "OK";
    }

    public String fallback(Throwable t) {
        log.error("exception",  t);
        return "fail";
    }

总结

以上是一个常用的线上断路器的使用方式案例,下一篇我们继续解析断路器的配置,让你对配置不再迷茫。

相关文章

网友评论

      本文标题:Hystrix入门篇:如何在项目中使用断路器(一)

      本文链接:https://www.haomeiwen.com/subject/esyxtdtx.html