跳转到主要内容

Web应用的缓存基础设施

项目描述

简介

网页缓存是一个复杂的过程:有许多可能的策略可供选择,正确的策略可能取决于请求者、正在检索的URL以及接受的语言和编码等资源协商设置。

在应用程序中硬编码缓存逻辑是不可取的,特别是对于可重用代码。也无法允许管理员手动配置应用程序中每个资源的缓存头。这个包试图解决这个问题,通过提供一个缓存规则集框架:它允许实现者为每个组件指定一个规则集。管理员可以定义一个策略,该策略决定了每个规则集的正确缓存行为。

根据您的环境,有不同的选项将规则集转换为HTTP缓存头。

  • 如果您正在使用Plone 3 和 CacheFu,可以使用five.caching 与CacheSetup集成。

  • 如果您正在使用Zope 2.12或更高版本,可以使用plone.caching 与发布者事件集成,如果需要支持PURGE请求,还可以使用plone.cachepurging

  • 如果您正在使用Plone 4,也可以使用plone.app.caching,它为plone.cachingplone.cachepurging 提供UI和默认行为。

  • 在WSGI环境中,您可以在environ或响应头中设置规则集,并添加一个处理这些提示的中间件。

使用方法

您可以使用ZCML或直接在Python中注册规则集。如果您使用ZCML,可以使用<cache:ruleset />指令

<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:browser="http://namespaces.zope.org/browser"
    xmlns:cache="http://namespaces.zope.org/cache"/>

  <include package="z3c.caching" file="meta.zcml" />

  <cache:rulesetType
      name="plone.contentTypes"
      title="Plone content types"
      description="Non-folderish content types"
      />

  <cache:ruleset
      for=".frontpage.FrontpageView"
      ruleset="plone.contentTypes"
      />

  <browser:page
      for="..interfaces.IFrontpage"
      class=".frontpage.FrontpageView"
      name="frontpage_view"
      template="templates/frontpage_view.pt"
      permission="zope2.View" />

</configure>

以下示例设置了一个名为frontpage_view的浏览器视图,并将其与plone.contentTypes规则集关联。

注意:规则集名称应该是点名称。也就是说,它们应该只包含大写或小写字母、数字、下划线和/或点(圆点)。这种想法是形成一个类似于Python包和模块创建的命名空间。

您可以在for属性中指定一个类或接口。与适配器注册一样,可以使用更具体的注册来覆盖更通用的注册。

在上面的示例中,我们还使用<cache:rulesetType />指令添加了一些关于规则集类型的元数据。这对于UI支持主要是有用的,通常可以省略。

如果您更愿意直接使用Python,可以这样做

from z3c.caching.registry import register
from frontpage import FrontpageView

register(FrontpageView, "plone.contentTypes")

要查找对象的规则集,请使用lookup()方法

from z3c.caching.registry import lookup
cacheRule = lookup(FrontpageView)

要声明规则集类型元数据,请使用declareType方法

from z3c.caching.registry import declareType
declareType = declareType(name="plone.contentTypes", \
                          title=u"Plone content types", \
                          description=u"Non-folderish content types")

如果您想获取所有声明的类型的列表,请使用enumerateTypes()方法

from z3c.caching.registry import enumerate
for type_ in enumerateTypes():
    ...

类型对象提供IRulesetType,并具有nametitledescription属性。

严格模式

默认情况下,在使用规则集之前不需要声明其类型。这很方便,但会增加出现拼写错误或语义上等效的规则集大量增加的风险。如果您想避免这种情况,可以将规则集放入显式模式,如下所示

from z3c.caching.registry import setExplicitMode
setExplicitMode(True)

关于可缓存资源的缓存信息

此软件包故意设计得简单,并且只依赖于一小组核心Zope Toolkit软件包。然而,在现实世界中,缓存通常需要关于发布(和可能缓存的)资源的特定信息,例如底层资源上次修改的时间,以及当缓存代理需要清除时需要清除哪些URL。

z3c.caching旨在成为想要声明它们如何进行缓存的包的“安全”和最小化依赖项。因此,虽然设置缓存控制响应头和支持清除缓存反向代理的实现留给其他包,但z3c.caching提供了一些接口,这些“缓存感知”的包可以实现,以便高级框架(如plone.cachingplone.cachepurging)可以依赖。这避免了这些包与高级框架之间的直接依赖。

以下描述了这些接口。还提供了一些辅助组件。要配置它们,您可以在ZCML配置中包含z3c.caching

<include package="z3c.caching" />

最后修改日期/时间

可以使用ILastModified适配器接口来描述给定发布对象的最后修改日期。

class ILastModified(Interface):
    """An abstraction to help obtain a last-modified date for a published
    resource.

    Should be registered as an unnamed adapter from a published object
    (e.g. a view).
    """

    def __call__():
        """Return the last-modified date, as a Python datetime object.

        The datetime returned must be timezone aware and should normally
        be in the local timezone.

        May return None if the last modified date cannot be determined.
        """

为此接口提供了一个默认实现:当查询Zope浏览器视图时,它将委托给视图上下文上的ILastModified适配器。高级包可以选择为其他类型的发布资源以及/或不同类型的视图上下文实现此适配器。

缓存清除

高流量网站经常在Web应用程序服务器前面放置缓存代理,如SquidVarnish,以卸载资源的缓存。这些代理可以通过响应头进行控制(可能是基于z3c.caching规则集查找的缓存操作设置的)。大多数缓存代理还支持所谓的PURGE请求,其中Web应用程序直接向缓存代理发送请求,要求其清除(可能是旧的)可能持有的资源副本(例如,因为该资源已更改)。

此包不实现与缓存代理的任何通信。如果您需要在Zope 2环境中需要,请考虑plone.cachepurging。然而,包括了一些组件来帮助包声明它们与支持清除的缓存代理相关的行为。

