session锁造成的服务不可用

20180629

问题描述:

批发版出现一个问题,A用户在请求完挂单接口之后,后续所有的接口都请求失败。前端返回的是连接超时,其他用户请求接口正常。nginx的http状态码是499(客户端主动关闭连接)

问题分析:

1、首先查看日志,发现业务的日志没有记录,nginx的日志是有的。说明前端的请求是确确实实打到后台来了。

2、打断点查看调用c++层的日志,发现根本就没有日志。

3、确定问题是发生在php脚本执行这一块。依次排除,发现执行到session_start()这个方法的时候,脚本就不继续往下跑。

4、查阅资料,发现调用session_start()方法时会对当前session文件加锁,防止脏读和脏写。到了这个地方问题差不多就水落石出了。

解决方案:

1、添加超时机制,将超时时间设置成3s。

后续处理:

1、整个跑下来还是没有找出到底是哪个进程阻塞了(20180710找到了),session锁的释放机制是怎么样的。

2、php-fpm是怎么处理脚本的,脚本kill掉之后session锁会不会释放。

3、session锁是怎么来实现的。

4、用memcached或者redis会不会出现这样的问题,应该怎样来处理。

20180706

1、其实查看源代码会发现这个是用c写的,用到了文件锁的概念。也就是说这个是系统级别的锁,锁的状态不是由php引擎来维持,只是由他来改变。所以就能够理解为什么会发生这样的情况了。还有就是php在处理session时候只有session_start()会读取一次session,session_commit()会写入一次session。如果中间业务跑的很久,那肯定会阻塞之后的进程了。

20180710

1、这个地方是因为php使用rabbitmq连接的时候,java端的服务挂了。导致了php脚本一直在监听返回,同时这个监听没有做超时机制,这就导致php脚本超时。此时php脚本停止了,同时调用gc,但是文件锁并没有释放。这时候当前的session锁就无法释放了,那之后对应cookie用户在php就会一直阻塞,所有请求都一直在等待锁的释放。因为客户端请求一直在增加,而服务端的请求还没有到等到脚本超时。这时候服务器的连接会越来越多,最终会拖垮服务器。

20180712

1、了解了下linux下的锁机制,此处的session文件其实是被系统的强制锁锁定的。现在还有一个问题就是为什么php没有去执行释放锁操作。理论上这个地方是php执行超时,然后应该会被zend内核宰掉。目前做了测试,在当前脚本没有跑完的情况下,锁没有释放。就算使用别的编辑器都无法对文件进行修改,但是可以读取。脚本执行完之后锁会释放,可以对文件进行修改了。

猜你喜欢

转载自blog.csdn.net/weixin_38052017/article/details/89874637
今日推荐