您的位置:首页 > 其它

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

2011-04-13 19:09 281 查看
当内部网站内容和用户越来越多,网站日趋复杂时,访问速度不可避免的越来越低。通过在服务器前端配置
Varnish

进行缓存,可以有效的提升网站的性能。
Varnish
非常适合对静态内容进行缓存,但是对于具有大量动态内容、而且内容的访问权限与用户的角色紧密关联的内部站点,它将变得非常复杂而难以管理。本文提供了一种有效的解决方案。

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

使用Varnish
对内网进行缓存


原文链接:
http://www.jarn.com/blog/intranet-caching-with-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.i
a3d8
m_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
 

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

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息