Bug:界面有时无法登陆或者根本不出登录界面
简单分析过程
现象1:数据库死锁
处理:reindex进程造成数据库死锁,reindex这个进程9点多的版本的postgresql上没有必要,因为高版本的postgresql有自动reindex的过程,所以直接去掉了。
现象2:大量端口被占用,大量close_wait状态引擎
问题分析:本以为这个问题解决了,提交了升级包之后,测试组用了两天之后就又出现这种无法登陆的情况了,这个时候使用netstat -anp发现大量端口被占用,很多的close_wait状态和time_wait状态,最多的时候能达到1万条,并且很多的进程的发送队列和接收队列都不是0,有时候达到上千,这不正常,close_wait状态的进程也是不正常的,这种状态下的进程得持续两个小时。杀了该进程,便能够登录上去,以为是可用端口被占满,导致无法建立新的端口。
处理:于是查服务引擎的代码,修改tcp方式为本地套接字方式,这样端口被占满的情况不再出现,但还是有close_wait状态的进程,于是修改apache的配置文件,将keep-alive开关置为关,这样默认就是服务引擎主动关闭,close_wait进程不再存在。
现象3:同一ip同一时刻大量请求
问题分析:本以为解决了,又提交了升级包,测试用了两天又出现部分人登录不上去,部分人能登录的情况,查看访问日志access_log,看到同一个ip一秒钟发了十多次请求,并且这个请求一直持续,用firedebug观察,每次请求的阻塞时间都会达到执行的时间一半甚至一半以上。
处理:后来发现index.html页面的js代码有两个函数使用setInterval函数,分别是获取系统状态和获取系统正在扫描的任务数,并且分别是每隔10s和30s发送请求,后来发现setInterval函数会不停的发送,并且当时间执行比较长的时候没有被执行的话就会不停的被累加,这很符合用了两天无法使用的情况,于是修改了该函数为settimeout,每次执行完才会有下一次请求,并且修改index.html为鼠标离开就不发送请求方式,并且加大了apache的并发控制数。
此刻的心情:本以为解决了,打了升级包给测试,用了两天又出现了,差不多要崩溃了,是时候分离问题了,分析到这个时候差不多已经用了两周多,基本上每天都加班外带周六加班,问题还是这么继续着,这个时候就动员全员来拼这个问题,把问题分析过程都发了出去。
会议:得到了一个初步结论:
1,拿工具测试性能瓶颈
2,manage方式看看有没有问题
3,登录出问题后将数据访问和apache分离开来,登陆去除数据库访问
4,升级脚本db.sql优化
5,import后台代码,调用失败,wsgi_mod起来的线程之后的线程有限制。
6,先做个包,apache日志,postgresql日志开关打开,优化的都提交。牛犇负责postgresql日志打开
做了个包之后,将apache和数据库的日志级别都调到了debug级别,不停刷新页面
简单分析过程:分析了这种情况下的问题:
1,apache日志,
apache在出现一个ipv6cal命令的异常前后,数据库出现unexpectedeof on client connection的错误,这个错误是导致数据库出现idle的原因,但是不确定一定是ipv6cal这个命令引起的,因为这个数据库错误在其他时间段也出现过,目前ipv6cal这个错误目前已经找到原因,另外django也加了中间件trasaction来控制事务的提交和回滚。
2,数据库日志:
分析数据库的日志,发现begin次数比rollback和commit的总数多八个(排除掉日志的开头和结尾),这个日志里有13个 unexpect eof on client connection。数据库出现闲置进程,出现挺多idle状态的进程,查看数据库的锁表,有挺多锁,目前发现至少有三个ExclusiveLock锁(只允许查询),能 正常登录的时候有一个Exclusive锁,其他的锁模式则是AccessShareLock,这些锁状态都不影响查询。
3,ab工具分析
用apache的ab工具测试1700设备,ab –c 100 –n 1000 平均每秒能接受请求200,这还比较正常,当登录不上的时候,每秒请求数只能到20,并-n参数还是100。这就很不正常了,但是io,cpu,内存,进程数,端口都很正常。数据库会有一些闲置连接。
解决问题:
1,首先解决ipv6cal的一个错误
2,引入django的transaction中间件来控制事务的提交和回滚,当出现异常的时候回退,这样就避免出现idle的数据库进程。另外得注意把将SessionMiddleware置于commonmiddleware前面,防止wsgi报没有session属性的问题。
3,搜索web和后台的访问数据库的代码,给所有的新建数据库连接,关闭等都加上try,except控制。
综合这些问题又打了一次包,还是有这个问题存在,很绝望。这是后续的处理过程:
1,使用manage.py单独测试,没有问题,代码和数据库访问应该没问题,后来推翻了,因为没有经过几天的测试。
2,使用openssl 的s_client工具测试apache的配置,使用openssls_client -connect 能得到回应,那么apache的配置没有问题。
3,一步步跟踪代码,发现在登录前获取升级包的函数出问题了,而且是在libxml2.parseFile函数,查看apache日志,啥错误也没有。再联想到libxml2有时候会遇到的段错误,就怀疑是django框架没有捕获段错误。修改libxml2为ElementTree,然后再做一个包,跟踪了几天再没有出现无法登陆的问题。
总结:像这么大的问题,一定要及时分离,分离数据库,apache,wsgi,代码,特别是没有思路的时候。比如说用openssls_client 判断apache 的ssl响应无问题。在代码中去除数据库的访问,使用manage.py判断代码是否有问题。
阅读(1821) | 评论(0) | 转发(0) |