为何不宜监测连接池利用量

Posted 蓝海讯通OneAPM

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为何不宜监测连接池利用量相关的知识,希望对你有一定的参考价值。





我在工作过程中长期接触那些对性能敏感的应用。正如我们所意料到的,其中多数都必须在这一点或者那一点使用数据库,因此最终就不可避免地就有了连接池。此时为防止应用等待连接,就会对连接池的利用量进行监测。可这种监测真的有用吗?说实话,真的没用……


应用如何使用连接池?


今天多数应用对连接池的使用都是隐式的。应用首先取得连接,然后执行一些语句,最后关闭连接。在关闭调用时,应用并不会破坏连接,而是要将其放回连接池,以尽量减小所谓的繁忙时间。在更深层次上,多数应用服务器在交易被提交之前,都不会将连接放回连接池。为此较好的做法就是在事务过程中要尽可能晚一点儿取得数据库连接。这样做的目的仍是最大限度缩短利用时间,从而让大量应用线程能够分享有限数量的连接。


所有连接池都具备一个利用量测量值,用以确定可用连接是否足够,换句话说,就是看看连接的缺乏是否存在不利影响。但由于一个连接只会被占用非常短的时间(常常是几分之一秒),因此我们需要同等频繁地检查利用量,如此才有统计上显著的机会来发现连接池在正常条件下是否达到最大占用。


JDBC 连接池利用量


为何不宜监测连接池利用量
每10秒轮询一次时的连接池利用量


可实际上事情还没完——由于过于频繁地检查连接池(比如说一秒钟好几次)会引起很大的监测开销,因此多数解决方案都会每两秒检查一次,这样只有在连接池始终达到最大占用时,我们才会看到利用量达到100%。如果连续跟踪利用量,那么结果就会不同:



为何不宜监测连接池利用量

连续而非轮询跟踪最小/最大和平均值时看到的连接池利用量


这就意味着,当我们采用常规监测解决方案看到100%的连接池利用量时,性能就已经遇到了显著的不利影响——但真是这样吗?

为何不宜监测连接池利用量


100%的连接池利用量到底意味着什么?


实际上没有太多的意义,不过是说连接池中的所有连接都在使用状态,但却并不意味着有任何事务因此而遇到性能问题。在连续负载情境中,我们可以轻松调整设置,让连接池利用量始终达到100%,同时不让任何事务遇到问题;这正是完美状态。


但许多用例并没有稳定的连续负载模式,因此在连接池利用量远未达到100%时我们就将注意到性能退化。连接池利用量没告诉我们任何事情;连接取得时间才告诉了我们一些情况!



本图所示为连接池利用量和最小/最大连接取得时间。尽管连接池从未达到最大占用量,但连接取得时间仍然不为零。


多数应用服务器和连接池都具有一个等待或占用指标,这个指标比连接池利用量更值得我们关心。连接取得时间代表的是事务为了从连接池中取得连接而必须等待的时间,故而表示了一种真实、可操作的信息。如果该时间上升,我们就知道连接池中的连接有时不够(或者连接池本身就没写好)。在连接池平均利用量远未接近100%时,这一测量值就会显示出显著的等待时间。不过仍有一个小问题:


这个测量值仍然是整个连接池的(更具体地说是所有事务的)汇总平均值。因此尽管通过它我们可以理解总体上是否有足够的连接,但却不能识别哪些业务事务受到影响以及受影响的程度。


正确测量连接取得时间


简单地说,连接取得时间就是getConnection调用返回所花费的时间。我们可以在事务内部轻松测得这一时间,并且可在测量后将该时间计入各笔业务事务,而非作为整个连接池的平均值。这就意味着对于每一事务类型,我们都能确切地知道需要花去多少等待时间——毕竟,在一个平均响应时间为一秒的事务中,我不在乎等上10ms;但在响应时间为100ms的事务类型中,等候10ms就是不可接受的。


单笔事务中测量的getConnection调用。虽然连接池平均时间为0.5ms,但调用时间却达到了10ms。


我们甚至可以确定哪些事务正在以并发方式竞争有限的连接,同时还可理解异常值(意思就是在偶然情况下某笔事务花费了相对较长的时间来等待连接。如果连接取得时间的测量不正确,那么这种情况就会因为平均效应而被隐藏)。


配置最优的连接池尺寸


有时候不容易提前知道该把连接池配置成多大。实际上,多数人对连接池尺寸的设置都比较随意,只是简单地把它设置成一个在他们看来足够大的值。尽管在某些处理量较大的情况下无法始终避免等待,但我们可在充分理解这一尺寸的基础上来优化这一尺寸。


有一种非常简单并且实用的方式来实现这一点——只需在峰值负载期间监测连接取得时间即可,并且最好如上所述按照各笔业务事务进行监测。此时尤其要注意该时间对响应时间的贡献量,并且一定要从分析中扣除那些根本没有等待的事务——这些事务只会致使计算扭曲。


如果对具体业务事务的平均响应时间贡献度非常低(比如说低于1%),那么就可以说连接池足够大。重点要注意的是,我这里说的不是绝对的毫秒时间,而是贡献时间!如果贡献时间太高(比如说达到甚至超过5%),则需将连接池加大到贡献时间可以接受为止。而所导致的平均连接池利用量,平均起来可能非常低,也可能接近100%,但都无所谓!


结论


连接池测量值的用处大小取决于连接池轮询的频率。轮询得越多,添加的开销就越多——而到头来得到的测量值仍不过是猜测值。连接取得时间等影响量测量值的用处和可操作性就要大得多。我们可以通过这一测量值把连接池调整到没有开销(或者与响应时间相比至少可以接受)的点。与所有影响量测量值一样,最好不要使用总体平均值,而是要从该测量值对最终用户响应时间的贡献的角度来理解这个测量值。


以上是关于为何不宜监测连接池利用量的主要内容,如果未能解决你的问题,请参考以下文章

Tomcat 连接池详解

数据库连接池的配置

[数据库连接池] Java数据库连接池--DBCP浅析.

你真的熟悉数据连接池吗?手写实现连接池

[八]数据库连接池与JDBC。纳尼?连接池关JDBC神马事?

JDBC连接池