Netflix Hystrix @HystrixCommand 注解

点击下载教程项目代码:netflix_hystrix_demo.zip

@HystrixCommand 是 Netflix Hystrix 框架提供的一个注解,用于标记在 Spring Boot 应用中需要进行熔断器保护的方法。

@HystrixCommand 作用

@HystrixCommand 注解的主要作用如下:

  • 实现熔断器:@HystrixCommand 注解可以为方法添加熔断器功能,当方法调用失败次数达到一定阈值时,熔断器会打开,后续的请求将直接失败,而不会再去调用实际的方法,从而避免了故障的扩散和系统资源的浪费。

  • 提供降级处理:当熔断器打开或者方法执行出现异常时,可以通过指定的降级方法来返回一个默认的结果,保证系统的基本可用性。

  • 隔离资源:可以为不同的方法配置不同的线程池或信号量,实现资源的隔离,避免某个服务的故障影响到其他服务的正常运行。

@HystrixCommand 源码

下面是 @HystrixCommand  注解的源码:

package com.netflix.hystrix.contrib.javanica.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


/**
 * This annotation used to specify some methods which should be processes as hystrix commands.
 * 该注解用于指定一些应作为 hystrix 命令处理的方法。
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface HystrixCommand {

    /**
     * The command group key is used for grouping together commands such as for reporting,
     * alerting, dashboards or team/library ownership.
     * 命令组键用于将命令分组,例如用于报告、警报、仪表盘或团队/库所有权。
     * <p/>
     * default => the runtime class name of annotated method
     * default => 被注释方法的运行时类名
     *
     * @return group key
     */
    String groupKey() default "";

    /**
     * Hystrix command key.
     * Hystrix 命令关键字。
     * <p/>
     * default => the name of annotated method. for example:
     * default => 被注释方法的名称,例如:...
     * <code>
     *     ...
     *     @HystrixCommand
     *     public User getUserById(...)
     *     ...
     *     the command name will be: 'getUserById'
     * </code>
     *
     * @return command key
     */
    String commandKey() default "";

    /**
     * The thread-pool key is used to represent a
     * HystrixThreadPool for monitoring, metrics publishing, caching and other such uses.
     * 线程池关键字用于表示 HystrixThreadPool,以用于监控、指标发布、缓存和其他类似用途。
     * @return thread pool key
     */
    String threadPoolKey() default "";

    /**
     * Specifies a method to process fallback logic.
     * A fallback method should be defined in the same class where is HystrixCommand.
     * Also a fallback method should have same signature to a method which was invoked as hystrix command.
     * for example:
     * 指定处理回退逻辑的方法。回退方法应与 HystrixCommand 定义在同一个类中。
     * 此外,回退方法应与作为 hystrix 命令调用的方法具有相同的签名:
     * <code>
     *      @HystrixCommand(fallbackMethod = "getByIdFallback")
     *      public String getById(String id) {...}
     *
     *      private String getByIdFallback(String id) {...}
     * </code>
     * Also a fallback method can be annotated with {@link HystrixCommand}
     * <p/>
     * default => see {@link com.netflix.hystrix.contrib.javanica.command.GenericCommand#getFallback()}
     *
     * @return method name
     */
    String fallbackMethod() default "";

    /**
     * Specifies command properties. 指定命令属性。
     *
     * @return command properties
     */
    HystrixProperty[] commandProperties() default {};

    /**
     * Specifies thread pool properties. 指定线程属性。
     *
     * @return thread pool properties
     */
    HystrixProperty[] threadPoolProperties() default {};

    /**
     * Defines exceptions which should be ignored.
     * Optionally these can be wrapped in HystrixRuntimeException if raiseHystrixExceptions contains RUNTIME_EXCEPTION.
     * 定义应忽略的异常。
     * 如果 raiseHystrixExceptions 包含 RUNTIME_EXCEPTION,
     * 则可选择用 HystrixRuntimeException 封装这些异常。
     * @return exceptions to ignore
     */
    Class<? extends Throwable>[] ignoreExceptions() default {};

    /**
     * Specifies the mode that should be used to execute hystrix observable command.
     * For more information see {@link ObservableExecutionMode}.
     * 指定用于执行 hystrix 可观察命令的模式。更多信息,请参阅 ObservableExecutionMode。
     * @return observable execution mode
     */
    ObservableExecutionMode observableExecutionMode() default ObservableExecutionMode.EAGER;

    /**
     * When includes RUNTIME_EXCEPTION, any exceptions that are not ignored are wrapped in HystrixRuntimeException.
     * 当包含 RUNTIME_EXCEPTION 时,任何未被忽略的异常都会封装在 HystrixRuntimeException 中。
     * @return exceptions to wrap
     */
    HystrixException[] raiseHystrixExceptions() default {};

    /**
     * Specifies default fallback method for the command. If both {@link #fallbackMethod} and {@link #defaultFallback}
     * methods are specified then specific one is used.
     * note: default fallback method cannot have parameters, return type should be compatible with command return type.
     * 指定命令的默认回退方法。如果同时指定了 fallbackMethod 和 defaultFallback 方法,则使用特定的方法。
     * 注意:默认 fallback 方法不能有参数,返回类型应与命令返回类型兼容。
     * @return the name of default fallback method
     */
    String defaultFallback() default "";
}

