session_destroy()比我需要的执行时间早

时间:2018-07-24 20:55:24

标签: php session

所以我有这样的代码:

$_SESSION['message'] = "Some Message";
$MSG = $_SESSION['message'];
header('location: ../Pages/Error.php');
echo "<script type='text/javascript'>alert('$MSG');</script>"; //It has text here
die(); //i set this only for testing purpose
session_destroy();
die();

如您所见,我有2个die()-首先是为了测试。

因此,当代码与首die()echo()一起使用时,使用../Pages/Error.php的{​​{1}}会正常显示该消息,因为在$_SESSION['message']文件和{{1 }}(这也是出于测试目的),但是当我出于某些原因删除这两个文件时,Error.php的运行速度比alert函数快,并且id破坏了我的sesion_destroy();,因此我的header()显示了空消息。

不含测试部分的代码:

$_SESSION['message']

有人可以解释一下为什么会这样吗?

2 个答案:

答案 0 :(得分:2)

之所以会发生这种情况,是因为您的浏览器正在重定向到新页面。之前,此脚本(上面显示的脚本)实际上将会话数据写入存储中。会话数据会一直保留在内存中,直到脚本完成或您手动调用session_write_close()为止。

这意味着要使您的示例正常工作,必须在输出重定向标头之前编写会话数据,如下所示:

$_SESSION['message'] = "Some Message";
$MSG = $_SESSION['message'];
session_write_close();
header('location: ../Pages/Error.php');
echo "<script type='text/javascript'>alert('$MSG');</script>"; //It has text here
die(); //i set this only for testing purpose
session_destroy();
die();

这也意味着您的会话“ 不会被破坏”,这比您最初怀疑的要快。

答案 1 :(得分:1)

这就是发生的情况(例如,时间)。请注意,此ISN不会自动发生什么情况。

1 $_SESSION['message'] = "Some Message";
2 $MSG = $_SESSION['message'];
3 header('location: ../Pages/Error.php');
4 echo "<script type='text/javascript'>alert('$MSG');</script>"; //It has text here
5 You do not have buffering, so header and echo go out to the browser.
6 session_destroy();
8           The browser receives the Location header
7 The server destroys the session file.
9           The browser requests the page
10          The server receives the request
11          The server tries to load the session file. Duh! It's not there!

它可能以其他方式略有不同:

4 echo "<script type='text/javascript'>alert('$MSG');</script>"; //It has text here
5 You have buffering, so nothing gets output.
6 session_destroy();
7 The server destroys the session file.
8 The scripts exits, the buffer is flushed

9           The browser receives the Location header
10           The browser requests the page
11          The server receives the request
12          The server tries to load the session file. Duh! It's not there!

第二个脚本的session_destroy和session_start相互运行时,它可能(在某些系统上)以灾难性的方式运行,从而使第二个脚本读取损坏的会话并阻塞(由于锁定而不会发生) ;但是锁定有其自身的缺点,请参见下文)。

如果您的第一个脚本没有死,而是发出一个Location标头并继续工作,那么可能会发生更有趣的事情。在脚本终止之前,不会存储会话中的数据,因此,如果启动了第二个脚本,它将找到未更新的会话。但是,如果您激活缓冲,则位置将在结尾处发送,第二个脚本将起作用。因此,缓冲显然可以“解决”真正的种族问题。

会话对性能的影响

在那些通过锁定来仲裁对会话文件的读/写访问权限的系统上发生了一件更有趣的事情(这是应该的,因为“竞争条件”是BAD,如上所述),并且您拥有透明的会话,因此对您框架的许多请求-即使是那些不需要保存会话数据的请求,甚至可能甚至不需要读取它们-最终都在另一个后面堆积,因为只要它们被信号量表示,它们就不能并行运行。会话文件FS锁定。

您可以使用Chrome或Firefox Web工具轻松诊断此行为,例如AJAX调用异步开始,但是实际的数据传递已序列化:

-----SXXXXXXXX----------
--------SwwwwwwwwwXXX---
-----SwwwwwXXXXX--------
-------SwwwwwXXXXX------
--------SwwwwwwXXX------
     |<------------>|

在这种情况下,请在session_start()之后立即添加“ session_write_close()”,或者为可能需要读取会话的那些文件尽快(在某些框架的类构造函数中)添加< em>但不要更改,这似乎会神奇地加快您的应用程序的速度(删除所有不需要的session_start()时也会发生这种情况,但是框架可能会使实现起来很复杂):

-----SXXXXXXXX---
--------SwwXXX---
-----SwwXXXXX----
-------SwXXXXX---
--------SwXXX----
     |<----->| "perceived" user time goes down a good 40%