今天开发一个网页聊天程序,利用AJAX保持着一个长连接监听新的聊天信息,之后又调用了另外一个AJAX来发言,于是就发生了一个AJAX线程被阻塞的问题。
在未监听到新的聊天信息的之前,发言用的AJAX就无法发出。
问题描述:
上图中
第一个链接是长连接(监听新聊天信息使用的)AJAX连接,每次连接时间为30秒;
第二个链接是发言用的AJAX连接,请求后实时返回结果。
遇到的问题就是第一个链接发出后,在第一个链接没有执行完毕(也就是没有返回结果前),这段时间内如果执行第二个链接,需要排队,等第一个执行完,才会执行。
这里就郁闷了,以为是JS的原因:“JS是不是AJAX只能单线程发送?”
因为上述问题,以及推测的答案,百度、谷歌了一下午,看了好多技术文章,直接崩溃,无法解决。
难道要使用“轮询”方式解决这个问题?但是这样会造成很多网络资源浪费,因为3秒定时请求一次,然后打开多个网页的情况下,基本就是几百毫秒就请求一次了。
什么是“轮询”?
就是使用JS定时循环执行函数,每隔几秒向服务器请求一次,看有没有新消息,如果有就获取过来。
解决方法:
晚上吃完饭,回来继续百度
一、百度搜索:“异步长连接遇阻塞”,发现一篇文章《异步长连接遇阻塞,探索,以及解决 》:http://blog.csdn.net/guoerwei/article/details/6535389
看完此文后得出一些线索:
问题不是出在JS上,问题在于PHP程序上! 因为session的出现,导致了无法正常工作。直接将session先删掉,发现长连接已经不堵塞了。
原因是长连接死循环的时候,session文件被一直打开着,处于被锁定的状态,这时来发送消息,会因为session而阻塞……
二、至此,问题解决,那么上面我们的解决办法是,直接删掉session,但是项目做到现在,已经有很多的session了,删掉测试下,肯定的没问题,但是想要直接不使用session,还是有点麻烦,那么是否可以在不删除session的情况下解决这个问题呢?
接着百度搜索“php如何解决session封闭问题”,发现一篇文章《PHP中Session引起的脚本阻塞问题解决办法》http://www.jb51.net/article/48805.htm
从里面得到一个函数
结合了PHP的Session机制,找到了阻塞的原因。由于PHP的Session信息是写入文件的,1个客户端占有1个session文件。因此,当 session_start被调用的时候,该文件是被锁住的,而且是以读写模式锁住的(因为程序中可能要修改session的值),这样,第2次调用 session_start的时候就被阻塞了。
查了下PHP的Bug列表,发现有人提出了这个问题:
Description:
------------
Calling session_start() appears to wait until other scripts have exited
that are using the same session. My guess is the 1st request locks the
session file for exclusive use, and the second request blocks until it
can open it.
PHP官方的回复是:
Thank you for taking the time to write to us, but this is not a bug.This is expected, the session file is locked to avoid corruption.
本文为作者原创: |