关乎性能的思考
来源:互联网 发布:seven stars烟淘宝 编辑:程序博客网 时间:2024/05/16 05:37
那么,现在步入正题。首先我想分享的是使用Jmeter做DBCP的调优。调优的初衷很简单,提高TPS,同时减少数据库灾难带来的连接池exhaust(提高可用性)。第一个调优目标,是个很业务的事情,需要根据你的业务场景进行调整,策略上最值得注意的是maxIdle和minIdle两个参数,类似Java的-Xmx和-Xms的设置。剩下的一些参数调整,个人觉得没什么借鉴意义,所以就不赘述了,毕竟这是一件很业务的事情。再看另一个目标,这里我主要想说的是removeAbandoned和removeAbandonedTimeout。从软件的健壮性来讲,边界值问题尤为重要。在资源获取型编码过程中,最好的体现就是超时时间的设置,这是个很经验,很统计概率的事情。对样本空间进行充分取样,一定可以得出该样本空间样本点的均值,当然还有均方差。后者更多的在关注样本点与平均值的偏离程度。仔细体会一下Jmeter的90% Line性能指标(这只是一个很简单的数学场景,后面有机会和大家分享一篇性能调优中的数学之美的博文)。好了,话题收敛一下,我来解释一下removeAbandonedTimeout的重要性:当connection idle时间超越这个数值时, AbandonedObjectPool会在borrowObject和returnObject时会先进行连接的有效性判断。很好理解,在借出对象时,需要判断该对象是否处于活跃状态(不满足removeAbandoned条件则归还,满足需要看超时时间,然后…);归还时的判断原则大致类同,这个很容易想到。代码如下:
- /**
- * Get a db connection from the pool.
- *
- * If removeAbandoned=true, recovers db connections which
- * have been idle > removeAbandonedTimeout and
- * getNumActive() > getMaxActive() - 3 and
- * getNumIdle() < 2
- *
- * @return Object jdbc Connection
- * @throws Exception if an exception occurs retrieving a
- * connection from the pool
- */
- public Object borrowObject() throws Exception {
- if (config != null
- && config.getRemoveAbandoned()
- && (getNumIdle() < 2)
- && (getNumActive() > getMaxActive() - 3) ) {
- removeAbandoned();
- }
- Object obj = super.borrowObject();
- if (obj instanceof AbandonedTrace) {
- ((AbandonedTrace) obj).setStackTrace();
- }
- if (obj != null && config != null && config.getRemoveAbandoned()) {
- synchronized (trace) {
- trace.add(obj);
- }
- }
- return obj;
- }
- /**
- * Return a db connection to the pool.
- *
- * @param obj db Connection to return
- * @throws Exception if an exception occurs returning the connection
- * to the pool
- */
- public void returnObject(Object obj) throws Exception {
- if (config != null && config.getRemoveAbandoned()) {
- synchronized (trace) {
- boolean foundObject = trace.remove(obj);
- if (!foundObject) {
- return; // This connection has already been invalidated. Stop now.
- }
- }
- }
- super.returnObject(obj);
- }
通过分析,压测,调整参数验证,我们达到了优化目标(主要是基于以上参数的调整)。而后,我们需要认真反思一下:在拿到一款开源软件并成功run起来,进入到production环境前,是不是需要做点啥?每依赖一个新Jar包,就压测一通,是不是很没章法,显得?能不能理论指导实践一下呢?我的回答是当然可以,但需要仔细研读一下关乎性能的相关参数说明。当然,哪些会成为你着重关注的性能参数,这又是一个很经验的事情。再举个例子,之前做过几个Connection调优的事情,问题定位到最后,发现两边的Connection timeout设置的不具备“包容性”。Hmm,具体来说,在Tomcat的AJP connector和apache的mod_jk connector pipe对接时,处于数据流向的AJP connector的timout是不是可以大于等于mod_Jk counterpart呢?试想一下,倘若前者过小,当连接数大于connection_pool_minsize,并且connection_pool_timeout 超时,mod_jk会断开连接。而Tomcat 这边只要到了connectionTimeout超时时间,就会立即放弃连接。这就导致了mod_jk 继续持有连接,而Tomcat这边却放弃了这条连接。后果很严重吧?为了更形象点,我还是把关键配置项摘录下来吧:
workers.properties:
- worker.node1.connection_pool_minsize=25
- worker.node1.connection_pool_timeout=600
server.xml :
- <Connector port="8009" address="${jboss.bind.address}" protocol="AJP/1.3" emptySessionPath="true" enableLookups="false" redirectPort="8443" URIEncoding="UTF-8" backlog="256" maxThreads="250" connectionTimeout="600000"/>
Hmm,既然注意到了这点,我们就可以把Tomcat的connectionTimeout调得比较大,让它完全包容mod_Jk counterpart,又或者把mod_jk的connection_pool_minsize 设成0,再或者在mod_jk中设置worker.node1.prepost_timeout=10000 ,通过断开死连接的方式,都是可以解决这个问题的。写到这,忽然想起之前封装的那个高性能的HttpClient。为什么我敢“吹牛”它是高性能呢?原因很简单,Apache的性能参数之前我们已经进行了调优(通过分析日志统计出连续HTTP请求出现的次数、间隔时间、访问量, 以确定 MaxKeepAliveRequests 和 KeepAliveTimeout 的值。说到这里,我有必要提醒大家注意一下Timeout和KeepAliveTimeout的区别,用两段官方的解释说明一下吧,个人觉得很贴切:
The TimeOut directive currently defines the amount of time Apache will wait for three things:
1. The total amount of time it takes to receive a GET request.
2. The amount of time between receipt of TCP packets on a POST or PUT request.
3. The amount of time between ACKs on transmissions of TCP packets in responses.
The number of seconds Apache will wait for a subsequent request before closing the connection.Once a request has been received, the timeout value specified by the Timeout directive applies.
),那么我封装HttpClient的时候,只需要对接apache的MPM参数(具体可参看:http://blog.csdn.net/fengjia10/article/details/7315279),那么在设计,编码阶段就可以解决大部分性能问题,剩下的就是根据业务场景稍作调优即可。
小结:通过这篇博客,我想说的是,作为职业架构师,我们不仅要读的通源码,玩得起perf tool(分析问题,解决问题),更需要的是将你的优化意识尽可能早的引入到软件的研发周期中,即架构设计,甚至是基础代码的编写过程中。尽可能的运用数学模型去验证你的性能参数选择。请牢牢记住:意识永远比技术更重要。
- 关乎性能的思考
- 关乎性能的思考
- 素质教育关乎你的切身利益吗?
- 关乎DevOps成败的三个火枪手
- SOA带来的性能思考
- 密码学 性能的一些思考
- 关于性能优化的思考
- 系统的思考性能问题
- 关于性能问题的思考
- 系统的思考性能问题
- 性能测试的小思考
- 性能 关于性能优化的思考
- 关于淘宝网性能测试的思考
- 游戏服务器程序的性能思考
- 有关系统性能优化的一点思考
- 高性能网站架构的思考
- javaweb性能优化的系统思考
- 关于ssdb性能方面的一些思考
- DE2上移植uClinux系统
- 关于编码的详细分析
- Ubuntu Unity返回到经典Gnome桌面
- 深入理解Hadoop集群和网络
- URL中包含中文时fileNotFoundException解决1
- 关乎性能的思考
- 编写数据库连接池
- getAttribute和getParameter的区别
- 纯java版QQ源码下载
- u-boot 移植步骤详解
- cocos2d-x中init函数的作用(初始化)
- JDBC-连接池
- 讨论一下:windows mobile与wince
- 修改Qt程序的图标