每个会话不能有多个线程

Posted

技术标签:

【中文标题】每个会话不能有多个线程【英文标题】:Can't have several threads per session 【发布时间】:2012-08-14 00:04:38 【问题描述】:

我正在构建一些 webapp 并实现了长轮询(以及我的数据库中的命令队列),因此我的服务器可以异步向我的客户端发送命令等。命令被编码为 json 并通过 ajax 调用发送给客户端到服务器,并通过服务器到客户端的长轮询方式。

一切正常,直到我在 ajax.php 文件中包含我的“身份验证模块”。该模块包装了会话内容并调用 session_start()。

问题是,我的长轮询例程最多可以等待 21 秒,然后再返回客户端。在此期间,服务器不会从同一会话运行任何内容。而是在长轮询 ajax 调用返回后立即执行。

我了解每个会话一次只能有 1 个线程的限制,并且请求已排队。

现在的问题是:解决这个问题的最佳方法是什么?是否有一个设置允许每个会话有多个线程(在我的情况下,3 个就可以了)。或者我应该只是发送告诉客户他的 SessionID 是什么(我的数据库中有一些会话表,以跟踪哪个用户连接到哪个会话)。然后客户端可以将它与任何 ajax 调用一起发送,这样就可以绕过身份验证模块。

在后面的选项中,我担心它会因为最终的会话欺骗而引发一系列安全问题。我需要向每个会话发送一个“随机字符串”,以确保你不能轻易欺骗,但即便如此,它也不完美......

感谢您的遮阳篷 :)

尼古拉斯·高蒂尔

【问题讨论】:

只是一个想法。会话文件可能被锁定,并且单独的“线程”无法访问它们。您是否尝试过在不需要时明确关闭会话?我看到你说你有一个将会话 ID 与会话相关联的表,整个会话都在表中吗? (如果是这样,请忽略我的文件锁定理论) 没有使用该表,因此我可以向“给定用户的所有会话”等发送消息。我在会话变量中并没有真正存储太多,只是 userId、sessionID(我的数据库中的那些)以及它是否有效。我想看看我可以用“session_write_close”做什么,正如你提到的“在不需要时显式关闭会话。 哇,改变“睡眠($counter);”通过“session_write_close();睡眠($counter);session_start();”解决了问题!似乎它阻止了“会话文件资源”......你天才哈哈,发布一个问题并选择作为 awnser! 【参考方案1】:

众所周知的问题/事实是 PHP 在会话文件的使用期间锁定会话文件以防止出现竞争条件。

如果您查看 PHP 源代码 (ext/session/mod_files.c),您可以看到 ps_files_open 函数锁定会话文件,而 ps_files_close 将其解锁。

如果您在长时间运行的脚本开始时调用session_start(),并且没有显式关闭会话文件,它将被锁定直到脚本终止,PHP 将在脚本关闭期间释放所有文件锁定。

当您不使用会话时,您应该调用session_write_close 将会话数据刷新到磁盘,并释放锁定以便您的其他“线程”可以读取数据。

我相信你可以想象如果文件没有被锁定会发生什么。

T1: Open Session
T2: Open Session
...
T2: Write Data
T1: Write Data

线程 2 写入的数据将被线程 1 完全覆盖,同时线程 1 想要写出的任何数据对线程 2 都不可用。

【讨论】:

会话文件只有在需要写入时才会被阻止?

以上是关于每个会话不能有多个线程的主要内容,如果未能解决你的问题,请参考以下文章

从 CSV 文件加载数据以进行负载测试并为每个用户保持会话

C - SIGINT处理程序不能与多线程一起工作,每个线程都有一个popen进程。

多线程

lib 魔法线程安全吗?

虚拟机的那个线程是不是需要每个线程有多个实例?

线程有有序性和可见性