我对会话驱动程序有非常具体的需求,因为我将使用 pingbacks(API 规范)实现基于 API 的登录,并且我需要会话驱动程序的非常自定义的行为。同时包括数据库/memcached 交互。该项目是“不问不说”的东西 xD 但无论如何,任何帮助将不胜感激。
我知道 laravel 4 支持这种东西。他们支持自定义创建者,但是关于如何做到这一点的文档只有 0 个。global.php 中不再使用“Session::extend”方法:/
基本上你可以通过创建自己的类然后在 app/config/app.php 中替换它来扩展/替换任何 Laravel 类。
来自 Dayle:“在 Laravel 4 中,组件(核心类)是使用 ProviderInterfaces 加载的,这些都列在应用程序配置中。如果您将提供者更改为您自己的自定义提供者(对于扩展类),您的代码不仅会使用新模块,但 Laravel 核心也将利用这些更改。”
我想知道你需要什么样的具体行为。但我必须提醒您,使用会话与使用任何其他类型的共享资源相同,因此必须适用所有原则,尤其是防止并发写入。
PHP 在文件存储以及 Memcache 存储的标准实现方面做得很好。每当涉及到用户实现的会话读取和保存时,针对并发访问的锁定通常会被忽略和遗忘。另一方面,锁定会话将使多个并行请求的执行串行化,这对于每个会话 ID 可能有多个并发 Ajax 请求的 Web 2.0 应用程序来说并不是最好的选择。
我很抱歉这么说,但 Laravel 在这方面做得很糟糕。即使文件驱动程序根本不锁定,即使他们在保存数据时尝试。他们未能实现的是在读取数据之前需要建立锁。否则,相同的数据会被读取两次,两次不同的更改,然后写回两次 - 但第一次更改会丢失。
这个并发问题真的很难调试,因为在使用没有任何 Ajax 或仅用于读取的 Ajax 的传统网页应用程序时,它可能不会发生。
所以我建议不要使用当前的 Laravel 会话驱动程序。他们在写入会话文件方面做得非常糟糕(我的第一个问题是:为什么他们首先需要重新实现对文件的写入 - PHP 中已经有工作代码,这可能也更快,因为它是用C,而不是 PHP),对于他们写入的所有其他内容也是如此。
更新:
我首先查看了错误的源代码。正如评论中提到的,Laravel 3 在这方面完全被打破了,即使是文件,因为它没有使用原生的 PHP 会话存储处理程序,而是实现了自己的。
Laravel 4 一直使用这种布局,直到 beta 4,同样被破坏了。直到最近才发生使用 Symfony/HTTP-Foundation 而不是他们自己的重大返工。所以 Laravel 4 现在不对任何失败负责,Symfony 是。
Symfony 做得稍微好一点,因为实际上有一个会话存储驱动程序,它使用原生 PHP 功能将会话保存到文件中。欢迎回来会话锁定!\Symfony\Component\HttpFoundation\Session\Storage\Handler \ NativeFileSessionHandler 调用to ini_set()
。session.save_handler
files
任何其他存储处理程序(由于明显的原因,NullSessionHandler 除外)都会自行实现加载和保存数据而无需任何锁定。
让我们看一个可以轻松修复的示例:MemcachedSessionHandler
. 如果你看它,你几乎看不到open()
andclose()
方法中的任何代码,但这是应该发生锁定的地方。唯一的活动代码是 inread()
和write()
(and destroy()
),它直接与 Memcached 客户端对象对话。所以可以假设我没有注意到锁定发生的地方 - 没有!
Memcached 实际上为 PHP 提供了一个本地会话保存处理程序。见http://php.net/manual/en/memcached.sessions.php
简单的解决方法是主要复制 NativeFileSessionHandler 并将 和 设置为session.save_handler = memcached
您session.save_path
要使用的 Memcache 集群。保存处理程序实现正确的锁定。
有一个未解决的问题报告了这一点:https ://github.com/symfony/symfony/issues/4976现在已经开放了 10 个月,这告诉我大多数开发人员更喜欢并发请求的极快会话读取操作而不是实施适当的锁定。
所以 Laravel 4 做了一些正确的事情来摆脱他们自己实现的错误代码(我不觉得他们当时看到了这个错误),但现在继承了 Symfony 代码的错误。
你应该做什么:
Zend Server 提供 Zend Session Cluster。它适用于我正在使用的环境。它对 PHP 是透明的并且具有锁定功能。它将数据写入硬盘并提供高可用性。我认为这是一个相当不错的功能集。想想看。
Memcached 的本机会话保存处理程序也具有锁定功能。我相信它在某种程度上缺乏对高可用性的支持,当然,存储在节点上的任何数据都会丢失。毕竟,它只是一个非常快的缓存,而不是可靠的存储。
对于任何其他存储,您需要弄清楚如何以原子方式获取锁。或者处理并发写入。
例如,MySQL 提供使用SELECT * FROM sesstable WHERE id = sessID FOR UPDATE
. Redis 还提供了一种带有 SET 的锁定机制。
如果锁定不是您想要做的,另一种选择是在确实发生并发写入时尝试清理。CouchDB 允许写入冲突,由客户端应用程序来解决它们 - 数据库将允许访问所有不同的版本。Memcached 还提供Memcached::cas
(比较和交换),仅当已存储的值未更改时才会写入。读取失败时存储的值,尝试与当前数据集合并,然后重试。