druid连接池源码剖析
介绍
我一直在从事的所有项目都使用了数据库连接池 ,这是有很好的理由的。 有时我们可能会忘记为什么我们采用一种设计模式或一种特定技术,因此值得退后一步并对其进行推理。 每项技术或技术决策都有其优点和缺点,如果看不到任何缺点,您需要怀疑自己缺少什么。
数据库连接生命周期
每个数据库读取或写入操作都需要一个连接。 因此,让我们看一下数据库连接流的样子:
流程如下所示:
- 应用程序数据层向数据源请求数据库连接
- 数据源将使用数据库驱动程序打开数据库连接
- 创建数据库连接并打开TCP套接字
- 应用程序读/写数据库
- 不再需要连接,因此已关闭
- 插座已关闭
您可以轻松推断出打开/关闭连接是一项非常昂贵的操作。 PostgreSQL对每个客户端连接使用单独的OS进程 ,因此打开/关闭连接的高速率将给数据库管理系统带来压力。
重用数据库连接的最明显原因是:
- 减少用于创建/销毁TCP连接的应用程序和数据库管理系统OS I / O开销
- 减少JVM对象垃圾
集中与不集中
让我们比较一下无池解决方案与HikariCP的比较,后者可能是可用的最快的连接池框架。
该测试将打开和关闭1000个连接。
private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceConnectionTest.class);
private static final int MAX_ITERATIONS = 1000;
private Slf4jReporter logReporter;
private Timer timer;
protected abstract DataSource getDataSource();
@Before
public void init() {
MetricRegistry metricRegistry = new MetricRegistry();
this.logReporter = Slf4jReporter
.forRegistry(metricRegistry)
.outputTo(LOGGER)
.build();
timer = metricRegistry.timer("connection");
}
@Test
public void testOpenCloseConnections() throws SQLException {
for (int i = 0; i < MAX_ITERATIONS; i++) {
Timer.Context context = timer.time();
getDataSource().getConnection().close();
context.stop();
}
logReporter.report();
}
该图表显示了打开和关闭连接所花费的时间,因此越低越好。
连接池比无池替代要快600倍 。 我们的企业系统由数十个应用程序组成,仅一个批处理系统每小时可以发出超过200万个数据库连接,因此值得考虑2个数量级的优化。
类型 | 无汇集时间(毫秒) | 连接池化时间(毫秒) |
---|---|---|
分 | 74.551414 | 0.002633 |
最高 | 146.69324 | 125.528047 |
意思 | 78.216549 | 0.128900 |
标准差 | 5.9438335 | 3.969438 |
中位数 | 76.150440 | 0.003218 |
为什么合并速度如此之快?
要了解池解决方案为什么表现如此出色,我们需要分析池连接管理流程:
每当请求连接时,池数据源将使用可用的连接池来获取新的连接。 仅当没有可用连接并且池尚未达到最大大小时,池才会创建新连接。 池连接的close()方法将返回到池的连接,而不是实际关闭它。
更快更安全
连接池充当传入连接请求的有界缓冲区。 如果出现流量高峰,连接池将对其进行分级,而不是使所有可用数据库资源饱和。
等待步骤和超时机制是安全钩,可防止过多的数据库服务器负载。 如果一个应用程序获得了太多的数据库流量,则连接池将减轻它的负担,从而防止它关闭数据库服务器(因此影响整个企业系统)。
拥有权利的同时也被赋予了重大的责任
所有这些好处都是有代价的,池配置的额外复杂性(尤其是在大型企业系统中)体现了这一点。 因此,这不是银弹,您需要注意许多池设置,例如:
- 最小尺寸
- 最大尺寸
- 最大空闲时间
- 获取超时
- 超时重试尝试
我的下一篇文章将探讨企业连接池的挑战以及Flexy Pool如何帮助您找到合适的池大小。
- 代码可在GitHub上获得 。
翻译自: https://www.javacodegeeks.com/2014/04/the-anatomy-of-connection-pooling.html
druid连接池源码剖析