Hystrix请求命令

2020-03-04  本文已影响0人  一腔诗意换酒钱

Hystrix请求命令

请求命令就是用类的继承的方式来代替注解。

定义HelloCommand类:

public class HelloCommand extends HystrixCommand<String> {
    @Autowired
    RestTemplate restTemplate;

    public HelloCommand(Setter setter,RestTemplate restTemplate){
        super(setter);
        this.restTemplate = restTemplate;
    }

    @Override
    protected String run() throws Exception {
        return restTemplate.getForObject("http://provider/hello",String.class);
    }
}

在controller调用HelloCommand

    @GetMapping("/hello2")
    public void hello2(){
        //拿到helloCommand实例
        HelloCommand helloCommand = new HelloCommand(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("zby")), restTemplate);
        String execute = helloCommand.execute();//直接执行
        System.out.println(execute);
        HelloCommand helloCommand2 = new HelloCommand(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("zby")), restTemplate);
        try {
            Future<String> queue = helloCommand2.queue();//先入队后执行
            String s = queue.get();
            System.out.println(s);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

注意:一个实例只能执行一次,有两种执行方法

1.直接执行(同步调用)

2.先入队后执行(异步调用)

在command类中重写HystrixCommand的getFallBack()方法,即可实现服务降级的功能

异常处理

执行HsytrixCommand实现的run()方法抛出异常时,除HystrixBadRequestException之外,其他异常都会被认为是Hystrix命令执行失败并触发服务降级处理逻辑。若想要知道异常的具体信息,可以在getFallBack方法中对异常进行处理。

在HystrixCommand类中为我们提供了捕获异常的方法getExecutionException()可以通过这个方法获取异常的全部信息

    @Override
    protected String getFallback() {
        return "command-error"+getExecutionException().getMessage();
    }

请求合并

首先在provider中提供请求合并的接口

@GetMapping("/user/{ids}")//假设从consumer传来多个id,格式为1,2,3...
public List<User> getUserByIds(@PathVariable String ids){
    String[] split = ids.split(",");
    List<User> users = new ArrayList<>();
    for (String s : split) {
        User user = new User();
        user.setId(Integer.parseInt(s));
        users.add(user);
    }
    return users;
}

将传来的参数合并为一个List数组,根据数组中的每个参数,拿到相应的请求结果的集合。这个接口既可以处理单个请求,也可以处理多个请求。

在Hystrix中定义UserService

@Service
public class UserService {
    @Autowired
    RestTemplate restTemplate;
    
    @HystrixCommand
    public List<User> getUserByIds(List<Integer> ids){
        User[] users = restTemplate.getForObject("http://provider/user/{1}", User[].class, StringUtils.join(ids, ","));
        return Arrays.asList(users);
    }                                              
}

定义一个请求命令类UserBatchCommand用于对服务返回结果进行批处理

public class UserBatchCommand extends HystrixCommand<List<User>> {
    private List<Integer> ids;
    private UserService userService;

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

    @Override
    protected List<User> run() throws Exception {
        return userService.getUserByIds(ids);
    }
}

最后定义请求合并方法,方法继承自HystrixCommand包含有三个泛型:

1.批处理的返回类型List<User>

2.数据响应的的类型,也就是User对象

3.传递的参数类型Integer

public class UserCollapseCommand extends HystrixCollapser<List<User>,User,Integer> {
    private UserService userService;
    private Integer id;

    public UserCollapseCommand(UserService userService, Integer id) {
        //请求合并等待时间
        super(HystrixCollapser.Setter.withCollapserKey(HystrixCollapserKey.Factory.asKey("UserCollapseCommand"))
            .andCollapserPropertiesDefaults(HystrixCollapserProperties.Setter().withTimerDelayInMilliseconds(200)));
        this.userService = userService;
        this.id = id;
    }

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

    /**
     * 请求合并的方法,把合并好的请求放在collection里统一发送
     * @param collection
     * @return
     */
    @Override
    protected HystrixCommand<List<User>> createCommand(Collection<CollapsedRequest<User, Integer>> collection) {
        List<Integer> ids = new ArrayList<>(collection.size());
        for (CollapsedRequest<User, Integer> userIntegerCollapsedRequest : collection) {
            ids.add(userIntegerCollapsedRequest.getArgument());
        }
        return new UserBatchCommand(ids,userService);
    }

    /**
     * 请求结果分发
     * 第一个参数是provider返回的结果,第二个参数是合并后请求
     * @param users
     * @param collection
     */
    @Override
    protected void mapResponseToRequests(List<User> users, Collection<CollapsedRequest<User, Integer>> collection) {
        int count = 0;
        for (CollapsedRequest<User, Integer> request : collection) {
            request.setResponse(users.get(count++));
        }
    }
}

配置完成后进行测试:

    @GetMapping("/hello5")
    public void hello5() throws ExecutionException, InterruptedException {
        HystrixRequestContext ctx = HystrixRequestContext.initializeContext();
        UserCollapseCommand cmd1 = new UserCollapseCommand(userService,1);
        UserCollapseCommand cmd2 = new UserCollapseCommand(userService,2);
        UserCollapseCommand cmd3 = new UserCollapseCommand(userService,3);
        UserCollapseCommand cmd4 = new UserCollapseCommand(userService,4);
        UserCollapseCommand cmd5 = new UserCollapseCommand(userService,5);
        Future<User> q1 = cmd1.queue();
        Future<User> q2= cmd2.queue();
        Future<User> q3 = cmd3.queue();
        Future<User> q4 = cmd4.queue();
        Future<User> q5 = cmd5.queue();
        User u1 = q1.get();
        User u2 = q2.get();
        User u3 = q3.get();
        User u4 = q4.get();
        User u5 = q5.get();
        System.out.println(u1);
        System.out.println(u2);
        System.out.println(u3);
        System.out.println(u4);
        System.out.println(u5);
        ctx.close();
    }

访问接口,可以看到,在provider中只打印了一条记录

image

Hystrix中返回了五个结果

image

在获取三条记录后让线程休眠200毫秒,之后继续获取,可以看到provider总共收到两次请求。说明设置的等待时间.andCollapserPropertiesDefaults(HystrixCollapserProperties.Setter().withTimerDelayInMilliseconds(200))可以生效

image
上一篇 下一篇

猜你喜欢

热点阅读