常用属性

groupKey

groupKey 主要用于对相关的命令进行分组,这些分组可以帮助在 Hystrix 仪表板等工具中更好地组织和查看相关的命令统计信息。

groupKey 的作用:

(1)资源隔离:有助于 Hystrix 实现资源隔离。Hystrix 通过将不同的命令分组,可以针对不同的组设置不同的线程池或者信号量限制。

(2)统计和监控:在 Hystrix 的监控体系中,groupKey 能够让你更方便地查看和分析相关命令的统计数据。比如在 Hystrix 仪表板上,你可以根据 groupKey 来查看某个组内所有命令的执行次数、失败率、响应时间等统计信息。

示例:

@Service
public class UserService {
    
    @HystrixCommand(groupKey = "userServiceGroup")
    public String getUserById(String id) {
        // 实际调用获取用户信息的逻辑,这里可能是一个RESTful服务调用等
    }
    
    @HystrixCommand(groupKey = "userServiceGroup")
    public void updateUser(String id, String newData) {
        // 实际调用更新用户信息的逻辑
    }
    
}

commandKey

用于标识 Hystrix 命令的唯一键值。如果不指定,默认使用被注解方法的名称作为 commandKey。

commandKey 属性作用:

  • 命令分组和统计:commandKey 主要用于对 Hystrix 命令进行分组和统计。例如,在 Hystrix 的监控和统计界面(如 Hystrix Dashboard)中,相同 commandKey 的命令会被归为一组进行统计分析。这有助于开发者了解特定类型的命令在系统中的执行情况,比如调用次数、成功率、响应时间等指标。

  • 缓存关联:当使用 Hystrix 的缓存功能时,commandKey 也用于关联缓存。如果多个方法具有相同的 commandKey 并且开启了缓存,Hystrix 可以根据这个 commandKey 来缓存和检索结果,提高系统性能。

示例:

@Service
public class UserService {
    
    @HystrixCommand(commandKey = "getUserByIdKey")
    public String getUserById() {
        // 这里是实际的业务逻辑,比如调用另一个微服务或者数据库操作
    }
    
}

threadPoolKey

threadPoolKey 属性用于指定 Hystrix 命令所属的线程池的唯一标识符。它在实现服务隔离等功能方面起着关键作用。

threadPoolKey的作用:

(1)资源隔离:通过为不同的 Hystrix 命令指定不同的 threadPoolKey,可以将这些命令隔离在不同的线程池中。

(2)配置灵活性:每个线程池可以有自己独立的配置。可以根据业务需求,为不同的 threadPoolKey 对应的线程池设置不同的大小(coreSize)、队列大小(maxQueueSize)等参数。

(3)监控和管理:以 threadPoolKey 为单位进行监控和管理。可以很方便地查看每个线程池的运行状态,如线程池的使用率、队列长度、执行任务的统计信息等。

示例:

@Service
public class MyService {

    @HystrixCommand(threadPoolKey = "myServiceThreadPool", fallbackMethod = "fallback")
    public String callRemoteService() {
        // 这里是调用远程服务的逻辑,例如通过RestTemplate
    }

