【问题标题】:Using multiple threadpools and connection pool使用多个线程池和连接池
【发布时间】:2019-07-07 08:17:47
【问题描述】:

我目前正在使用 5 个线程池,我想为这些池找到最佳大小。这是某种先验分析。池按用途划分:用于处理命令(cmdPool)、处理库存事务(invPool)、用于数据库事务的池(dbPool),还用于只需要像 I/O 那样运行异步的普通事物(fastPool)和用于计划任务的池(计时器池)。我还没有任何可用于解决问题的统计数据。

对于数据库查询,我使用带有默认值的 HikariCP。稍后我将尝试更改最大连接数和最小空闲连接数以找到最佳性能。但是现在,当使用 Hikari 池时,总是会从其中一个池中调用它,以免影响主线程。通常的数据库查询是在 dbPool 下调用的,但仅当代码块不是已提交到线程池之一的已可运行文件的一部分时。

实际设置看起来它只是在应用程序中正常工作。所以我的问题是:

1.) 当我决定停止使用 cachedThreadPool 并使用具有一些最小空闲线程(如 timerPool)的池时,将如何影响性能和资源,或者我应该坚持使用 cached ?

2.) 设置最大池大小以防止在短时间内有 100 个客户端加入并让他们在其他任务完成时继续等待一段时间时出现峰值是正确的解决方案。

3.) 有没有更好的解决方案如何管理多种任务?

cmdPool = Executors.newFixedThreadPool(3);
invPool = Executors.newFixedThreadPool(2);
dbPool = Executors.newCachedThreadPool();
fastPool = Executors.newCachedThreadPool();
timerPool = new ScheduledThreadPoolExecutor(5);
timerPool.allowCoreThreadTimeOut(true);
timerPool.setKeepAliveTime(3, TimeUnit.MINUTES); 

首先,每个操作都取决于连接的客户端数量,假设有 5-25 个客户端这样的值。池的设计应该能够维持 100 个客户端这样的极端情况,并且不会在短时间内创建太多线程。

预期用途可能会有所不同,并且每秒都不相同,甚至可能根本不会运行任何任务。 cmdPool 的预期使用量是每秒使用 3-8 次(轻量级任务)。对于 invPool 的使用几乎与 cmdPool 相同,每秒使用 2-6 次(也是轻量级任务)。至于 dbPool,这比其他所有的都更难以预测,但仍然预期的使用量是每秒 5-20 次使用(轻量级和中量级任务)也取决于网络的繁忙程度。计时器和快速池旨在接受任何类型的任务并直接执行,预计每秒使用 20-50 次。

感谢您的任何建议,谢谢。

【问题讨论】:

    标签: java threadpool connection-pooling


    【解决方案1】:

    最好的解决方案是让您的应用程序适应预期的流量。 您可以通过多种方式做到这一点:

    • 微服务架构设计它,让编排器来处理流量高峰
    • 设计实时读取线程池大小的参数的应用程序(从数据库、文件、配置服务器...),这样您就可以在需要时更改值
    • 如果您只需要调整您的应用程序但不需要动态更改值,请将您的配置放入文件(或数据库)中。检查不同的配置以找到最适合您需求的配置

    重要的是去掉类似于这个的代码:

    cmdPool = Executors.newFixedThreadPool(3);
    

    并用与此类似的代码替换它

    @Value("${cmdPoolSize}")
    private int cmdPoolSize;
    
    ...
    
    cmdPool = Executors.newFixedThreadPool(cmdPoolSize);
    

    其中池的大小不是取自代码,而是取自外部配置

    更好的方法也是用参数定义池的种类:

    @Value("${cmdPoolType}")
    private String cmtPoolType;
    
    @Value("${cmdPoolSize}")
    private int cmdPoolSize;
    
    ...
    
    if (cmdPoolType.equals("cached")) {
      cmdPool = Executors.newCachedThreadPool();
    } else if (cmdPoolType.equals("fixed")) {
      cmdPool = Executors.newFixedThreadPool(cmdPoolSize);  
    }
    

    您在哪里选择合理的可用池类型。

    在最后一种情况下,您还可以使用 spring 配置文件并在启动应用程序之前对其进行更改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-13
      • 1970-01-01
      • 1970-01-01
      • 2016-05-24
      • 2020-02-09
      • 1970-01-01
      • 2010-09-24
      • 1970-01-01
      相关资源
      最近更新 更多