為了到底訊息及時推送,選擇使用ajax長輪詢,按照網上各種資料講的,在頁面載入的時候就發起一個ajax請求,然後再伺服器端hold住,sleep(1):每隔1秒就查詢一下資料表裡面的計數值是否大於之前的值(初始值為0),如果大於之前的值說明有新訊息就返回計數值提示有多少條資訊,然後發起新的請求。否則當運行超過60秒也返回一條資訊,還是發起新的請求。但是這樣會面臨這樣的問題,如果你在掛起這條請求的同時,又需要發起其他的請求,那麼這些請求就被依次阻塞了,必須要等掛起的請求結束才可以進行被阻塞的請求,這樣顯然不是我想要的結果。我也看了webqq,它好像是採用了iframe但是我真心的不知道到底改怎麼用iframe解決請求的阻塞的問題,請大家不吝賜教。若能避免使用“推拉模式”、“反向ajax”之類的大概念則更好。
回複內容:
阻塞的問題我遇到過,通過排查和查閱資料得到原因如下:
原因:為了安全考慮(避免單個使用者並發請求導致的session資料錯亂),PHP採用排它鎖來互斥的訪問session資料(不管你是用session檔案還是memcache存session),也就是說開啟了session後,單個使用者只能串列的訪問這個網站,並發的請求只有一個會被立刻響應,其它都會被阻塞。
解決辦法:
- 不用session
- [推薦]及時用session_write_close() 函數儲存session(此函數會釋放session資料的排它鎖)
- [不推薦]自己類比session。不調用session_start(此函數會鎖住session資料)通過cookie獲得session_id,然後擷取session資料。通過session_decode/encode編解碼session資料儲存等
再說一下樓主的即時推送需求,這個我也做過:
不要用ajax,因為比較耗費伺服器資源,即時性也得不到很好的保證。
我用的是WebSocket(HTML5/Flash)+PHP Socket 伺服器(workerman 一個高效能的PHP Socket 伺服器架構
)
這個方案即時性高,並且消耗資源非常低,多瀏覽器支援。
DEMO:
發送訊息的後台頁面:Web訊息推送器
即時接收訊息的頁面:Web訊息接受頁面
代碼地址:walkor/web-msg-sender · GitHub
還有個PHP+WebSocket聊天室也是類似的原理:workerman-chat
安裝使用就兩步(workerman不依賴apache、nginx、php-fpm等容器就可以直接運行。
不支援Win):
1、下載代碼
2、運行./bin/workermand start
一切ok
發訊息後台:http://ip:3333
接受訊息頁面:http://ip:3333/web-msg-sender.html會有人願意在各種"不行","不要",近乎被侮辱的情況下幫你解決這麼具體的技術問題嗎?這個是由於session被佔用導致的,讓長輪循不再操作session。用session_write_close()的函數可以解決你的問題。為何不用comet如何解決,我將php邏輯代碼全部去除了,只在介面的for迴圈十次裡sleep(1),但還是存在ajax等待迴圈ajax執行完成在執行
答案:session_write_close好像是ajax請求同一個網域名稱,一次限制只能發送2個請求,用iframe可以跨子域發請求,突破這個限制,具體可以參考 http://blog.zhaojie.me/2007/02/break-the-browsers-restrictions-6.html
謝謝,我是一名前端,php懂得少,剛好遇到這個問題,感謝大牛~~~~