• 使用Hystrix实现请求合并,降低服务器并发压力


    1.引入Hystrix 

    1. <dependency>
    2. <groupId>org.springframework.cloudgroupId>
    3. <artifactId>spring-cloud-starter-netflix-hystrixartifactId>
    4. dependency>

    2.在启动类上开启Hystrix功能

    @EnableHystrix

    3.请求合并实现代码

    1. import com.bzcst.bop.oms.orm.model.po.Product;
    2. import com.bzcst.bop.oms.orm.service.ProductService;
    3. import com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser;
    4. import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    5. import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
    6. import com.netflix.hystrix.contrib.javanica.conf.HystrixPropertiesManager;
    7. import lombok.extern.slf4j.Slf4j;
    8. import org.springframework.stereotype.Service;
    9. import javax.annotation.Resource;
    10. import java.util.List;
    11. import java.util.concurrent.Future;
    12. /**
    13. * @author 向振华
    14. * @date 2023/10/26 14:37
    15. */
    16. @Slf4j
    17. @Service
    18. public class BatchService {
    19. @Resource
    20. private ProductService productService;
    21. @HystrixCollapser(
    22. batchMethod = "getByIds",
    23. scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL,
    24. collapserProperties = {
    25. @HystrixProperty(name = HystrixPropertiesManager.MAX_REQUESTS_IN_BATCH, value = "10"),
    26. @HystrixProperty(name = HystrixPropertiesManager.TIMER_DELAY_IN_MILLISECONDS, value = "20")
    27. }
    28. )
    29. public Future getById(Long id) {
    30. return null;
    31. }
    32. @HystrixCommand
    33. public List getByIds(List ids) {
    34. log.info("批查询 ---> " + ids);
    35. return productService.listByIds(ids);
    36. }
    37. }

    其中getById(Long id)方法并不会进入。 

    其中ProductService 是基于mybatisplus的查询接口

    1. import com.bzcst.bop.oms.orm.model.po.Product;
    2. import com.baomidou.mybatisplus.extension.service.IService;
    3. public interface ProductService extends IService {
    4. }

     4.调用

    1. import cn.hutool.http.HttpRequest;
    2. import cn.hutool.http.HttpResponse;
    3. import com.bzcst.bop.oms.orm.model.po.Product;
    4. import org.springframework.web.bind.annotation.GetMapping;
    5. import org.springframework.web.bind.annotation.PathVariable;
    6. import org.springframework.web.bind.annotation.RestController;
    7. import javax.annotation.Resource;
    8. import java.util.concurrent.CountDownLatch;
    9. import java.util.concurrent.ExecutorService;
    10. import java.util.concurrent.Executors;
    11. import java.util.concurrent.Future;
    12. /**
    13. * @author 向振华
    14. * @date 2023/10/26 14:32
    15. */
    16. @RestController
    17. public class TestController {
    18. @Resource
    19. private BatchService batchService;
    20. @GetMapping("/product/{id}")
    21. public Object product(@PathVariable Long id) throws Exception {
    22. Future productFuture = batchService.getById(id);
    23. return productFuture.get();
    24. }
    25. public static void main(String[] args) {
    26. // 创建线程池
    27. ExecutorService executorService = Executors.newFixedThreadPool(20);
    28. // 模拟20个并发请求
    29. CountDownLatch countDownLatch = new CountDownLatch(20);
    30. for (int i = 1; i <= 20; i++) {
    31. int fi = i;
    32. executorService.execute(() -> {
    33. try {
    34. countDownLatch.await();
    35. HttpRequest httpRequest = HttpRequest.get("http://localhost:8080/bop-oms/product/" + fi);
    36. String body = httpRequest.execute().body();
    37. System.out.println(fi + " ---> " + body);
    38. } catch (Exception e) {
    39. }
    40. });
    41. countDownLatch.countDown();
    42. }
    43. }
    44. }

    日志记录可以看出是批量处理

    1. 2023-10-26 17:54:31.708 INFO 10524 --- [-BatchService-9] c.bzcst.bop.oms.controller.BatchService : 批查询 ---> [10, 5, 9, 15, 4, 12, 11, 16, 8, 14]
    2. Creating a new SqlSession
    3. SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@58dfec5b] was not registered for synchronization because synchronization is not active
    4. parser sql: SELECT id, xxx FROM oms_product WHERE id IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    5. 2023-10-26 17:54:31.712 INFO 10524 --- [-BatchService-8] c.bzcst.bop.oms.controller.BatchService : 批查询 ---> [3, 18, 1, 13, 7, 19, 20, 2, 6, 17]
    6. Creating a new SqlSession
    7. SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4235ea19] was not registered for synchronization because synchronization is not active
    8. parser sql: SELECT id, xxx FROM oms_product WHERE id IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    9. JDBC Connection [HikariProxyConnection@935862209 wrapping com.mysql.cj.jdbc.ConnectionImpl@130542a5] will not be managed by Spring
    10. ==> Preparing: SELECT id, xxx FROM oms_product WHERE id IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    11. ==> Parameters: 10(Long), 5(Long), 9(Long), 15(Long), 4(Long), 12(Long), 11(Long), 16(Long), 8(Long), 14(Long)
    12. JDBC Connection [HikariProxyConnection@205926351 wrapping com.mysql.cj.jdbc.ConnectionImpl@67b600cc] will not be managed by Spring
    13. ==> Preparing: SELECT id, xxx FROM oms_product WHERE id IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    14. ==> Parameters: 3(Long), 18(Long), 1(Long), 13(Long), 7(Long), 19(Long), 20(Long), 2(Long), 6(Long), 17(Long)
    15. <== Columns: id, tenant_id, category_id, name, code, price, ladder_price, is_ladder_price, unit, is_enabled, description, version, create_by, create_time, update_by, update_time, delete_flag
    16. <== Row: 4, 1, 0, 转供电, 4, 4.00, , 0, , 1, , 1, , 2022-12-29 17:01:09, , 2022-12-29 17:01:09, 0
    17. <== Row: 5, 1, 0, 通下水道, XSD, 5.00, , 0, , 1, , 1, , 2023-05-23 18:24:30, , 2023-05-23 18:24:30, 0
    18. <== Row: 8, 1, 0, 门卡押金, 0302, 8.00, , 0, , 1, , 1, , 2023-03-04 10:57:50, , 2023-04-14 09:53:17, 0
    19. <== Row: 9, 1, 0, 阶梯单价, 12321, 9.00, , 1, , 1, , 1, , 2023-10-13 16:39:09, , 2023-10-13 16:39:09, 0
    20. <== Row: 10, 1, 0, 阿萨德, 123333, 10.00, , 0, , 1, , 1, , 2023-09-14 10:43:01, , 2023-09-14 10:43:01, 0
    21. <== Row: 11, 1, 0, 补贴空置费, 444, 11.00, , 0, , 1, , 1, , 2023-03-02 17:05:10, , 2023-03-02 17:05:10, 0
    22. <== Row: 12, 1, 0, 路灯费, B12.00, , 0, , 1, , 1, , 2023-03-03 10:55:23, , 2023-03-03 10:55:23, 0
    23. <== Row: 14, 1, 0, 零星物业, 3, 14.00, , 0, , 1, , 1, , 2023-03-02 16:50:05, , 2023-03-02 16:50:05, 0
    24. <== Row: 15, 1, 0, 零星电费, 2, 15.00, , 0, , 1, , 1, , 2023-03-02 16:49:46, , 2023-03-02 16:49:46, 0
    25. <== Row: 16, 1, 0, 非生活垃圾清运费, 16, 16.00, , 0, , 1, , 1, , 2022-12-29 17:01:09, , 2022-12-29 17:01:09, 0
    26. <== Total: 10
    27. Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@58dfec5b]
    28. <== Columns: id, tenant_id, category_id, name, code, price, ladder_price, is_ladder_price, unit, is_enabled, description, version, create_by, create_time, update_by, update_time, delete_flag
    29. <== Row: 1, 1, 0, 专项维修金, 1, 1.00, , 0, , 1, , 1, , 2022-12-29 17:01:09, , 2022-12-29 17:01:09, 0
    30. <== Row: 2, 1, 0, 车位空置费, 2, 2.00, , 0, , 1, , 1, , 2022-12-29 17:01:09, , 2022-12-29 17:01:09, 0
    31. <== Row: 3, 1, 0, 车位费, CWF01, 3.00, , 0, , 1, , 1, , 2023-10-10 09:57:07, , 2023-10-10 09:57:07, 0
    32. <== Row: 6, 1, 0, 服务费, 6, 6.00, , 0, , 1, , 1, , 2022-12-29 17:01:09, , 2022-12-29 17:01:09, 0
    33. <== Row: 7, 1, 0, 销售配合费, s, 7.00, , 0, , 1, , 1, , 2022-12-29 17:01:09, , 2022-12-29 17:01:09, 0
    34. <== Row: 13, 1, 0, 零星水费, 1, 13.00, , 0, , 1, , 1, , 2023-03-02 16:49:18, , 2023-03-02 16:49:18, 0
    35. <== Row: 17, 1, 0, 顾问费, 17, 17.00, , 0, , 1, , 1, , 2022-12-29 17:01:09, , 2022-12-29 17:01:09, 0
    36. <== Row: 18, 1, 0, 餐饮垃圾费, 18, 18.00, , 0, , 1, , 1, , 2022-12-29 17:01:09, , 2022-12-29 17:01:09, 0
    37. <== Row: 19, 1, 0, 租赁广告费用, 1000123, 19.00, [], 0, , 1, , 1, , 2023-06-08 10:51:16, , 2023-06-08 10:51:16, 0
    38. <== Row: 20, 1, 0, 租金, ZJ002, 20.00, [], 0, , 1, , 1, , 2023-03-15 17:40:12, , 2023-03-15 17:40:12, 0
    39. <== Total: 10
    40. Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4235ea19]

    或者这样请求也可以

    1. @GetMapping("/product")
    2. public void product() throws Exception {
    3. List list = new ArrayList<>();
    4. for (long i = 1; i <= 20; i++) {
    5. Future productFuture = batchService.getById(i);
    6. list.add(productFuture);
    7. }
    8. for (Future future : list) {
    9. Object o = future.get();
    10. System.out.println(o);
    11. }
    12. }

    如果scope是REQUEST方式,则需要使用HystrixRequestContext

    1. @GetMapping("/product")
    2. public void product() throws Exception {
    3. HystrixRequestContext context = HystrixRequestContext.initializeContext();
    4. try {
    5. List list = new ArrayList<>();
    6. for (long i = 1; i <= 20; i++) {
    7. Future productFuture = batchService.getById(i);
    8. list.add(productFuture);
    9. }
    10. for (Future future : list) {
    11. Object o = future.get();
    12. System.out.println(o);
    13. }
    14. } finally {
    15. context.shutdown();
    16. }
    17. }

    5.@HystrixCollapser参数介绍

    batchMethod,请求合并方法

    scope,请求合并方式,REQUEST:请求范围,GLOBAL:全局范围,默认com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL

    collapserProperties
    HystrixPropertiesManager.MAX_REQUESTS_IN_BATCH 最大请求合并数量,默认Integer.MAX_VALUE
    HystrixPropertiesManager.TIMER_DELAY_IN_MILLISECONDS 请求合并间隔毫秒值,默认10ms

    注意,达到请求合并间隔毫秒值,没达到最大请求合并数量时,也会进行请求合并

    @HystrixCollapser是基于Spring的AOP实现的

    com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect

    6.请求合并工作流程图

  • 相关阅读:
    ansible file模块、参数详细讲解、例子
    蓝牙低能耗安全连接 – 数值比较
    【Arduino24】8*8点阵实验
    MySQL--大数据量的分页优化方案
    微电子/集成电路专业学术期刊汇总!
    什么是虚拟局域网?快解析有哪些的虚拟化应用功能?
    一种影像比对快速提取建筑物要素变化的方法
    node.js -- 身份认证
    vscode配合gitee同步云设置
    C++对象模型(17)-- 构造函数语义学:成员初始化列表
  • 原文地址:https://blog.csdn.net/Anenan/article/details/134060235