9、Spring Cloud08——断路器03

Hystrix请求合并

请求合并就是consumer反复的请求provider同一个接口,只是传的参数不一样,为了提高HTTP的通信效率,把它连着调用的很多个接口合成一个请求发出去,然后在provider上处理,处理完成后,返回一个一个结果就ok了,但是这不是所有的请求都能合并,这是有要求的,比如说,请求的时间里的特别近。服务端的接口也有要求,返回的数据要支持多个请求的,一般是list集合。

比如说,服务端有一个根据id查询书的接口,传两个id去查询同一本书,或者两个不一样的id,查询两本不一样的书,然后返回来,这时候服务端本来是getBookById() 应该返回一个Book对象,但是要做请求合并的话,就不能返回Book对象,要返回一个List集合里面放了一个Book,因为这个请求结果可能有多个,拿到List集合之后再在consumer中自动的把list集合拆开,发到几个不同的请求里面去,然后那个请求就拿到了它的响应结果了,服务端返回的是list集合,客户端拿到的是Book对象。

下面写一个简单的例子:
首先在provider中的BookController中定义如下方法:


    /*一会儿在那边调用的时候,那个方法名叫,getBookById,就传一个Long类型的数据进来就行了
    请求合并的话,我可以把所有请求的参数收集起来,然后拼接成一个参数,主要格式就是自己来自定义
    我假设这里把参数的格式拼成: 1,2,3 ,4,5......
    * */
    @GetMapping("/book/{ids}")
    public List<Book> getBookByIds(@PathVariable String ids){
        System.out.println("ids>>>>>>>>>>"+ids);
        String[] split=ids.split(",");
        List<Book> books=new ArrayList<>();
        for (String s : split) {
            Book book = new Book();
            book.setId(Long.parseLong(s));
            books.add(book);
        }
       return  books;
    }

在consumer的BookService中添加如下代码:

 public List<Book> getBookByIds(List<Long> ids){
        Book[] books = restTemplateTwo.getForObject("http://provider/book/{1}", Book[].class, StringUtils.join(ids, ","));
        return Arrays.asList(books);
    }

在consumer中定义一个BookBachCommand

public class BookBatchCommand extends HystrixCommand<List<Book>> {

   BookSerivce bookSerivce;
   List<Long> ids;

    public BookBatchCommand(BookSerivce bookSerivce,List<Long> ids) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("CollapsingGroup"))
                .andCommandKey(HystrixCommandKey.Factory.asKey("CollapsingKey")));
        this.bookSerivce = bookSerivce;
    }

    @Override
    protected List<Book> run() throws Exception {
        return bookSerivce.getBookByIds(ids);
    }
}

然后在consumer中创建一个BookCollapseCommand 来调用BookBachCommand

public class BookCollapseCommand extends HystrixCollapser<List<Book>,Book,Long> {
  BookSerivce bookSerivce;
  Long id;

    public BookCollapseCommand(BookSerivce bookSerivce) {
        super(Setter.withCollapserKey(HystrixCollapserKey.Factory.asKey("bookCollapseCommand")).andCollapserPropertiesDefaults(HystrixCollapserProperties.Setter().withTimerDelayInMilliseconds(100)));
        //withTimerDelayInMilliseconds(100) 等待一百毫秒,如果有请求来就一起走,没有就自己走
        this.bookSerivce = bookSerivce;
    }

    @Override
    public Long getRequestArgument() {
        return id;
    }

    @Override
    protected HystrixCommand<List<Book>> createCommand(Collection<CollapsedRequest<Book, Long>> collection) {
        //ids就是合并后的请求的参数,collection其实就是待合并的请求
        List<Long> ids=new ArrayList<>((collection.size()));
        for (CollapsedRequest<Book, Long> request : collection) {
            //把请求的参数一个个放到ids中
            ids.add(request.getArgument());
        }
        return new BookBatchCommand(bookSerivce,ids);
    }

    @Override
    protected void mapResponseToRequests(List<Book> books, Collection<CollapsedRequest<Book, Long>> collection) {
        //第一个参数请求之后从provider上面拿过来的结果,第二个参数就是一个个的请求
        int count=0;
        for (CollapsedRequest<Book, Long> request : collection) {
            //把集合中的数据挨个取出来,分别设置给 request
            request.setResponse(books.get(count++));
        }

    }
}

然后再在BookController中创建一个方法用于测试:

@GetMapping("/test6")
    public void test6() throws ExecutionException, InterruptedException {
        HystrixRequestContext ctx = HystrixRequestContext.initializeContext();
        BookCollapseCommand bc1 = new BookCollapseCommand(bookSerivce, 99L);
        BookCollapseCommand bc2 = new BookCollapseCommand(bookSerivce, 99L);
        BookCollapseCommand bc3= new BookCollapseCommand(bookSerivce, 99L);
        BookCollapseCommand bc4 = new BookCollapseCommand(bookSerivce, 99L);
        //注意一定要先入队等待其他请求
        Future<Book> q1=bc1.queue();
        Future<Book> q2=bc2.queue();
        Future<Book> q3=bc3.queue();
        Future<Book> q4=bc4.queue();
        Book b1 = q1.get();
        Book b2 = q2.get();
        Book b3 = q3.get();
        Book b4 = q4.get();
        System.out.println(b1);
        System.out.println(b2);
        System.out.println(b3);
        System.out.println(b4);
        ctx.close();
    }

运行结果如下:
在这里插入图片描述在这里插入图片描述在provider中只调用了一次,而consumer中的四个请求各自拿到了他们想要的数据,这就是请求合并,他们的前提是这几个请求离得非常近。如果像如下那样就不行:
在这里插入图片描述会发两个请求,意味着第四个跟不上,单独发:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值