使用Varnish对大型内网进行缓存

3 篇文章 0 订阅
2 篇文章 0 订阅

当内部网站内容和用户越来越多,网站日趋复杂时,访问速度不可避免的越来越低。通过在服务器前端配置 Varnish 进行缓存,可以有效的提升网站的性能。 Varnish 非常适合对静态内容进行缓存,但是对于具有大量动态内容、而且内容的访问权限与用户的角色紧密关联的内部站点,它将变得非常复杂而难以管理。本文提供了一种有效的解决方案。


------------------------------------------------------------------------------------------


使用Varnish 对内网进行缓存

原文链接: http://www.jarn.com/blog/intranet-caching-with-varnish


  powerd by varnish

 

Varnish 非常适合对静态内容进行缓存,但是对于大型的内部站点它将变得非常复杂而难以管理。通过构建一些条件逻辑,我们可以避免这种情况的发生。

最近我们的一个工作是提升一个大型的由 Plone 构建内部站点访问的性能,经过分析我们确定有必要更好的进行 HTTP 缓存。不幸的是,尽管大量的访问集中于相对少量的一些页面,但是这些页面所呈现的内容取决于用户在他们公司的岗位和其他一些身份信息。决定权限的身份信息组合是如此之多,导致这个站点的 varnish 缓存的命中率非常低。

这些身份信息是如此的复杂,不容易全部存储在请求( request )中,所以我们决定在 varnish 中执行一个小的子请求( sub-request )来获取这些身份信息。不幸的是,尽管 varnish 的一个核心功能就是构建 HTTP 请求( make HTTP request ),但是它没有一个简单的发出子请求的 API 。所以我们使用 libCURL 库,并且将我们的插件打包至一个动态库中。然后用 VCL 的内联 C 代码的能力载入这个动态库,在 vcl_hash 中进行调用,如下所示:

sub vcl_hash {

  C{

    if (get_zope_roles) {

      char *str = (*get_zope_roles)("http://localhost:8080/site/@@whoami",

        VRT_r_req_url(sp), VRT_GetHdr(sp, HDR_REQ, "/007cookie:"));

      VRT_l_req_hash(sp, str);

      free(str);

    }

  }C

}

子请求将获取用户的身份信息,并且返回给 varnish 以作为它的 hash 函数的一部分。通常 hash 函数用来判断两个请求是否指向同一个 URL 。这个改动意味着缓存将被有效分离,这样具有 Manager 角色的用户和具有 Contributor 角色的用户访问的是完全不同的缓存内容。当然这要求被缓存的页面完全不包含与特定用户相关的内容,而是只包含与其身份相关的内容。最终结果是我们以较小的代价(子请求获取用户身份信息)提高了整个站点的缓存命中率。

我们是从 Plone 站点的 @@whoami 这个 view 获取用户身份信息的。身份信息是纯文本的,能够很快的获取到。获取的代价相对于整个访问请求可以说是微乎其微的。实际的实现较为复杂,下面是最核心的一些部分:

class WhoAmI(BrowserView):

    """ return effective roles for a given context """

  def __call__(self):

    user = getSecurityManager().getUser()

    url = self.request.get('url', self.request['HTTP_REFERER'])

    url = url.split('VirtualHostRoot/', 1)[-1]

    url = url.split('?', 1)[0]

    try:

      __traceback_info__ = user.getUserName(), url

      obj = self.context.unrestrictedTraverse(url)

      if isinstance(obj, MethodType):

        obj = obj.im_self

      roles = user.getRolesInContext(obj)

      whoami = ' '.join(sorted(roles))

    except (KeyError, AttributeError, IndexError, NotFound):

      # If we can't get roles we fall back to the username

      whoami = user.getUserName()

    return whoami

你可以从 这里 下载代码并且集成到你的 buildout 中去。如果想要让页面能够跨用户缓存,你需要设置 Cache-Control Public

 


---------------------------------------------------------

anzsoft         专业Plone/Zope 技术及服务提供商

Samespace   智能表单+ 工作流 快速业务开发平台

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值