1、Session locking: Non-blocking read-only sessions in PHPphp
當時網上看的一篇文章html
https://www.leaseweb.com/labs/2014/08/session-locking-non-blocking-read-sessions-php/?utm_source=leaseweblabs.com&utm_medium=referral&utm_campaign=redirectweb
中文譯文大體以下:ajax
什麼是session鎖?
爲了明白這點,咱們首先要知道web server不是經過一個單線程運行你的php代碼,他是多個工做線程同時運行,而後處理請求。
通常,瀏覽網頁的用戶請求是被序列化的,這也是爲何http長鏈接起到的做用。經過保持給請求頁面的全部資源鏈接的打開,能夠避免鏈接的開銷。
瀏覽器很是聰明,而且老是試圖對HTML頁面的請求進行序列化。對於頁面上的資產(圖像、腳本等),還有另外一種策略。
瀏覽器會從它所看到的HTML中所引用的每一個惟一的主機名中並行下載多個資源。
它能夠經過打開多個TCP鏈接或管道來實現這一點。
當一個瀏覽器任務它正在下載資源,它可能並行的下載這些資源給一個單一的瀏覽用戶。
會話鎖定避免這種併發性(經過阻塞)在這種狀況下提供對會話數據的可靠訪問。json
session鎖如何工做
這個很是簡單:當你使用‘session_start()’,php就是阻塞(等待)直到上一個請求的腳本經過‘session_write_close()’進行釋放。在Linux主機上,它是依靠‘flock()’方法實現。這是一個警告鎖機制,直到這個阻塞被釋放。
注意:這部分上鎖的時間不會計算在php中的「max_execution_time」配置項,「max_execution_time」詳見set_time_limit()
爲何session鎖是必須的瀏覽器
session鎖防止在用以存儲session數據的共享內存出現競爭條件。每個PHP進程都會讀取整個session的儲存,並寫回數據在它關閉以前。
這意味要可靠地儲存一個登陸進來的用戶信息(一般在會話數據session中完成),你必須確保沒有其餘進程已經讀取這個session數據,否則將在寫入後覆蓋掉你保存的數據(由於最後一次寫入數據爲準)
sesion的只讀
許多網站使用AJAX調用來加載數據。在檢索這些數據時,咱們想知道用戶是否在須要時登陸來拒絕訪問。此外,咱們不但願將此AJAX數據加載到會話鎖定中,這將減慢網站的速度。這就是下面(多是髒)代碼的地方。它將容許您得到對會話數據的只讀訪問(調用它而不是「sessionstart()」)。經過這種方式,您能夠在AJAX調用中檢查權限,但不須要鎖定,所以不會阻塞和序列化請求。它能夠顯著提升你的PHP AJAX網站的速度!bash
function session_readonly() { $session_name = preg_replace('/[^\da-z]/i', '', $_COOKIE[session_name()]); $session_data = file_get_contents(session_save_path().'/sess_'.$session_name); $return_data = array(); $offset = 0; while ($offset < strlen($session_data)) { if (!strstr(substr($session_data, $offset), "|")) break; $pos = strpos($session_data, "|", $offset); $num = $pos - $offset; $varname = substr($session_data, $offset, $num); $offset += $num + 1; $data = unserialize(substr($session_data, $offset)); $return_data[$varname] = $data; $offset += strlen(serialize($data)); } $_SESSION = $return_data; }
2、測試模擬session
1.首先,咱們打開php-fpm的慢日誌記錄併發
request_slowlog_timeout = 4s slowlog = /var/log/slow.log
2.而後,首先纔是默認狀況下,寫入數據後沒session_write_close();的狀況函數
test_sessom.php
<?php /** * Created by PhpStorm. * User: tjj * Date: 17-6-23 * Time: 下午4:01 */ session_start(); $_SESSION['latestRequestTime'] = time(); //session_write_close(); sleep(1); $twitterId = $_SESSION['latestRequestTime']; echo json_encode($twitterId);
test.html
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <img src="./test_session.php?v=1"> <img src="./test_session.php?v=2"> <img src="./test_session.php?v=3"> <img src="./test_session.php?v=4"> <img src="./test_session.php?v=5"> <img src="./test_session.php?v=6"> <img src="./test_session.php?v=7"> <img src="./test_session.php?v=8"> <img src="./test_session.php?v=9"> <img src="./test_session.php?v=10"> <img src="./test_session.php?v=11"> <img src="./test_session.php?v=12"> <img src="./test_session.php?v=13"> <img src="./test_session.php?v=14"> <img src="./test_session.php?v=15"> </body> </html>
訪問test.html的結果:
能夠看出每個請求的時間幾乎都是疊加前面的等待時間,因爲都要等待前面的請求完成釋放。
而後看看php的慢日誌記錄狀況,能夠看到超過4s的都記錄了,並且報的是session_start()這個函數的問題。
再看看 test_session.php中session_write_close()註釋打開後的請求狀況。
明顯沒有形成阻塞,請求響應時間基本正常。
總結:涉及到的ajax接口不須要用session的就不session_start(),不須要寫入session的就在session_start()後直接加入session_write_close(),須要寫入session的,寫入session後加入session_write_close()。