Netflix Hystrix @HystrixCollapser 注解

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

@HystrixCollapser 是 Netflix Hystrix 库中的一个注解,用于实现请求合并(Request Collapsing)。请求合并是一种优化策略,它可以将多个相似的请求合并为一个请求进行处理,从而减少开销,提高系统性能。

下面是 @HystrixCollapser 源码:

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

import com.netflix.hystrix.HystrixCollapser.Scope;

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

/**
 * This annotation is used to collapse some commands into a single backend dependency call.
 * 此注解用于将一些命令合并为单个后端依赖调用。
 * This annotation should be used together with {@link HystrixCommand} annotation.
 * 此注解应与 @HystrixCommand 注解一起使用。
 * <p/>
 * Example: 示例
 * <pre>
 *     @HystrixCollapser(batchMethod = "getUserByIds"){
 *          public Future<User> getUserById(String id) {
 *          return null;
 * }
 *  @HystrixCommand
 *      public List<User> getUserByIds(List<String> ids) {
 *          List<User> users = new ArrayList<User>();
 *          for (String id : ids) {
 *              users.add(new User(id, "name: " + id));
 *          }
 *      return users;
 * }
 *   </pre>
 *
 * A method annotated with {@link HystrixCollapser} annotation can return any
 * value with compatible type, it does not affect the result of collapser execution,
 * collapser method can even return {@code null} or another stub.
 * 使用 @HystrixCollapser 注解的方法可以返回任何兼容类型的值,
 * 不会影响 Collapser 的执行结果、 Collapser 方法甚至可以返回 null 或其他存根。
 * Pay attention that if a collapser method returns parametrized Future then generic type must be equal to generic type of List,
 * 注意,如果 collapser 方法返回参数化的 Future,那么泛型类型必须与 List 的泛型类型相等。
 * for instance:
 * <pre>
 *     Future<User> - return type of collapser method 折叠器方法的返回类型
 *     List<User> - return type of batch command method 批处理命令方法的返回类型
 * </pre>
 * <p/>
 * Note: batch command method must be annotated with {@link HystrixCommand} annotation.
 * 注意:批处理命令方法必须使用 @HystrixCommand 注解进行标注。
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HystrixCollapser {

    /**
     * Specifies a collapser key.
     * 指定一个合并器键。
     * <p/>
     * default => the name of annotated method. 带注释方法的名称。
     *
     * @return collapser key.
     */
    String collapserKey() default "";

    /**
     * Method name of batch command.
     * 批量命令的方法名称。
     * <p/>
     * Method must have the following signature:
     * 方法必须具有以下签名:
     * <pre>
     *     java.util.List method(java.util.List)
     * </pre>
     * NOTE: batch method can have only one argument.
     * 注意:批处理方法只能有一个参数。
     * @return method name of batch command 批量命令的方法名称
     */
    String batchMethod();

    /**
     * Defines what scope the collapsing should occur within.
     * 定义合并应在什么范围内发生。
     * <p/>
     * default => the {@link Scope#REQUEST}.
     *
     * @return {@link Scope}
     */
    Scope scope() default Scope.REQUEST;

    /**
     * Specifies collapser properties.
     * 指定 collapser 属性
     * @return collapser properties
     */
    HystrixProperty[] collapserProperties() default {};

}

常用属性

collapserKey

用于定义请求合并的键(Key),例如:

@HystrixCollapser(batchMethod = "getUserDetailsBatch", collapserProperties = {
    @HystrixProperty(name = "timerDelayInMilliseconds", value = "100")
}, collapserKey = "userDetailsCollapser")
public Future<UserDetails> getUserDetails(String userId) {
    // 这个方法实际上不会执行,它只是返回一个Future,用于异步获取结果
}

上面示例中,collapserKey 的值是 userDetailsCollapser。所有带有相同 collapserKey(这里是userDetailsCollapser)并且 batchMethod(这里是getUserDetailsBatch)也相同的@HystrixCollapser 注解标记的方法请求,会在满足一定条件(如时间窗口,由timerDelayInMilliseconds 属性控制)下被合并。

batchMethod

