阻塞会话存储
Posted
技术标签:
【中文标题】阻塞会话存储【英文标题】:Blocking Session Storage 【发布时间】:2016-03-24 18:45:17 【问题描述】:我们使用 Guzzle HTTP 来发出 HTTP(s) 请求以生成 CSV 文件;我们使用的另一个组件是$_SESSION
变量,用于存储有关不同文件生成的状态信息。
这种方法的主要问题是 php 会阻止所有其他使用 $_SESSION
变量的请求。我们知道我们可以用一个叫做session_write_close()
的函数来解决这个“问题”;
但是我们仍然需要能够更新信息并将其存储在稍后的$_SESSION
变量中,并且我们还应该能够在站点的其他部分中使用$_SESSION
信息;因此它应该是“同步的”。
【问题讨论】:
您可以稍后在脚本中再次启动会话,写入它,然后再次关闭它。这将大大减少阻塞。 【参考方案1】:PHP 会话的实现假设会话数据是:
-
从后备存储中完整加载。
可能在脚本执行期间被修改。
完整地写入其后备存储。
因此,例如,假设您实现了一个未实现锁定的会话处理程序,并且发生了以下事件序列。
-
请求 A 从后备存储加载会话数据。
请求 B 从后备存储加载会话数据。
请求 A 修改 $_SESSION['foo']
请求 B 正忙于做事...
请求 A 完成并将会话写入后备存储。
请求 B 完成并将会话写入后备存储,从而消除 A 所做的更改。
这就是为什么 PHP 的默认会话处理程序以及任何其他值得一提的会话处理程序在给定请求期间锁定每个会话的原因。
鉴于您需要在长时间运行的请求结束时写入数据,并且还有多个并行运行,您可能根本不应该对这些数据使用会话,我建议使用数据库和 交易。
【讨论】:
这可能是我们问题的最佳解决方案,唯一的问题是我们不应该使用任何数据库。因此,我们将重新评估我们的选择。目前,我们每次需要时都会关闭并重新打开我们的 $_SESSION“连接”,但这很不稳定。【参考方案2】:遗憾的是,session_write_close
正是您需要使用的,以确保请求不会被阻塞。我的建议是在开始生成 CSV 之前,在脚本开始时获取并设置所需的所有会话信息。然后致电session_write_close
并继续创建您的 CSV 文件。
【讨论】:
这种方法的问题是我们需要稍后在脚本中更新 CSV 生成的状态。 如果您需要在会话数据中更新它,那么可以。您必须决定这两种后果中的哪一种危害较小。【参考方案3】:您的问题是您的请求比典型请求花费的时间要长得多。原因是从您的脚本执行 HTTP 请求需要时间。这会导致您最初出现阻塞会话文件的问题。
我可以看到您的问题的两种解决方案:
将与发出请求相关的逻辑卸载到不同的进程中,该进程会传递所有需要的信息,而无需实际会话使用(工作人员)。这可以通过使用队列甚至是简单的 cron 脚本来实现,该脚本可以从一些共享存储(如 DB)中窥探它需要执行的操作。
放弃使用会话或至少放弃使用阻塞存储会话。好的替代方案可能是:包含所需信息的简单数据库表、memcached 或 Redis 等键值存储。
【讨论】:
以上是关于阻塞会话存储的主要内容,如果未能解决你的问题,请参考以下文章