记录一次公司网站调优过程

这几天公司网站每当业务高峰的时候,就出现如下状况:

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都是不错的工具。



你可能感兴趣的:(调优)