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內核宰掉。目前做了測試,在當前腳本沒有跑完的情況下,鎖沒有釋放。就算使用別的編輯器都無法對文件進行修改,但是可以讀取。腳本執行完之後鎖會釋放,可以對文件進行修改了。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章