每个会话不能有多个线程。

3
我正在构建一些Web应用程序,并实现了长轮询(以及我的数据库中的命令队列),以便我的服务器可以异步地向客户端发送命令,等等。这些命令被编码为JSON并通过Ajax调用从客户端到服务器发送,通过长轮询从服务器到客户端发送。
一切都很顺利,直到我在ajax.php文件中包含了我的“身份验证模块”。该模块包装了会话内容并调用session_start()。
问题是,我的长轮询例程可能需要等待长达21秒才能返回给客户端。在此期间,服务器不会从同一会话中运行任何内容。相反,它将在长轮询Ajax调用返回后立即执行。
我理解每个会话最多只能有1个线程,并且请求会排队等待。
现在问题来了:如何解决这个问题?是否有设置允许每个会话有几个线程(在我的情况下3个就可以了)?或者我应该告诉客户端他的SessionID是什么(我在我的数据库中有一些会话表,用于跟踪哪个用户连接到哪个会话)。然后客户端可以将其与任何ajax调用一起发送,以便绕过身份验证模块。
对于后面的选项,我担心由于可能的会话欺骗而打开了一堆安全问题。我需要向每个会话发送一个“随机字符串”,以确保您无法轻松欺骗,但即使这样,它也不是完美的...
谢谢您的回答 :)
尼古拉斯·高蒂埃

只是一个想法。可能会出现会话文件被锁定,而单独的“线程”无法访问它们的情况。当不需要时,您是否尝试显式关闭会话?我看到您说有一个将会话ID与会话相关联的表,整个会话都在表中吗?(如果是这样,请忽略我的文件锁定理论) - Leigh
没有使用表格,我可以向“给定用户的所有会话”发送消息等。我实际上并没有在会话变量中存储太多内容,只有userId、sessionID(来自我的数据库)以及它是否有效。我正在尝试了解如何使用“session_write_close”,正如您提到的,“在不需要时显式关闭会话”。 - NGauthier
哇,将“sleep($counter);”更改为“session_write_close(); sleep($counter); session_start();”解决了问题!看起来是在“会话文件资源”上阻塞了...你真是个天才哈哈,发一个问题,我会选择它作为答案! - NGauthier
1个回答

4

众所周知,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都不可用。


只有在需要写入会话文件时才可能被阻止吗? - Jose Nobile

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接