php中 session start,PHP函数session_start()中的session锁

一、Session locking: Non-blocking read-only sessions in PHP

当时网上看的一篇文章

https://www.leaseweb.com/labs/2014/08/session-locking-non-blocking-read-sessions-php/?utm_source=leaseweblabs.com&utm_medium=referral&utm_campaign=redirect

中文译文大致如下:

什么是session锁?

为了明白这点,我们首先要知道web server不是通过一个单线程运行你的php代码,他是多个工作线程同时运行,然后处理请求。

一般,浏览网页的用户请求是被序列化的,这也是为什么http长连接起到的作用。通过保持給请求页面的所有资源连接的打开,可以避免连接的开销。

浏览器非常聪明,并且总是试图对HTML页面的请求进行序列化。对于页面上的资产(图像、脚本等),还有另一种策略。

浏览器会从它所看到的HTML中所引用的每个唯一的主机名中并行下载多个资源。

它可以通过打开多个TCP连接或管道来实现这一点。

当一个浏览器任务它正在下载资源,它可能并行的下载这些资源给一个单一的浏览用户。

会话锁定避免这种并发性(通过阻塞)在这种情况下提供对会话数据的可靠访问。

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网站的速度!

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;

}

二、测试模拟

1.首先,我们打开php-fpm的慢日志记录

request_slowlog_timeout = 4s

slowlog = /var/log/slow.log

2.然后,首先才是默认情况下,写入数据后没session_write_close();的情况

test_sessom.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

test_session.php?v=1

test_session.php?v=2

test_session.php?v=3

test_session.php?v=4

test_session.php?v=5

test_session.php?v=6

test_session.php?v=7

test_session.php?v=8

test_session.php?v=9

test_session.php?v=10

test_session.php?v=11

test_session.php?v=12

test_session.php?v=13

test_session.php?v=14

test_session.php?v=15

访问test.html的结果:

4bfa2bfeb2f3f05a265fbe2f17f4f6b0.png

可以看出每一个请求的时间几乎都是叠加前面的等待时间,由于都要等待前面的请求完成释放。

然后看看php的慢日志记录情况,可以看到超过4s的都记录了,而且报的是session_start()这个函数的问题。

3f60f35574c1c9df98053ed33fa43dca.png

再看看 test_session.php中session_write_close()注释打开后的请求情况。

e8b613e40163b20f9d7558f66fc1617c.png

明显没有造成阻塞,请求响应时间基本正常。

总结:涉及到的ajax接口不需要用session的就不session_start(),不需要写入session的就在session_start()后直接加入session_write_close(),需要写入session的,写入session后加入session_write_close()。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值