    public String fallback() {
        return "Fallback response";
    }
}

fallbackMethod

该属性用于指定降级处理的方法名。当被注解的方法执行失败或超时时,会调用该降级方法来返回默认结果。示例:

@Service
public class UserService {
    
    @HystrixCommand(fallbackMethod = "getUserFallback")
    public String getUserInfo(String userId) {
        //
    }

    public String getUserFallback(String userId) {
        return "Fallback user information for " + userId;
    }
}

commandProperties

该属性允许你配置与 Hystrix 命令相关的各种属性。支持如下属性:

  • execution.isolation.strategy  用于指定隔离策略。它有两种取值:THREAD(线程隔离)和SEMAPHORE(信号量隔离)。

    • THREAD:为每个命令在单独的线程池中执行,这样可以避免一个长时间运行的命令阻塞整个容器的线程池。

    • SEMAPHORE:基于计数器限制了同时访问某个资源的并发数。这种策略在调用比较轻量级且执行速度快的场景下比较适用,因为它避免了线程上下文切换的开销。

  • execution.isolation.thread.timeoutInMilliseconds  用于设置命令执行的超时时间,单位是毫秒。当一个被 @HystrixCommand 注解标记的方法执行时间超过这个设定的时间时,Hystrix 会中断该方法的执行(如果是线程隔离策略),并执行回退(fallback)逻辑。

  • circuitBreaker.requestVolumeThreshold  定义了在一个滚动窗口中,打开熔断器的最少请求数量。例如,设置为20,意味着在一个统计窗口内,至少要有 20 个请求才能触发熔断器的状态改变。如果请求数量过少,即使部分请求失败,也不会轻易打开熔断器,因为少量的失败可能是偶然情况。

  • circuitBreaker.errorThresholdPercentage  指定了在一个滚动窗口内,错误请求占总请求数的百分比阈值。当错误率超过这个阈值时,熔断器会从闭合(CLOSED)状态转换为打开(OPEN)状态。例如,设置为50%,如果在一个统计窗口内,失败请求的比例超过 50%,熔断器就会打开,后续的请求会直接执行回退逻辑,而不会真正调用被注解的方法。

  • circuitBreaker.sleepWindowInMilliseconds  当熔断器处于打开状态后,这个属性定义了经过多少毫秒后,Hystrix 会允许一个请求通过熔断器,去尝试调用真实的服务(此时熔断器处于半开(HALF - OPEN)状态)。

示例:

@Service
public class MyService {
    @HystrixCommand(commandProperties = {
            // 设置隔离策略为线程隔离
            @HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
            // 设置超时时间为1500毫秒
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500"),
            // 设置熔断器打开的最少请求数量为10
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
            // 设置错误率阈值为40%
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "40"),
            // 设置熔断器打开后等待尝试的时间为3000毫秒
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "3000")
    })
    public String myMethod() {
        //
    }
}

threadPoolProperties

threadPoolProperties 属性主要用于配置与 Hystrix 命令关联的线程池的属性。支持如下属性:

  • coreSize  线程池的核心线程数。核心线程数是线程池能够保持存活的线程数量,即使它们处于空闲状态。

  • maxQueueSize  线程池的最大队列长度。当线程池中的所有线程都在忙碌,新的任务会被放入队列等待执行。这个属性限制了队列能够容纳的任务数量。

  • queueSizeRejectionThreshold  这是一个动态调整队列大小的阈值。它允许你在运行时根据实际情况,在队列满之前就开始拒绝任务,以避免队列过度积压导致系统性能下降。

  • keepAliveTimeMinutes  当线程池中的线程数量超过核心线程数时,多余的线程在空闲状态下能够存活的时间。

示例:

@Service
public class MyService {
    @HystrixCommand(
            threadPoolProperties = {
                    @HystrixProperty(name = "coreSize", value = "20"),
                    @HystrixProperty(name = "maxQueueSize", value = "100")
            }
    )
    public String myMethod() {
        // 这里是实际的业务逻辑,可能是调用其他服务或者执行复杂的计算
    }
}

ignoreExceptions

