这是我们过去几周一直面临的问题.
1 /我们的设置
PHP 5.4 + MySQL
2个专用服务器,负载均衡
使用memcached在2台服务器之间复制会话
在这些服务器上运行的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().
每个标题后调用exit()("Location ...")
register_globals是关闭的
我们已经测试了我们的其他两个应用程序和有问题的应用程序之间可能的交互,尽管它们不共享任何代码,数据库或会话处理.那里没有任何东西.
我们已经分析了断开连接时的访问日志,以检查行为模式:这里也没有运气.
所以我们不知道是什么导致了这个问题,因为它似乎是随机发生的,所以我的问题是:
问题可能来自我们的代码:我们错过了要检查的任何内容吗?这个解决方案似乎不太可能,因为代码大部分时间都适用于所有用户,但我仍然在考虑它.
问题可能来自另一个会"清空"会话变量数组部分的应用程序/进程.我们还审查了其他应用程序的代码,但没有找到任何可能导致此问题的代码.如果另一个进程正在执行此操作,为什么它只会清空一些会话而不是所有会话?
谢谢你的帮助.