首先,z3.caching定义了一个Purge事件,该事件描述了接口z3c.caching.interfaces.IPurgeEvent

class IPurgeEvent(IObjectEvent):
    """Event which can be fired to purge a particular object.

    This event is not fired anywhere in this package. Instead, higher level
    frameworks are expected to fire this event when an object may need to be
    purged.

    It is safe to fire the event multiple times for the same object. A given
    object will only be purged once.
    """

如果一个对象已经更改,可能需要清除,您可以触发此事件,如下所示

from z3c.caching.purge import Purge
from zope.event import notify

notify(Purge(context))

高级框架(如plone.cachepurging)可以监听此事件,为对象排队清除请求。

当然,清除对象缓存表示的最常见原因是它已被修改或删除。z3c.caching为标准事件提供了事件处理器:IObjectModifiedEventIObjectMovedEventIObjectRemovedEvent,这些事件重新广播修改/移动/删除对象的Purge事件。

要选择这些事件处理器,只需使用IPurgeable接口标记您的内容对象,例如

from z3c.caching.interfaces import IPurgeable

class MyContent(Persistent):
    implements(IPurgeable)

    ...

您也可以在ZCML中声明性地执行此操作,即使对于您无法控制的类

<class class=".content.MyContent">
    <implements interface="z3c.caching.interfaces.IPurgeable" />
</class>

这些助手可以向类似于plone.cachepurging的框架发送信号,表明对象需要被清除,但这不足以知道如何构造PURGE请求。缓存代理还需要被告知要清除哪个或哪些路径。这是IPurgePaths适配器接口的职责。

class IPurgePaths(Interface):
    """Return paths to send as PURGE requests for a given object.

    The purging hook will look up named adapters from the objects sent to
    the purge queue (usually by an IPurgeEvent being fired) to this interface.
    The name is not significant, but is used to allow multiple implementations
    whilst still permitting per-type overrides. The names should therefore
    normally be unique, prefixed with the dotted name of the package to which
    they belong.
    """

    def getRelativePaths():
        """Return a list of paths that should be purged. The paths should be
        relative to the virtual hosting root, i.e. they should start with a
        '/'.

        These paths will be rewritten to incorporate virtual hosting if
        necessary.
        """

    def getAbsolutePaths():
        """Return a list of paths that should be purged. The paths should be
        relative to the  domain root, i.e. they should start with a '/'.

        These paths will *not* be rewritten to incorporate virtual hosting.
        """

“相对”路径和“绝对”路径之间的区别只有在使用虚拟主机时才会生效。在大多数情况下,您希望实现getRelativePaths()以返回一个相对于当前虚拟主机根的路径。在Zope 2中,您可以通过任何可遍历项上的absolute_url_path()函数来获取这个路径。或者,您可以查找一个IAbsoluteURL适配器并丢弃域名部分。

getAbsolutePaths()主要对缓存代理的“特殊”路径有用。例如,您可以将Varnish配置为在向/_purge_all发送请求时清除整个缓存,然后实现getAbsolutePaths()以返回包含该字符串的迭代器。

以下是来自plone.cachepurging的默认实现,该实现清除由Zope 2的OFS.Traversable派生的对象的默认路径。

class TraversablePurgePaths(object):
    """Default purge for OFS.Traversable-style objects
    """

    implements(IPurgePaths)
    adapts(ITraversable)

    def __init__(self, context):
        self.context = context

    def getRelativePaths(self):
        return [self.context.absolute_url_path()]

    def getAbsolutePaths(self):
        return []

在ZCML中,这被注册为

<adapter factory=".paths.TraversablePurgePaths" name="default" />

Plone特定的plone.app.caching实现了其他适配器(具有其他唯一的名称),用于处理默认视图方法别名(/view)以及Archetypes图像和文件字段的下载路径。

变更日志

3.0 (2023-02-08)

  • 停止支持Python 2.7、3.5、3.6。[icemac]

  • 添加对Python 3.9、3.10、3.11的支持。[icemac]

2.2 (2019-10-16)

  • 修复弃用警告:从zope.componentzope.interface的导入移动。依赖zope.interface >= 3.8.0。[jensens]

  • 添加对Python 3.8a3的支持。[icemac]

2.1 (2018-11-06)

  • 将IRuleset的规则集更改为TextLine,以与zope.configuration >= 4.2一起使用。参见Products.CMFPlone#2591。[pbauer]

2.0 (2018-03-22)

  • 添加对Python 3.5、3.6、3.7、PyPy2和PyPy3的支持。[icemac]

2.0a1 - 2010年4月22日

  • 添加了Purge事件和IPurgeableIPurgePaths接口。尽管这个包不提供任何清除支持,但为了方便其他包描述它们的缓存清除行为,这里保留必要的接口是有用的。这允许在通用代码中相对无害地依赖z3c.caching,而不是一个更高级的应用服务器特定框架。[optilude]

  • 添加了显式声明规则集类型的概念。默认情况下是可选的,但可以通过将explicit设置为True来使其成为必需的。[optilude]

  • 添加了ILastModified实现,用于将视图委派给视图的上下文。[optilude]

  • 向注册表中添加了enumerateTypes()方法,用于列出所有当前使用的缓存规则ID。[optilude]

  • 使注册表更直接地使用ZCA。[matthewwilkes]

1.0b1 - 2008年10月15日

  • 初始版本 [wichert]

项目详情


下载文件

下载适合您平台的项目文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源代码分发

z3c.caching-3.0.tar.gz (22.1 kB 查看哈希)

上传于

构建分发版

z3c.caching-3.0-py3-none-any.whl (20.6 kB 查看哈希)

上传于 Python 3

由以下支持