使用多个线程池和连接池

时间:2019-02-13 13:19:01

标签: java threadpool connection-pooling

我当前正在使用5个线程池,我想找​​到这些池的最佳大小。这是某种先验分析。池按使用情况划分:用于处理命令(cmdPool),处理库存事务(invPool),用于数据库事务的池(dbPool),还用于仅需要运行异步操作(例如I / O)的普通事务(fastPool)和计划任务的池(timerPool)。我还没有任何可用于解决问题的统计数据。

对于数据库查询,我使用具有默认值的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次。

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

1 个答案:

答案 0 :(得分:0)

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

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

重要的是删除类似于以下代码的代码:

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