ajax 異步長連接遭遇堵塞,“排序執行請求”的問題解決


今天開發一個網頁聊天程序,利用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

從里面得到一個函數

 

session_write_close();

 

結合了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.

 

本文為作者原創:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM