PHP中的随机会话数据丢失

时间:2014-09-03 11:21:52

标签: php session session-variables

以上是我们过去几周所遇到的问题。

1 /我们的设置

  • PHP 5.4 + MySQL
  • 2个专用服务器,负载均衡
  • 使用memcached
  • 在两台服务器之间复制会话
  • 在这些服务器上运行的3个应用程序:
    • 一个使用默认php会话设置的自定义开发应用程序
    • 另一个自定义开发的应用程序,使用不同的会话设置(cookie名称,路径)
    • 一个Wordpress CMS

2 /问题

问题出现在我们的第一个应用程序上。

我们的一些用户报告说他们有时会在几分钟后断开连接(当会话设置为持续3小时时)。它可能会在同一天发生几次,然后几天没有断开,但问题总是会回来。 到目前为止受影响的用户比例很小,但我希望在它“传播”给其他用户之前解决这个问题。

问题似乎发生在应用程序的不同位置,尽管我们已经确定了大多数错误发生的3个scenarii:

  • 有些涉及提交表单($ _SESSION变量已修改)
  • 其他只需要打开一个弹出页面,而不修改会话数据

我们试图重现用户描述的不同场景:有时我们已经能够,但大多数时候我们没有任何问题,这使得调试变得困难。

其他说明:

  • 问题是最近的,这个应用程序已运行多年没有任何问题。
  • 这似乎与我们的服务器负载没有关系,因为在夏季休息期间,当我们的交通流量很低时,问题仍然存在
  • 一次仅影响一个会话/用户:同时登录的所有其他用户都不会遇到此问题
  • 所有不同的浏览器(IE,Firefox,Chrome)都出现了问题

3 /技术分析

当发生断开连接时,用户将被重定向到“您的会话已过期或您无权查看”页面。加载此页面后,我们会收到一封带有$ _SESSION变量转储的技术电子邮件。

当会话以正常方式过期时,我们收到的电子邮件显示$ _SESSION变量为空(正常行为)。 当发生意外断开时,有趣的是$ _SESSION并非完全为空:在数组包含的~20个元素中,只剩下一个(总是相同)。

因此,这意味着会话未过期,但没有足够的数据来“识别”用户,因此显示“无权限”页面。作为确认,当发生这种情况时,我们可以检查memcached,该会话仍然保存一些数据。

这些是我们到目前为止已经确定的潜在问题,以及我们为排除这些问题所做的工作:

  • Memcached表示70和80%的自由空间,所以我们认为不是问题。
  • 我们删除了Memcached并返回使用NFS共享目录来访问会话文件:问题实际上变得更糟。这将指向一个应用程序错误,因为NFS写入数据的速度较慢,会更频繁地发生会话丢失。
  • 我们浏览了所有讨论PHP会话数据丢失的不同论坛(包括SO),并相应地审查了我们的代码。代码库很大,但我们使用自动化工具和脚本来避免丢失文件。
    • 在每个页面的开头调用session_start()。
    • 在每个标题(“Location ...”)之后调用
    • exit()
    • register_globals已关闭
  • 我们测试了其他两个应用程序和有问题的应用程序之间可能存在的交互,尽管它们不共享任何代码,数据库或会话处理。那里没有任何东西。
  • 我们已经分析了断开连接时的访问日志,以检查行为模式:这里没有运气。

所以我们不知道导致这个问题的原因,因为它似乎是随机出现的,所以我的问题是:

  • 问题可能来自我们的代码:我们错过了要检查的任何内容吗?这个解决方案似乎不太可能,因为代码大部分时间都适用于所有用户,但我仍然在考虑它。
  • 问题可能来自另一个会“清空”部分会话变量数组的应用程序/进程。我们还审查了其他应用程序的代码,但没有找到任何可能导致此问题的代码。 如果另一个进程正在执行此操作,为什么它只会清空一些会话而不是所有会话?

感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

我认为你不会得到你问题的明确答案。可能的原因太多,您没有显示任何代码。

不过,我的猜测是你已关闭memcached.sess_locking,或者如果你有自定义会话实现 - 它根本没有实现锁定。
最终,这会导致两个同时发出的HTTP请求之间存在竞争条件。

我的猜测是基于经常看到的关闭锁或尽快释放它们的不良建议,以达到更高的性能。

答案 1 :(得分:0)

如果“突然”发生此问题,请检查更改内容。你在申请上做过什么工作吗?如果是,请检查已提交的代码(您谈到了自动化工具,因此我希望有一个存储库可以准确找到代码更改)。 你在服务器上有什么改变吗?像升级软件,升级/更改硬件,更改其他两个应用程序? 想到一件事,你检查了用于缓存的驱动器吗?它可能是文件系统的损坏部分。这将解释随机用户部分。

我经常做的几件事是:

  • 尝试确定首次出现的时刻尽可能准确。在我的工作中,这偶尔会触发某人说“噢,这可能与我改变/更新/创建这个或那个时有关”,所以这可能会有所帮助。另一方面,它有时需要数天,数周或更长时间才会被注意到,所以如果没有出现,请开始扩展该时间范围。
  • 您已经有几个方案,在这些方案中找到共同因素。如果他们不共享任何代码,请停止查看。如果他们在那里共享代码搜索。当然,在这里分享(部分)可能会让我们帮助您搜索。
  • 进行有组织的搜索。当我是应用程序中最常用的人时(通常在我创建它时更好),我通常会进行主应用程序检查。一位同事将检查可能对其产生影响的周围应用程序。在你的情况下那2个其他应用程序。最后,我们的系统管理员将检查服务器上新安装或更新的软件,他还会检查我们的网络人员是否有任何硬件改变或网络相关的改变(对于其他人,这可能是托管服务提供商)。

答案 2 :(得分:0)

它可以像使用会话的WordPress插件一样简单,并使用不同的值调用session_name()session_id(),将自定义应用程序与默认会话设置重叠。

由于WordPress本身不使用会话,因此插件通常是从具有会话自由的角度编写的。我刚刚在一个WordPress测试网站上进行了搜索,发现了一个画廊插件中使用的会话,一个用于在页面上放置背景图像的插件,一个购物车插件,以及我正在编写的插件,需要从一个上传文件管理页面到另一个。