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()。