使用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
智能表单+
工作流 快速业务开发平台
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
智能表单+
工作流 快速业务开发平台
相关文章推荐
- 在php中直接使用socket编程对memcached缓存进行增删改查数据
- 使用Memcached进行内存缓存
- 使用python 结合mysql和redis进行缓存设计
- 使用 NGINX 进行微程序缓存的好处
- 使用memcached进行内存缓存
- 使用Varnish代替Squid做网站缓存加速器的详细解决方案[原创]
- 使用SqlDependency进行缓存
- 使用memcached进行内存缓存
- web项目使用ehcache-web进行页面缓存或者文件压缩
- 使用ProxySQL查询缓存进行扩展
- 使用memcached进行内存缓存
- 大型网站架构演化(三)——使用缓存改善网站性能
- 使用memcached进行内存缓存
- JavaEE 使用 Redis 数据库进行内容缓存和高访问负载
- 使用Varnish代替Squid做网站缓存加速器的详细解决方案
- 使用frp进行内网穿透入门
- 使用memcached进行内存缓存
- 利用MSSQL对不经常使用的表进行依赖缓存
- 使用memcached进行内存缓存
- 微软企业库4.1学习笔记(十四)缓存模块2 使用缓存模块进行开发