java - Java中的连接池和线程池设置
问题描述
使用 Hikari 池的 Spring 应用程序。
现在对于来自客户端的单个请求,我必须查询 10 个表(业务需要),然后将结果组合在一起。查询每个表可能需要 50 毫秒到 200 毫秒。为了加快响应时间,我FixedThreadPool
在我的服务中创建了一个查询不同线程中的每个表(伪代码):
class MyService{
final int THREAD_POOL_SIZE = 20;
final int CONNECTION_POOL_SIZE = 10;
final ExecutorService pool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
protected DataSource ds;
MyClass(){
Class.forName(getJdbcDriverName());
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(CONNECTION_POOL_SIZE);
ds = new HikariDataSource(config);
}
public Items doQuery(){
String[] tables=["a","b"......]; //10+ tables
Items result=new Items();
CompletionService<Items> executorService = new ExecutorCompletionService<Items>(pool);
for (String tb : tables) {
Callable<Item> c = () -> {
Items items = ds.getConnection().query(tb); ......
return Items;
};
executorService.submit(c);
}
for (String tb: tables) {
final Future<Items> future = executorService.take();
Items items = future.get();
result.addAll(items);
}
}
}
现在对于单个请求,平均响应时间可能为 500 毫秒。
但是对于并发请求,平均响应时间会迅速增加,请求越多,响应时间就会越长。
我想知道如何设置正确的连接池大小和线程池大小以使应用程序有效工作?
顺便说一句,该数据库在云中使用 RDS,具有 4 个 cpu 16GB 内存、2000 个最大连接数和 8000 个最大 IOPS。
解决方案
您可能需要考虑更多参数:
1. 数据库的最大并发请求参数。云提供商对不同层的并发请求有不同的限制,您可能需要检查一下。
2. 说50-200ms,虽然很难说,是平均有8个50ms的请求和2个200ms的请求,还是几乎都差不多?为什么?您的 doQuery 可能会受到最长查询时间(即 200 毫秒)的限制,但需要 50 毫秒的线程将在其任务完成后释放,使其可用于下一组请求。
3. 您期望收到的 QPS 是多少?
一些计算:如果单个请求占用 10 个线程,并且您配置了 100 个连接和 100 个并发查询限制,假设每个查询 200ms,您一次只能处理 10 个请求。如果大多数查询需要 50 毫秒左右,可能会比 10 好一点(但我不会乐观)。
当然,如果您的任何查询花费 >200 毫秒(网络延迟或其他任何东西),这些计算中的某些计算就会被折腾,在这种情况下,我建议您在连接端有一个断路器(如果您被允许中止超时后的查询)或在 API 端。
注意:最大连接限制与最大并发查询限制不同。
建议:由于需要500ms以下的响应,池上也可以有100-150ms左右的connectionTimeout。最坏的情况:150 毫秒连接超时 + 200 毫秒查询执行 + 100 毫秒应用程序处理 < 500 毫秒的响应。作品。
推荐阅读
- unity3d - Unity3D:水平移动播放器时遇到问题
- amazon-web-services - Use external ActiveMQ broker as trigger for AWS Lambda
- mysql - 使用 Sequelize 查询多个表
- delphi - 读取 ISAPI DLL 中的请求标头
- reactjs - Firestore join user to its collection data in ReactJS
- multithreading - how to debug ipc programs
- vba - Sum of dynamic range
- android - 如何在 x 次点击后显示插页式广告?
- google-cloud-build - Optionally run Cloud Build trigger on commit
- android - In retrofit, can I get the endpoint uri with all dynamic values/query params before making the call?