Plone 4.2如何使PAS缓存外部usera数据

时间:2012-09-20 08:07:11

标签: caching persistence plone

我正在实现一个处理针对邮件服务器的身份验证的PAS插件。实际上只实现了DBMail。

我意识到,每个请求会多次调用PAS插件中的enumerateUsers函数,并且需要我的插件为每个(后续)请求打开/关闭SQL连接。当然,这非常昂贵。

连接本身在plone工具中处理,该工具能够处理多个不同的邮件服务器,并删除对代表已注册服务器的包装器对象的enumerateUsers调用。

现在我的问题是,我应该使用什么样的缓存(OOBTree,Session?)来提供重复枚举的临时本地存储并避免后续的SQL连接?

另一个想法是,要挂钩第一次登录时发生的用户创建过程,外部用户会发布并完全“本地化”用户。

如果可能的话,第三个想法是将所需数据存储在特定成员中。

这里最好的做法是什么?

1 个答案:

答案 0 :(得分:4)

我确实会缓存查询结果。您需要对缓存结果的时间做出决定,如果长期存储,则需要如何使该缓存无效或检查更改。

这些决策没有最佳实践,因为它们完全取决于存储的数据类型和后端的API。例如,如果它们支持某种新鲜度查询,那么您将永久存储所有内容并轮询后端以查看缓存是否需要更新。

您可以从简单的请求缓存开始;每个请求查询一次,将存储在请求对象上。当请求对象被清理时,您的缓存将在请求结束时自动失效,下一个请求将是一个干净的平板。

如果您的后端用户很少更改,您可以在本地缓存中缓存信息更长时间。我在插件上使用了volatile属性。持久性机制会忽略以_v_开头的任何属性。因此,存储在_v_ volatile属性中的任何内容都是线程本地的,并且仅在进程的生命周期内存在,重新启动服务器会自动清除它们。

至少应该使用_v_ volatile属性来存储后端SQL连接。这样他们可以在请求之间保持打开状态,并且可以重复使用。像下面这样的方法可以做得很好:

def _connection(self):
    # Return a backend connection
    if getattr(self, '_v_connection', None) is None:
        # Create connection here
        self._v_connection = yourdatabaseconnection
    return self._v_connection

您还可以在插件上使用持久属性来存储缓存。此缓存将提交给ZODB并在重新启动时保持不变。然后你真的需要弄清楚如何使内容无效;存储时间戳并将数据逐出旧时等等。

您的缓存数据结构完全取决于您的应用程序需求。如果您不保留信息,则字典(用户名 - >信息)可能绰绰有余。持久化缓存可以从使用OOBTree而不是字典中受益,因为它们可以减少不同线程之间冲突的可能性,并且在涉及大量数据时更有效。

无论你做什么,都需要使用会话。会话容易发生冲突,不能很好地扩展,并且在任何情况下都不是存储此类缓存的地方。