Hystrix请求合并

1 继承HystrixCollapser实现请求合并

1.1 HystrixCollapser的实现类

 import com.netflix.hystrix.HystrixCollapser;
import com.netflix.hystrix.HystrixCollapserKey;
import com.netflix.hystrix.HystrixCollapserProperties;
import com.netflix.hystrix.HystrixCommand;
import com.szss.demo.orders.service.UserService;
import com.szss.demo.orders.vo.UserVO;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;


public class UserCommandCollapser extends HystrixCollapser<List<UserVO>, UserVO, Long> {

    private UserService userService;
    private final Long userId;

    public UserCommandCollapser(UserService userService, Long userId) {
        super(Setter.withCollapserKey(HystrixCollapserKey.Factory.asKey("UserCommandCollapser"))
                .andCollapserPropertiesDefaults(HystrixCollapserProperties.Setter().withTimerDelayInMilliseconds(100)));
        this.userService = userService;
        this.userId = userId;
    }

    /**
    *获取请求参数
    */
    @Override
    public Long getRequestArgument() {
        return userId;
    }

    /**
    *合并请求产生批量命令的具体实现
    */
    @Override
    protected HystrixCommand<List<UserVO>> createCommand(Collection<CollapsedRequest<UserVO, Long>> collapsedRequests) {
        List<Long> userIds = new ArrayList<>(collapsedRequests.size());
        userIds.addAll(collapsedRequests.stream().map(CollapsedRequest::getArgument).collect(Collectors.toList()));
        return new UserBatchCommand(userService, userIds);
    }

    /**
    *批量命令结果返回后的处理,需要实现将批量结果拆分并传递给合并前的各原子请求命令的逻辑中
    */
    @Override
    protected void mapResponseToRequests(List<UserVO> batchResponse, Collection<CollapsedRequest<UserVO, Long>> collapsedRequests) {
        int count = 0;
        for (CollapsedRequest<UserVO, Long> collapsedRequest : collapsedRequests) {
            UserVO user = batchResponse.get(count++);
            collapsedRequest.setResponse(user);
        }
    }
}

HystrixCollapser的抽象定义中有三个泛型

public abstract class HystrixCollapser<BatchReturnType, ResponseType, RequestArgumentType> implements HystrixExecutable<ResponseType>, HystrixObservable<ResponseType> {

这个三个泛型分别的含义是:
- BatchReturnType:createCommand()方法创建批量命令的返回值的类型。
- ResponseType:单个请求返回的类型。
- RequestArgumentType:getRequestArgument()方法请求参数的类型。

HystrixCollapserProperties.Setter().withTimerDelayInMilliseconds(100))

初始化的时候,指定在100毫秒内发生的请求进行合并。

1.2 UserService批量查询接口

只需要实现批量查询接口,单个查询也是走批量查询。

public class UserService {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserService.class);

    @LoadBalanced
    @Autowired
    private RestTemplate restTemplate;

    public List<UserVO> findAll(String ids) {
        ParameterizedTypeReference<List<UserVO>> responseType = new ParameterizedTypeReference<List<UserVO>>() {
        };
        ResponseEntity<List<UserVO>> user = restTemplate.exchange("http://users-service/users/{ids}", HttpMethod.GET, null, responseType, ids);
        return user.getBody();
    }
}

1.3 UserBatchCommand批量查询命令

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.szss.demo.orders.service.UserService;
import com.szss.demo.orders.vo.UserVO;
import org.apache.commons.lang.StringUtils;
import java.util.ArrayList;
import java.util.List;

public class UserBatchCommand extends HystrixCommand<List<UserVO>> {

    private UserService userService;
    private List<Long> ids;

    public UserBatchCommand(UserService userService, List<Long> ids) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("UserBatchCommand"))
                .andCommandKey(HystrixCommandKey.Factory.asKey("findAll")));
        this.userService = userService;
        this.ids = ids;
    }

    @Override
    protected List<UserVO> run() throws Exception {
        if (ids != null && !ids.isEmpty()) {
            return userService.findAll(StringUtils.join(ids.toArray(),","));
        }
        return new ArrayList<>();
    }
}

2 使用注解方式来实现请求合并

    @HystrixCollapser(collapserKey = "UserHystrixCollapser", batchMethod = "findAll", //scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL,
            collapserProperties = {@HystrixProperty(name = "timerDelayInMilliseconds", value = "100")})
    public Future<UserVO> find(Long id) {
        throw new RuntimeException("This method body should not be executed");
    }

    @HystrixCommand(commandKey = "findAll")
    public List<UserVO> findAll(List<Long> ids) {
        ParameterizedTypeReference<List<UserVO>> responseType = new ParameterizedTypeReference<List<UserVO>>() {
        };
        String idStr = StringUtils.join(ids, ",");
        ResponseEntity<List<UserVO>> user = restTemplate.exchange("http://users-service/users/{ids}", HttpMethod.GET, null, responseType, idStr);
        return user.getBody();
    }

UserService批量查询接口的实现,如1.2所示。

@HystrixProperty(name = "timerDelayInMilliseconds", value = "100")

指定在100毫秒内发生的请求进行合并。

public Future<UserVO> find(Long id)

被@HystrixCollapser标注的方法,返回类型必须为Future,使用异步方法,否则无法进行请求合并。

@HystrixCollapser中有scope属性,scope的取值为REQUEST, GLOBAL。
REQUEST范围只对一个request请求内的多次服务请求进行合并,GLOBAL是多单个应用中的所有线程的请求中的多次服务请求进行合并。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值