玩转SpringCloud专题(十七)-SpringCloud之Hystrix请求合并

本文我们来演示下Hystrix中解决雪崩效应的第三种方式请求合并的实现

1.请求合并的场景

没有合并的场景中,对于provider的调用会非常的频繁,容易造成处理不过来的情况
玩转SpringCloud专题(十七)-SpringCloud之Hystrix请求合并_第1张图片
合并请求的场景
玩转SpringCloud专题(十七)-SpringCloud之Hystrix请求合并_第2张图片

2.什么情况下使用请求合并

在微服务架构中,我们将一个项目拆分成很多个独立的模块,这些独立的模块通过远程调用来互相配合工作,但是,在高并发情况下,通信次数的增加会导致总的通信时间增加,同时,线程池的资源也是有限的,高并发环境会导致有大量的线程处于等待状态,进而导致响应延迟,为了解决这些问题,我们需要来了解 Hystrix 的请求合并。

3.请求合并的缺点

设置请求合并之后,本来一个请求可能 5ms 就搞定了,但是现在必须再等 10ms 看看还有没有其他的请求一起的,这样一个请求的耗时就从 5ms 增加到 15ms 了,不过,如果我们要发起的命令本身就是一个高延迟的命令,那么这个时候就可以使用请求合并了,因为这个时候时间窗的时间消耗就显得微不足道了,另外高并发也是请求合并的一个非常重要的场景。

4.请求合并案例

4.1.添加依赖

将Hystrix的依赖添加即可


<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-netflix-hystrixartifactId>
dependency>
4.2.启动类修改

启动类中开启@EnableCircuitBreaker注解。

/**
 * @author bruceliu
 * @create 2019-10-15 14:36
 * @description
 */
@SpringBootApplication
@EnableDiscoveryClient // 开启EurekaClient功能
@EnableFeignClients // 开启Feign功能
@EnableCircuitBreaker//对hystrixR熔断机制的支持
public class ConsumerApp {

    public static void main(String[] args) {
        System.out.println("服务的调用端启动8082.....");
        SpringApplication.run(ConsumerApp.class,args);
    }
}
4.3.业务层修改

具体代码如下,要注意的是getUser方法的返回类型必须是Future类型,batchMethod 属性指定的是请求合并后要执行的方法的名称。

package com.bruceliu.api;

import com.bruceliu.bean.User;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;

/**
 * @BelongsProject: springcloud0310
 * @BelongsPackage: com.bruceliu.api
 * @Author: bruceliu
 * @QQ:1241488705
 * @CreateTime: 2020-03-11 20:00
 * @Description: TODO
 */
@Service
public class UserService {

    /**
     * consumer 的 controller 调用的方法
     * 该方法返回值必须要返回Future 类型
     * 利用 hystrix 合并请求
     */
    @HystrixCollapser(
            batchMethod = "batchUser", scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL, collapserProperties = {
            //请求时间间隔在 20ms 之内的请求会被合并为一个请求,默认为 10ms
            @HystrixProperty(name = "timerDelayInMilliseconds", value = "20"),
            //设置触发批处理执行之前,在批处理中允许的最大请求数。
            @HystrixProperty(name = "maxRequestsInBatch", value = "200"),
    })
    public Future<User> getUser(Integer id) {
        System.out.println("-----------id-------:" + id);
        return null;
    }

    /**
     * 调用 Provider 服务的方法
     *
     * @param ids
     * @return
     */
    @HystrixCommand
    public List<User> batchUser(List<Integer> ids) {
        for (Integer id : ids) {
            System.out.println(id);
        }
        //假设是调用 provider 服务后返回的 list
        List<User> list = new ArrayList<>();
        list.add(new User(1, "张三", 18));
        list.add(new User(2, "李四", 19));
        list.add(new User(3, "王五", 20));
        list.add(new User(4, "小明", 21));
        list.add(new User(100, "小张", 22));
        System.out.println("***********************");
        return list;
    }
}

4.4.控制器调用

调用service的方法,模拟多次请求的场景,具体如下

@RestController
public class UserController {

    @Autowired
    private UserService userService;
    @RequestMapping("/consumer")
    public void getUsers() throws Exception{

        Future<User> f1 = this.userService.getUser(1);
        Future<User> f2 = this.userService.getUser(2);
        Future<User> f3 = this.userService.getUser(3);
        System.out.println(f1.get().toString());
        System.out.println(f2.get().toString());
        System.out.println(f3.get().toString());
    }
}
4.5.测试

启动服务后访问,查看控制台效果,发现虽然请求了多次service,但是batchUser方法只执行了一次
玩转SpringCloud专题(十七)-SpringCloud之Hystrix请求合并_第3张图片
只执行了一次,获取了三个结果!

4.5.控制器调用
参数 作用/默认值 备注
@HystrixCollapser
batchMethod 合并请求的方法
scope 请求方式/REQUEST 请求方式分为REQUEST和GLOBAL。REQUEST范围只对一个request请求内的多次服务请求进行合并 GLOBAL是多单应用中的所有线程的请求中的多次服务请求合并
timerDelayInMilliseconds 请求时间间隔在10ms之内的请求会被合并为一个请求/10ms 建议尽量设置的小一点,如果并发量不大的话,其实也没有必要使用HystrixCollapser来处理
maxRequestsInBatch 设置触发批处理执行之前,在批处理中允许的最大请求数/Integer.MAX_VALUE

你可能感兴趣的:(玩转SpringCloud)