你Php的session_start慢麼
事情發生在一個晴朗的早上,客戶投訴說公司運營的一個web電商系統出現偶發的504問題。“偶發”這種事兒,真心不好排查啊。
我們檢查了一遍所有的相關配置,包括nginx,php,php-fpm,mysql等等等等,調整了一些引數後情況並沒有變好~~
不僅如此,還有相當多的其它因素干擾著問題的排查,這其中就包含今天的這個主題。
實在沒轍了,只能開啟所有的log來追查了。
經過對日誌的分析,發現“偶發”的504都會伴隨著幾次php的slow log記錄,其中包含了兩個比較惹人注目的函式呼叫:curl和session_start。
前者很好理解,肯定是curl的目標地址出現了響應問題,經過確認也證實瞭如此,原來是之前依賴的一個第三方介面停止服務了。
而之所以“偶爾”,是因為這個服務有時候響應null,有時候直接阻塞到超時。。。
這不是今天的重點,我們來看session_start慢的問題。在使用者瀏覽器上表現的行為是,當出現了某個頁面504,接下來的一個時間段內,
該瀏覽器訪問同一個二級域名下的所有頁面都會返回504,但立即切換瀏覽器或更換二級域名即可立即正常訪問。
同事提出一種看法:所有的同一個會話的請求都會最終交給同一個php-fpm的worker程序來處理,所以會出現這種現象。
這和我的認知有點不同,畢竟要想實現session粘度處理,一般往往是要在整個請求鏈路的各個節點都要做設定的,
不可能預設就提供這樣的“高階功能”才對。可問題表現出來的情況恰恰又和同事的看法吻合,一時間很苦惱。
那就按照這個觀點,我們調整了php-fpm的一個引數:request_terminate_timeout。
將它開啟並設定一個較短的等待時間,確實發現上面提到的那個瀏覽器的504等待時間縮短了,
這彷彿又一次驗證了同事的觀點。
一直到排查的尾聲,我也一直沒有特別接受這個觀點,直到我們看到了session_start的慢日誌。
第一感覺是,一個內建函式怎麼可能會慢呢?GG了一下,發現大量的相關文章,原來是檔案鎖導致的。
簡單的說,php預設的session機制是靠檔案,瀏覽器攜帶的cookie中指明的session_id到服務端後,
假如一個請求開啟session後卡住了,後面的同一個會話的請求就會在
session_start呼叫上等待
,直到第一個請求釋放檔案鎖。對應我們的問題場景就是處理第一個請求的worker程序被kill。這對這種問題,大家給出的方案是,依靠php提供的session handler機制把session儲存在memcache或db裡。
或者使用session_write_close()
方法來釋放寫鎖,在session_start後直接呼叫該方法,可以化解鎖衝突,
而且你依然可以繼續讀取session中的值,只是無法編輯,若想編輯,再次呼叫@session_start()
函式即可。
長遠來看,還是推薦大家講session儲存在獨立的節點上,方便日後的叢集擴充套件。
今天的分享就到這裡~