使用多个线程池和连接池

Using multiple threadpools and connection pool

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

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

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

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 次。

感谢任何建议,谢谢。

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

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

重要的是移走与此类似的代码:

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 配置文件并在启动应用程序之前更改它。