这几天公司网站每当业务高峰的时候,就出现如下状况:
1)web服务器CPU负载30~50%左右。(状况正常)
2)Mysql数据库负载正常。
3)连接Redis的Jedis 2.5.2 + common.pool2,一直报can not get a resource。
Jedis Pool的配置是:
timeout=2000
max_total=30
max_idle=5
max_wait=3000
查看redis的监控软件发现redis连接数居然是max_total的3,4倍。
原因分析,及解决方法
1)怀疑,使用jedis的代码没有把获得的资源还回到pool中。但查代码后,确保生产环境程序,在代码层面都将资源还回到pool中了。
问题依旧。
2)既然都还回pool了,就怀疑是不是2周前将jedis从2.0升级到2.5.2。新的jedis-2.5.2,放弃了原先的common.pool,而使用了common.pool2。
由于,近期未更改过代码,仅是jedis升级。所以决定将部署版本还原到jedis-2.0版本。
问题依旧。
3)再次检查代码,
按照,减少jedis从pool中获取次数,且即使还回pool中的原则。将下述类似的代码:
for (int i = 0; i < 100; i++) {
Jedis jedis = null;
try {
jedis = getJedisFromPool();
String str = jedis.hget("key");
} catch (TimeoutException e) {
throw e;
}
finally{
if(jedis!=null){
// set jedis back to pool
releaseJedisInstance(jedis);
}
}
}
修改为:
String[] keyArr = new String[100]
for (int i = 0; i < 100; i++) {
keyArr[i] = "key" + i;
}
Jedis jedis = null;
try {
jedis = getJedisFromPool();
List<String> result = jedis.hmget(keyArr);
} catch (TimeoutException e) {
throw e;
}
finally{
if(jedis!=null){
// set jedis back to pool
releaseJedisInstance(jedis);
}
}
当天部署后,顺利通过当天第二个业务高峰。
第二天,凌晨0点----6点,Mysql服务器因为负载过高,导致网站瘫痪。
分析及解决方式:
1)分析:查看Mysql的log,发现有个业务,是200多万条数据的A表与200多万条数据的B表,进行了大量的,频繁的left join查询。从而导致大量的慢查询。
解决方式:
a)在B表中冗余字段,建立必要索引。
b)评审代码,优化sql。
2)分析:凌晨,网站开始进行大量后台统计。统计的时候会进行大量的高负载操作。
解决方式:
a)统计在生产库以外的备份出的库上进行。统计数据的查询及使用,也连接备份出的库。
b)去除不必要的统计功能。
3)分析:分析Nginx日志,发现有恶意刷某一页面或功能的请求。
解决方式:
a)增强该部分的代码。
b)在iptable上设置,例如:1分钟内请求大于300次,就屏蔽此IP。
4) 分析:各大搜索引擎,凌晨开始爬虫工作。我们公司网站的历史数据都是未做静态化处理的。
解决方式:历史数据,进行静态化处理。优势,
a)避免不必要的库查询。
b)搜索爬虫,对静态页面的支持更佳,从而提高SEO的效果。
c)静态页面可使用Varnish等,进行缓存操作。
当天夜里,至次日,数据库至此,解决数据库负载过高的情况。
但是,到目前位置,并未完美的且根本解决问题。因为,如果业务高峰再大一些,现有架构的程序依然不能支撑。
描绘一下出问题时的架构:(只画出Redis部分)
放弃pool连接,改用短连接后的,新的架构:(只画出Redis部分)
实现,redis的读写分离,redis主从结构。
在新架构上使用压力测试工具,进行压力测试:
1000并发,1000次请求
1)Web服务器,CPU稳定在150%。
2)Mysql无压力。
3)Redis无压力。
4)Web服务器,Mysql,Redis各个服务器的IO输出正常。
至此问题解决。
总结:
1)代码一定要优化,针对数据库,Redis这样的资源,一定要本着节约的原则。
2)pool 和 短连接比较。
|
Pool连接 |
短连接 |
扩展性 |
不容易水平扩展 |
容易水平扩展 |
稳定性 |
弱,不易实现负载均衡 |
强,,易实现负载均衡 |
读写分离 |
不容易实现 |
容易实现 |
3)压力测试尽量多做
介绍一个压力测试工具。
siege -c 1000 -r 1000 http://www.baidu.com
当然Apache自带的 ab 工具,WebBench,apache-jmete都是不错的工具。