• 基于springboot线程池,来提高接口并发相关demo的性能压测和思考


    背景:

        线上有个接口,需要循环调用其他系统的列表接口服务,之前是串行服务,考虑通过线程池来提高并行能力,业务代码进行了抽象,具体demo如下:

    1. import com.facebook.presto.jdbc.internal.guava.collect.Lists;
    2. import com.google.common.util.concurrent.ThreadFactoryBuilder;
    3. import com.vip.vman.service.RedisService;
    4. import lombok.extern.slf4j.Slf4j;
    5. import org.apache.kafka.common.errors.ApiException;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.web.bind.annotation.RequestMapping;
    8. import org.springframework.web.bind.annotation.RequestMethod;
    9. import org.springframework.web.bind.annotation.RestController;
    10. import java.util.ArrayList;
    11. import java.util.List;
    12. import java.util.concurrent.*;
    13. @Slf4j
    14. @RestController
    15. @RequestMapping(value = "/vman/thread")
    16. public class ThreadController {
    17. @Autowired
    18. RedisService redisService;
    19. ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("thread-get-all-test-%d").build();
    20. private final ExecutorService executorService = new ThreadPoolExecutor(50,60, 180L, TimeUnit.SECONDS,new LinkedBlockingQueue(),namedThreadFactory);
    21. /**
    22. * 1、假设列表总共有100个任务 、每个业务处理时长 100ms,下面压测数据
    23. * 2、如果核心线程数是 20时,压测耗时 500ms
    24. * 3、如果核心线程数是 50时,压测耗时 200ms
    25. * 3、如果是走串行任务,发现固定耗时在 10000ms
    26. */
    27. @RequestMapping(value = "/test_thread", method = RequestMethod.GET)
    28. public void executeTask4(Integer id) throws InterruptedException {
    29. List<Integer> list = Lists.newLinkedList();
    30. for (int i = 0; i <100; i++) {
    31. list.add(i);
    32. }
    33. String str = redisService.getJedis().get("is_use_multi_thread");
    34. long currentTime = System.currentTimeMillis();
    35. if ("1".equals(str)) {
    36. multiThreadProcessSpaceSubjectGroup(list);
    37. }else {
    38. singleThreadProcessSpaceSubjectGroup(list);
    39. }
    40. log.info("整个任务运行时间:{}, is_use_multi_thread:{},", System.currentTimeMillis() - currentTime, str);
    41. }
    42. private void singleThreadProcessSpaceSubjectGroup(List<Integer> list) throws InterruptedException {
    43. for (Integer id : list) {
    44. log.info("执行接口任务任务:{}",id);
    45. Thread.sleep(100);
    46. }
    47. }
    48. private void multiThreadProcessSpaceSubjectGroup(List<Integer> list) {
    49. List<Future<?>> futures = new ArrayList<>();
    50. for (Integer id : list) {
    51. Callable<Void> crossSubjectCallable = () -> {
    52. log.info("执行接口任务任务:{}",id);
    53. if( id == 10) {
    54. throw new ApiException("接口异常");
    55. }
    56. Thread.sleep(100);
    57. return null;
    58. };
    59. futures.add(executorService.submit(crossSubjectCallable));
    60. }
    61. for (Future<?> future : futures) {
    62. try {
    63. future.get();
    64. } catch (InterruptedException | ExecutionException e) {
    65. // Handle exceptions
    66. log.info("获取接口异常:{}", e);
    67. }
    68. }
    69. }
    70. }

    压测的接口数据:

    任务类型任务数核心线程数执行耗时
    串行执行100串行可以理解单线程10000ms
    线程池执行10020500ms
    线程池执行10050200ms

    通过改变线程池的核心线程数,发现接口性能提升明显,也参考了针对高并发场景相关线程,

    业务场景线程池策略原因备注
    高并发低耗时线程数可以设置少点如果设置线程数多,可能引起线程频繁切换,反而更耗时
    低并发高耗时线程数可以设置多点线程切换不会影响长耗时任务
    高并发高耗时

    重点:

  • 相关阅读:
    设计思维及在Thoughtworks的应用
    矢量绘图软件 Sketch mac中文版介绍
    Python小功能实现(链接下载图品并存储到EXCEL中)
    svn入门到精通
    导致word文档损坏故障发生的原因是什么?
    JavaScript中的`async`和`await`关键字的作用
    基础 IO (Linux学习笔记)
    C++ 实战Mongodb CRUD操作基本用法
    CICD 持续集成与持续交付——gitlab
    Spring源码:ApplicationContextAware和BeanFactoryAware理解BeanFactory和Aware
  • 原文地址:https://blog.csdn.net/wppwpp1/article/details/132904252