赞
踩
1)下图为一个的Constomer调用Provider的图
下图为在同一时间下共有的6个Customer要消费的Provider,那么此时就要通过的TOmcat的线程池创建6个线程访问的Provider,此时是没什么问题的。但是如果是500、1000个呢?Tomcat线程池是有上限的这样的势必是对Provider一个的跳转,如果压力过大Provider肯定是要出现问题的。那么我们就可以使用Hystrix的请求合并进行处理。
请求合并
下图为一个的请求合并之后的图,Hystrix会在指定的时间能,将所有的Constomer接收的请求合并成一个的请求,然后在将请求发送给的Provider,以此减少Provider的压力。
什么情况下使用请求合并
在微服务架构中,我们将一个项目拆分成很多个独立的模块,这些独立的模块通过远程 调用来互相配合工作,但是,在高并发情况下,通信次数的增加会导致总的通信时间增加, 同时,线程池的资源也是有限的,高并发环境会导致有大量的线程处于等待状态,进而导致 响应延迟,为了解决这些问题,我们需要来了解 Hystrix 的请求合并。
请求合并的缺点
设置请求合并之后,本来一个请求可能 5ms 就搞定了,但是现在必须再等 10ms 看看还 有没有其他的请求一起的,这样一个请求的耗时就从 5ms 增加到 15ms 了,不过,如果我们 要发起的命令本身就是一个高延迟的命令,那么这个时候就可以使用请求合并了,因为这个 时候时间窗的时间消耗就显得微不足道了,另外高并发也是请求合并的一个非常重要的场 景。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.7.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.sxt</groupId> <artifactId>19-hystrix-requestmerge</artifactId> <version>0.0.1-SNAPSHOT</version> <name>19-hystrix-requestmerge</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR2</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
spring.application.name=19-hystrix-requestmerge
server.port=9096
eureka.client.service-url.defaultZone=http://peer1:8081/eureka/,http://peer2:8082/eureka/,http://peer3:8083/eureka/
@SpringBootApplication
@EnableEurekaClient //开启服务注册
@EnableCircuitBreaker //开启熔断器
public class Application
{
public static void main(String[] args)
{
SpringApplication.run(Application.class, args);
}
}
创建ProviderService
@HystrixCollapser:该注解的作用是标识当前的方法是一个的合并请求的方法,并且此方法内的逻辑是不会被执行的
* batchMethod:请求合并完毕的后触发的方法
* scope:请求合并的模式
* collapserProperties:请求合并的设置
* timerDelayInMilliseconds:请求合并的等待的时间
* maxRequestsInBatch:指定时间内对请求合并的请求的最大数
* @retun: Future:注意请求的合并的方法的返回值必须为Future
@Service public class ProductService { /** * @param null * @description: 1.@HystrixCollapser:该注解的作用是标识当前的方法是一个的合并请求的方法,并且此方法内的逻辑是不会被执行的 * batchMethod:请求合并完毕的后触发的方法 * scope:请求合并的模式 * collapserProperties:请求合并的设置 * timerDelayInMilliseconds:请求合并的等待的时间 * maxRequestsInBatch:指定时间内对请求合并的请求的最大数 * @retun: Future:注意请求的合并的方法的返回值必须为Future * @author: shinelon * @time: 2019/9/3:17:30 */ @HystrixCollapser(batchMethod = "batchMethod", scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL, //请求时间间隔在 20ms 之内的请求会被合并为一个请求,默认为 10ms collapserProperties = { @HystrixProperty(name = "timerDelayInMilliseconds", value = "20"), //设置触发批处理执行之前,在批处理中允许的最大请求数。 @HystrixProperty(name = "maxRequestsInBatch", value = "200") }) public Future<Product> mergeRequest(Integer id) { System.out.println("========+" + id + "+======"); return null; } /** * 1.@HystrixCommand:表示当前的方法开启熔断 2.请求合并完毕后触发的方法,要和batchMethod 内的名字一致 3.在请求合并完毕后会将合并的参数的使用list集合的方式进行传递 * * @return */ @HystrixCommand public List<Product> batchMethod(List<Integer> ids) { for (Integer id : ids) { System.out.println(ids + "batchMethod------------"); } //相当于调用了Provider返回的数据 List<Product> list = Arrays.asList(new Product("电视", 1), new Product("电视", 2), new Product("电视", 3), new Product("电视", 4)); return list; } }
@Controller public class ProductController { @Autowired private ProductService productService; /** * 模拟测试请求的合并 * @throws ExecutionException * @throws InterruptedException */ @GetMapping(value = "/customer") public String setProductService() throws Exception { Future<Product> productFuture1 = this.productService.mergeRequest(1); Future<Product> productFuture2 = this.productService.mergeRequest(2); Future<Product> productFuture3 = this.productService.mergeRequest(3); Future<Product> productFuture4 = this.productService.mergeRequest(4); System.out.println(productFuture1.get().toString()); System.out.println(productFuture2.get().toString()); System.out.println(productFuture3.get().toString()); System.out.println(productFuture4.get().toString()); return ""; } }
1.合并的方法并没执行
2.Controller的调用是将所有的ID,被合并方法收集
3.返回的值存在于单个的结果并不是list,注意这里有个很大的弯,我们在使用请求的是的单个参数的请求,所以在请求合并之后是返回的单独的对象,虽然我们在合并之后的方法返回值为一个的List集合任意一个的。(因为我没有拿着传递的数据进行Provider的访问,别搞混了)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。