点击下载教程项目代码:netflix_hystrix_demo.zip
@DefaultProperties是 Hystrix 提供的一个注解,用于为类中的多个@HystrixCommand方法设置默认的配置属性。在一个包含许多服务调用方法的类中,如果每个@HystrixCommand方法都要单独设置相同的基本配置(如相同的降级方法、相同的线程池名称等),会导致代码冗余。通过@DefaultProperties可以统一设置这些默认属性,减少重复配置。
该注解用于为 Hystrix 命令指定默认参数,例如:defaultFallback = "defaultFallback"。如果我们需要为某个特定方法指定参数,可以使用 @HystrixCommand 注解。
该注解源码如下:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface DefaultProperties { String groupKey() default ""; String threadPoolKey() default ""; HystrixProperty[] commandProperties() default {}; HystrixProperty[] threadPoolProperties() default {}; Class<? extends Throwable>[] ignoreExceptions() default {}; HystrixException[] raiseHystrixExceptions() default {}; String defaultFallback() default ""; }
属性说明:
在 Hystrix 中,groupKey 是用于将多个相关的 @HystrixCommand 方法划分到同一个组的属性。@DefaultProperties 注解中的 groupKey 属性允许你为类中的 @HystrixCommand 方法设置一个默认的分组键。这个分组键主要用于断路器(Circuit Breaker)统计和线程池分配等方面。
当多个 @HystrixCommand 方法被划分到同一个 groupKey 组时,Hystrix 会将这些方法的相关数据(如请求次数、失败次数、成功次数等)进行聚合统计。
例如:
@Service @DefaultProperties(groupKey = "orderServiceGroup") public class OrderService { @HystrixCommand public Order getOrderById(Long id) { // 正常调用远程服务获取订单信息 } @HystrixCommand public List<Order> getOrdersByCustomerId(Long customerId) { // 正常调用远程服务获取客户订单信息 } }
上面示例中,getOrderById 和 getOrdersByCustomerId 方法都属于 orderServiceGroup 这个分组。如果在配置线程池或者断路器等相关属性时,没有为这两个方法单独设置其他属性,它们将共享这个分组对应的默认配置。例如,它们可能共享一个默认的线程池,并且断路器的行为也会根据这个分组的配置来进行判断。
该属性用于指定一个默认的线程池键。在 Hystrix 中,线程池是基于这个键来进行分配和管理的。它允许你为类中的 @HystrixCommand 方法设置一个共享的线程池,这个线程池与threadPoolKey 相关联。
当你设置了 threadPoolKey 后,Hystrix 会根据这个键来查找或创建对应的线程池。与 groupKey 不同,threadPoolKey 更加侧重于直接控制线程池的分配。如果多个 @HystrixCommand 方法具有相同的 threadPoolKey,它们将共享这个线程池。这在你希望某些方法能够共享特定的线程资源,而不依赖于默认的基于 groupKey 的线程池分配方式时非常有用。
例如:
@Service @DefaultProperties(threadPoolKey = "database-operations") public class ServiceA { @HystrixCommand public void databaseWrite(Object data) { // 数据库写入操作 } @HystrixCommand public String externalApiCall() { // 外部API调用 } }
上面例子中,databaseWrite 和 externalApiCall 方法都使用了 @DefaultProperties 中指定的 threadPoolKey="database-operations"。这意味着这两个方法将共享一个与 "database-operations" 关联的线程池。如果希望这两个操作能够使用不同的线程池,可以为它们分别设置不同的 threadPoolKey,比如为 databaseWrite 设置 "database-pool",为 externalApiCall 设置 "api-call-pool":
@Service public class ServiceA { @HystrixCommand(threadPoolKey = "database-pool") public void databaseWrite(Object data) { // 数据库写入操作 } @HystrixCommand(threadPoolKey = "api-call-pool") public String externalApiCall() { // 外部API调用 } }
注意:threadPoolKey 和 groupKey 可以一起使用来实现更精细的线程池分配和服务容错管理。通常,groupKey 用于断路器统计和高层次的分组,而 threadPoolKey 用于直接控制线程池的分配。它们可以根据实际应用场景进行灵活搭配。例如,在一个大型的微服务系统中,可能有多个服务属于同一个 groupKey(从业务功能角度划分),但其中某些服务的性能要求或资源使用特点不同,此时可以通过设置不同的 threadPoolKey 来为这些服务分配不同的线程池,以优化系统性能。
用于设置默认的命令属性,这些属性控制着 Hystrix 命令的行为。例如,包括执行超时时间、断路器相关属性等诸多设置。
@DefaultProperties(commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000") }) public class DemoService { //... }
上面例子中,execution.isolation.thread.timeoutInMilliseconds 属性被设置为 3000 毫秒。这意味着类中的 @HystrixCommand 方法默认的超时时间是 3000 毫秒,除非某个方法自己单独设置了不同的超时时间。其他常见的命令属性还包括:
execution.isolation.thread.timeoutInMilliseconds:用于设置 Hystrix 命令(即被 @HystrixCommand 注解标记的方法)在独立线程(线程池隔离模式下)中执行的超时时间,单位是毫秒。
circuitBreaker.enabled:用于决定是否启用断路器机制。默认值是true,如果设置为false,则不会开启断路器,即使服务出现问题也不会自动切换到降级模式。
circuitBreaker.errorThresholdPercentage:用于设置断路器打开的错误率阈值。例如,设置为50,表示当服务调用的错误率达到 50% 时,断路器将打开。
circuitBreaker.sleepWindowInMilliseconds:当断路器打开后,经过这个时间间隔(单位为毫秒),会尝试进行一次半开状态的服务调用,以检查服务是否恢复正常。
用于设置默认的线程池属性,如线程池的大小、队列大小等,以此来有效地管理 Hystrix 命令的线程资源。例如:
@DefaultProperties(threadPoolProperties = { @HystrixProperty(name = "coreSize", value = "10"), @HystrixProperty(name = "maxQueueSize", value = "100") }) public class DemoService { //... }
上面示例中,设置了线程池的核心大小为 10,最大队列大小为 100。这意味着类中的 @HystrixCommand 方法所使用的线程池默认会有 10 个核心线程,并且当任务队列中的任务数量达到 100 时,新的任务可能会根据线程池的拒绝策略进行处理。线程池属性包括:
coreSize:设置线程池的核心线程数量。
maxQueueSize:设置线程池的最大队列长度。
keepAliveTimeMinutes:用于设置线程池中多余线程(非核心线程)的存活时间,单位是分钟。
queueSizeRejectionThreshold:当队列大小达到这个阈值时,即使队列没有满,也会开始拒绝新的任务,这是一种防止队列过度填充的策略。
用于指定一组异常类型,当 @HystrixCommand 方法抛出这些异常时,Hystrix 不会触发降级操作。这与通常情况下只要 @HystrixCommand 方法抛出异常就会触发降级的默认行为形成对比。
在某些情况下,你可能希望某些特定类型的异常不触发降级。例如,在服务调用过程中,可能会抛出一些预期的、业务相关的异常,这些异常可能是由于用户输入不符合要求或者业务规则导致的,而不是因为服务本身出现故障(如网络问题、服务过载等)。对于这些预期的业务异常,你可能希望系统正常地将异常向上传递,而不是执行降级操作。
例如:
@Service @DefaultProperties(ignoreExceptions = {InsufficientBalanceException.class}) public class PaymentService { @HystrixCommand public PaymentResult processPayment(PaymentRequest request) { try { // 调用远程服务进行支付处理 } catch (InsufficientBalanceException e) { // 余额不足异常,正常抛出,不执行降级 throw e; } catch (Exception e) { // 其他异常,执行降级操作 return fallbackPaymentResult(); } } public PaymentResult fallbackPaymentResult() { // 降级方法,返回一个默认的支付结果 PaymentResult result = new PaymentResult(); result.setStatus("Payment service is currently unavailable."); return result; } }
上面示例中,@DefaultProperties(ignoreExceptions = {InsufficientBalanceException.class}) 告诉 Hystrix,当 processPayment 方法抛出 InsufficientBalanceException 时,不要触发降级操作,而是正常地将这个异常向上抛出。只有当抛出其他类型的异常(如网络异常、服务响应超时等)时,才会执行 fallbackPaymentResult 作为降级操作。
用于控制在 Hystrix 命令执行过程中,当出现错误或者触发降级时,是否抛出 Hystrix 相关的异常。属性取值是一个 HystrixRuntimeException 类型的枚举数组。可能的取值包括HystrixRuntimeException.Failure 和 HystrixRuntimeException.Timeout 等。其中:
HystrixRuntimeException.Failure:当设置包含这个值时,如果 Hystrix 命令执行失败(例如,由于远程服务返回错误码、内部业务逻辑抛出异常等原因),就会抛出HystrixRuntimeException 异常,并且异常类型会标记为 Failure。这样上层调用者可以捕获这个异常并根据异常类型进行相应的处理,比如记录错误日志、进行重试等操作。
HystrixRuntimeException.Timeout:如果设置包含这个值,当 Hystrix 命令执行超时(超过 execution.isolation.thread.timeoutInMilliseconds 所设置的时间)时,会抛出HystrixRuntimeException 异常,异常类型标记为 Timeout。这有助于调用者区分是因为服务调用超时导致的问题,还是其他类型的故障。
例如:
@Service @DefaultProperties(raiseHystrixExceptions = {HystrixRuntimeException.Failure, HystrixRuntimeException.Timeout}, fallbackMethod = "defaultFallback") public class MyService { @HystrixCommand public String callRemoteService() { // 正常调用远程服务的逻辑 } public String defaultFallback() { // 降级方法 } }
上面示例中,@DefaultProperties 注解设置了 raiseHystrixExceptions 属性包含 HystrixRuntimeException.Failure 和 HystrixRuntimeException.Timeout。这意味着当 callRemoteService 方法在调用远程服务时,如果出现执行失败(如远程服务返回错误状态码)或者执行超时的情况,都会抛出相应类型的 HystrixRuntimeException。同时,由于还设置了 fallbackMethod 为defaultFallback,在抛出异常之前,Hystrix 会先尝试执行这个降级方法来提供一个替代的返回值。
用于指定一个默认的降级方法。当类中的 @HystrixCommand 方法没有显式地设置自己的降级方法时,就会使用这个默认的降级方法。例如:
@RestController // 配置全局Hystrix @DefaultProperties(defaultFallback = "defaultFallback" ) public class DemoService { @Autowired private DemoService demoService; @GetMapping({"/"}) @HystrixCommand // 采用默认降级方法 public String index() { return demoService.getInfo(); } /** * 全局回调方法【回退方法】 */ private String defaultFallback() { return "很抱歉,网络拥挤!"; } }
注意:默认回退方法不能有参数。