该属性指定了一个批量执行方法,用于将多个请求合并为一个批量请求进行处理,这样可以减少网络开销和资源消耗,提高系统的性能和效率。例如:

public class UserService {

    @HystrixCollapser(batchMethod = "batchGetUsers")
    public Future<User> getUserById(String userId) {
        // 这个方法实际上不会执行请求,它只是返回一个Future
        // 请求会被合并并由batchGetUsers方法执行
    }

    // 批量方法
    @HystrixCommand
    public List<User> batchGetUsers(List<String> userIds) {
        List<User> users = new ArrayList<>();
        // 在这里实际执行批量获取用户信息的操作,例如从数据库或其他服务获取
        for (String userId : userIds) {
            User user = new User(userId);
            users.add(user);
        }
        return users;
    }
}

上述示例中,getUserById 方法上使用了 @HystrixCollapser 注解,并且 batchMethod 属性设置为batchGetUsers。当有多个 getUserById 请求时,这些请求会被合并,然后通过 batchGetUsers 方法进行批量处理。batchGetUsers 方法通过 @HystrixCommand 注解进行标记,这意味着它会被 Hystrix 进行监控和管理,例如设置超时时间、熔断等策略。

scope

该属性用于指定请求合并的范围。可以取值为 REQUEST 或 GLOBAL,默认为 REQUEST。

REQUEST(默认值)

当 scope = REQUEST 时,请求合并的范围是在一个单独的请求上下文中。这意味着在一个特定的 HTTP 请求或者其他类型的外部请求的生命周期内进行请求合并。

例如,在一个 Spring MVC 的 Web 应用中,如果一个控制器方法被多个线程同时调用,并且这些调用都在同一个 HTTP 请求的处理过程中,Hystrix 会将这些并发的、针对相同合并键(collapserKey)的请求合并为一个请求。

GLOBAL

当 scope = GLOBAL 时,请求合并的范围是全局的。它会跨越多个请求来合并相同类型的请求。

例如,在一个微服务架构中,如果有多个不同的客户端(如不同的 Web 应用或者其他服务消费者)对同一个后端服务的相同方法进行频繁调用,并且这些调用的参数符合合并条件(基于合并键),Hystrix 会将这些来自不同请求上下文的请求合并为一个请求。这种方式更加强大,但也需要谨慎使用,因为它可能会影响到不同请求之间的独立性和响应的及时性。

示例:

@Service
public class MyService {
    @HystrixCollapser(batchMethod = "batchGetData", collapserProperties = {
            @HystrixProperty(name = "timerDelayInMilliseconds", value = "100")
    }, scope = RequestScope.REQUEST)
    public Future<String> getData(String key) {
        // 这个方法实际上不会被执行,它只是定义了合并请求的单个请求参数和返回类型
        throw new RuntimeException("This method body should not be executed.");
    }
    
    @HystrixCommand
    public List<String> batchGetData(List<String> keys) {
        // 实际执行的批处理方法,用于获取数据
        List<String> dataList = new ArrayList<>();
        // 模拟从数据源获取数据
        for (String key : keys) {
            dataList.add("Data for key: " + key);
        }
        return dataList;
    }
}

在上面的示例中,@HystrixCollapser 注解的 scope 属性被设置为 REQUEST。如果要将其设置为GLOBAL,只需要修改 scope 属性的值即可。同时,batchMethod 属性指定了实际执行批量请求的方法,collapserProperties 可以配置请求合并的一些其他属性,如延迟时间(timerDelayInMilliseconds),它表示在等待一定时间后,如果还有未合并的请求,就执行合并后的请求。

collapserProperties

该属性用于配置请求合并的相关参数。例如:

@HystrixCollapser(batchMethod = "batchGetUsers", collapserProperties = {
    @HystrixProperty(name = "timerDelayInMilliseconds", value = "20")
})
public Future<User> getUserById(String userId) {
    // 单个请求的定义,返回一个Future表示异步结果
}

在上述示例中,timerDelayInMilliseconds 设置为 20,意味着每 20 毫秒会收集一次 getUserById 请求并合并。

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