Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4212211
  • 博文数量: 291
  • 博客积分: 8003
  • 博客等级: 大校
  • 技术积分: 4275
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-30 18:28
文章分类

全部博文(291)

文章存档

2017年(1)

2013年(47)

2012年(115)

2011年(121)

2010年(7)

分类: Python/Ruby

2011-07-19 22:54:24

本周周五下午,周六,周日我在家加班忙着重新写我们项目的收集数据程序。

原来的程序是由我属下用C写的,在运行一段时间后出现假死的请求,找来找去没有发现问题。后来决定用perl重写,用perl重写的原因是:

perl的优势是解析字符串,我们的收集程序需要解析通过TCP收到的字符串,提取相关的数据,perl是模式匹配的"带头大哥",另外非常灵活的数组和hash可以很方便处理数据。

perl的优势其实也是劣势,解析功能很强大,同时导致性能没有C的强大,我之前一开始没有用perl而用C的缘故就是,不确定perl写出来的程序是否能够支持每分钟5000次请求。直到我看到perl有支持EV的模块(AnyEvent类似于C的libevent之类的异步IO的高效服务)时,正好遇到C程序出现问题,因此决定用perl重写。

1.周五下午重新开始写代码,解析数据的模块很快写完了,得益于perl的解析功能强大。

2.接下来是安装perl模块,网上说perl5.14.1比perl5.8.8快,倒弄了半天安上perl5.14.1,安装AnyEvent比较顺利。

3.按照网上找的写了个例子,AnyEvent的资料太少了,用ab测试了一下(例子里就一个print),在cpu2G,内存2G的物理机上,rps(request per second)能达到9000多。

下面是悲剧开始,我开始了漫长的解决问题之路

4.由于数据要进入到数据库里,安装DBI,DBD::mysql时总是安装失败,最好搞了几个小时终于安上了,新版的perl的兼容性不好

5.这时已经下班了,之后把入库的代码写完加到AnyEvent里,发现最后测试出的rps为140,我差点哭了,这和目前线上的C程序轻松支持上千rps相比差太多了,测试完,这时已经凌晨2点了,我赶紧回家吧。

6.周六下午,在家没事重新想想性能的问题,

1) 首先把解析的代码重新优化减少不必要的解析,例如因为提取的数据都是在前3行,因此解析时解析完第3行就跳出。

2) 把for循环里的SQL插入改为拼接SQL字符串,最好一次性插入。

3)把程序改为多线程,发现不行,主要是mysql连接不能线程共享,在网上找了资料没有解决办法。

4)改多进程,发现这样系统负载急剧上升。

5) 忽然想起有一种设计模式 分配任务模式,就是前端是接收请求,后端起20个进程,前端收到请求后马上应答并关闭请求(对方其实不需要响应结果,只要送达即可),并把请求转发给后端任意一个工作进程进行处理,然后入库。用这种模式理论上应该达到20*140rps,但是加上数据库瓶颈,估计最好实际运行也能上千rps,这个基本上达到要求。这种方式有点类似云lvs,不同的是我接收请求后马上断掉连接,如下图所示,我的程序数据流是单向流动的

从图上看来,有两个性能瓶颈:LVS,数据库。

Collect_LVS按照上面测试中可以看到AnyEvent最高能够达到9000rps,但是时间测试中转发请求是要消耗时间的,最后测试出的是1614rps,这个效果比较好基本上满足需要。

数据库是耗时大户,要提高效率目前只能用多台数据服务器,但是资源有限只能用一台了。

6.我按照上面的设计把Collect_LVS和Collect_work写完后,在一台虚机(CPU1G,内存1G)测试发现,发了10000条数据,测试结果为1614rps,但是从入库的数据看到的是,发送完毕之后,数据还有一大半没有入库,过1分钟才入库完毕,统计到每一秒,达到了400多rps,效果比刚才测试的要好,在运行平台上应该能够翻倍(因为配置是虚机的4倍)。

7.弄完这个之后,为了让运行程序不能异常退出,和需要检测各个worker是否工作正常,我写了个daemon程序,监控这些进程,若是挂了则马上重启。发现这个工作非常繁琐,花费了周日的一个上午和晚上,还导致我去参加CU的数据库沙龙迟到。

阅读(3942) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~