该属性用于指定在执行被注解的方法时,哪些异常应该被忽略,而不触发Hystrix的回退逻辑(fallback)。

当一个被@HystrixCommand注解的方法抛出异常时,Hystrix通常会根据配置来决定是否执行回退逻辑。如果抛出的异常在ignoreExceptions属性指定的异常列表中,Hystrix将不会触发回退,而是直接将该异常向上抛出。

示例:

@Service
public class MyService {
    @HystrixCommand(ignoreExceptions = {CustomBusinessException.class})
    public String myMethod() {
        // 业务逻辑代码
    }
}

observableExecutionMode

该属性用于指定 Hystrix 命令在处理响应式类型(如 Observable 或 Flowable)时的执行模式。

Hystrix 支持两种 observableExecutionMode 执行模式:EAGER LAZY

  • EAGER(急切)模式:当设置为 EAGER 模式时,Hystrix 会立即订阅 Observable 或 Flowable。这意味着,一旦方法被调用,Hystrix 就会开始执行底层的逻辑,并且尝试获取数据。

  • LAZY(延迟)模式:与 EAGER 模式相反,LAZY 模式下 Hystrix 不会立即订阅 Observable 或Flowable。只有当有订阅者(subscriber)真正订阅了 Observable 或 Flowable 时,Hystrix 才会开始执行底层的逻辑并获取数据。

示例:

@Service
public class MyService {
    // 这里设置为EAGER模式,也可以设置为LAZY
    @HystrixCommand(observableExecutionMode = EAGER) 
    public Observable<String> getData() {
        //
    }
}

raiseHystrixExceptions

该属性用于定义哪些异常应该被 Hystrix 捕获并触发回退逻辑。通常,当一个被 @HystrixCommand 注解标记的方法抛出异常时,Hystrix 可以根据 raiseHystrixExceptions 的配置来决定是否执行回退方法。

注意:raiseHystrixExceptions 属性的类型是一个 Class<? extends Throwable>[],这意味着它接受一个或多个异常类(这些异常类是 Throwable 的子类)的数组。

示例:

public class MyService {
    @HystrixCommand(
        raiseHystrixExceptions = {RemoteException.class, TimeoutException.class},
        fallbackMethod = "fallbackMethod"
    )
    public String myServiceMethod() throws RemoteException, TimeoutException {
        // 这里是实际的服务调用逻辑,可能会抛出RemoteException和TimeoutException
    }

    public String fallbackMethod() {
        //
    }
}

上述示例中,当 myServiceMethod 方法抛出 RemoteException 或者 TimeoutException 时,Hystrix 会捕获这些异常,并触发对应的回退逻辑(如果配置了回退方法的话)。

defaultFallback

当被标记的方法执行出现故障(例如,抛出异常、超时等)时,defaultFallback 所指定的方法会被调用,用于提供一个默认的返回值,以防止故障扩散和系统崩溃。

示例:

@Service
public class MyService {
    
    @HystrixCommand(defaultFallback = "fallbackMethod")
    public String myServiceMethod() {
        // 这里可能是一个远程服务调用,比如通过RestTemplate调用其他微服务
        // 为了演示,假设这里会抛出一个运行时异常
    }
    
    public String fallbackMethod() {
        return "默认的返回值,因为服务调用出错";
    }
}

在上述示例中,myServiceMethod 方法使用了 @HystrixCommand 注解,并配置了 defaultFallback 属性为 fallbackMethod。当 myServiceMethod 执行过程中出现异常(这里主动抛出了一个RuntimeException)时,fallbackMethod 会被调用,返回一个默认的字符串。

注意:

  • 方法签名要求:defaultFallback 方法的返回值类型必须与被 @HystrixCommand 注解标记的方法的返回值类型一致。

  • 参数问题:defaultFallback 方法通常是无参数的。因为在熔断器触发时,Hystrix 框架很难将原始方法的参数传递给 defaultFallback 方法。

  • 异常处理范围:defaultFallback 方法不会捕获 myServiceMethod 中可能出现的所有异常。例如,如果 myServiceMethod 中有 try-catch 块,并且在 catch 块中没有重新抛出异常,那么defaultFallback 方法不会被触发。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号