由于网站性能下降,我开始将信息清漆视为caching解决scheme,并对Google Analytics(分析)有一些疑问。
当网站上有5K个活跃用户时(根据GA的实时stream量报告),服务器在后台服务器上加载达到30-40 +,乘客队列开始堆叠,站点几乎不可用。 我知道缓慢的查询和数据库工作需要获得更好的性能,但目前我没有资源来优化查询和数据库模式,索引等,所以考虑添加清漆。
我创build了一个图来更好地显示堆栈,下面是当前堆栈的样子:(该网站当前cachingCDN中的images / css / js – Akamai)
我想在后端服务器前添加两个varnish实例来caching文章,堆栈如下所示:
该网站是一个新闻网站,我正在寻找一个build议,如何正确处理cookie和caching。 对于第一阶段,我想完全排除经过validation的用户并提供dynamic内容,因为同时进行身份validation的用户不多。
Google Analytics(分析)的Cookie存在混淆。 我的理解是,Google使用javascript在客户端上设置了一个cookie,客户端直接与Google进行通信,因此后端不需要客户端发送的GA cookie,在vcl_recv子例程中取消设置是安全的。
sub vcl_recv { // Remove has_js and Google Analytics __* cookies. set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_[_a-z]+|has_js)=[^;]*", ""); // Remove a ";" prefix, if present. set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", ""); }
问题
由于默认情况下,varnish不会caching任何具有cookie集的东西,所以通过添加一个删除GA cookie的策略来实现上述堆栈是否安全? 我了解到,如果没有微调VCL政策,我不会得到很高的命中率,但是在我的testing中,即使在后端服务器前面的默认清漆,也有30%的命中率,分析之后,我看到大多数是js / css和图像文件,所以很明显,这些静态文件中有一些不是由Akamai甚至Apache服务的,而是传递给Passenger / Rails来提供静态文件。 这肯定需要纠正。
我是新的清漆,所以任何额外的细节/build议在清漆或堆栈,我build议,非常感激。
对于阶段2 +
由于内容得到更新,我打算在两个清漆服务器上执行清除,当后端服务器发生更改时(例如用户评论,页面浏览等)触发清除服务器。
有很多没有更新的归档文章,它是永久caching他们的安全吗?
由于我打算使用内存作为清漆存储,我应该有额外的(第三)清漆,并使用磁盘进行存储,明确这些存档页面。 也许在varnish服务器前面添加nginx堆栈以将stream量引导到存档内容的特定清漆实例? 负载平衡器 – >一对Nginx反向代理>一对清漆 – >(清漆LB到8后端服务器)
我很感激任何有关build筑的build议。 如果您需要更多的细节提供更好的build议,请让我知道,我会很乐意为您提供更多的细节。
这是很多问题! 🙂
Q. Is this a safe approach?
表面上,我会这样说。
一般来说,在流量大,内容快速变化的新闻网站上设置Varnish可能是一个挑战。
一个很好的方法是建立一个清漆盒,并直接访问群集(不通过负载平衡器),并给它一个临时的公共IP地址。 这将给你一个机会来测试VCL的变化。 你将能够测试评论,登录(如果你有),以及其他任何事情,以确保没有意外。
Q. Will Google still track properly, including repeat visitors?
是。 Cookie只用于客户端。
有一件事你应该看到,当后端发送一个cookie时,Varnish也不会缓存内容。 您将需要删除vcl_fetch上不需要的任何cookie。 如果使用cookie来跟踪用户状态,这可能是一个问题。
Q. Is there anything else that I need to watch for in my policies for phase1?
您将需要在Rails中禁用rack-cache,并设置您自己的头文件。 要知道,如果你删除清漆,Rails将运行没有缓存,可能会崩溃!
这是我在我的production.rb:
# We do not use Rack::Cache but rely on Varnish instead config.middleware.delete Rack::Cache # varnish does not support etags or conditional gets # to the backend (which is this app) so remove them too config.middleware.delete Rack::ETag config.middleware.delete Rack::ConditionalGet
而在我的application_controller我有这个私人的方法:
def set_public_cache_control(duration) if current_user response.headers["Cache-Control"] = "max-age=0, private, must-revalidate" else expires_in duration, :public => true response.headers["Expires"] = CGI.rfc1123_date(Time.now + duration) end end
这在我的其他控制器中被调用,以便对网站的各个部分应用多少抄送有非常细致的控制。 在每个以before_filter方式运行的控制器中使用setup方法:
def setup set_public_cache_control 10.minutes end
(application_controller有过滤器和一个空白的设置方法,所以在其他控制器中可以是可选的)
如果您拥有不需要cookie的站点的一部分,则可以根据VCL中的URL将其剥离,然后应用标题。
你可以像这样在你的apache配置中为你的静态资产设置缓存时间(假设你正在使用默认的资源路径):
<LocationMatch "^/assets/.*$"> Header unset ETag FileETag None # RFC says only cache for 1 year ExpiresActive On ExpiresDefault "access plus 1 year" Header append Cache-Control "public" </LocationMatch> <LocationMatch "^/favicon\.(ico|png)$"> Header unset ETag FileETag None ExpiresActive On ExpiresDefault "access plus 1 day" Header append Cache-Control "public" </LocationMatch> <LocationMatch "^/robots.txt$"> Header unset ETag FileETag None ExpiresActive On ExpiresDefault "access plus 1 hour" Header append Cache-Control "public" </LocationMatch>
这些标题将被发送到您的CDN,这将缓存资产的时间更长。 看清漆,你仍然可以看到要求降低的请求。
我也会在页面不需要cookies的所有内容上设置很短的缓存,但是经常改变。 在我的情况下,我为主页设置了10秒的缓存时间。 这对Varnish来说意味着一个用户请求将每隔10秒进入后端。
您还应该考虑设置清漆使用宽限模式。 这使得它可以缓存来自缓存的稍陈旧的内容,优先于来自后端的对于刚过期的项目的缓慢响应的访问者。
Q. There are plenty of archived articles that don't get updated, is it safe to cache them forever?
要做到这一点,你需要改变你的应用程序发送不同的头文件的文件被归档。 这假定他们不会有饼干。 根据我在我的网站上做的事情,我会这样做:
在上面的设置中添加一个条件来更改缓存时间:
def setup # check if it is old. This code could be anything if news.last_updated_at < 1.months.ago set_public_cache_control 1.year else set_public_cache_control 10.minutes end end
这将设置一个公共头,因此Varnish将缓存它(如果没有cookie),任何远程缓存(在ISP或企业网关)都将缓存。
这个问题是,如果你想删除故事,或更新(例如,出于法律原因)。
在这种情况下,你应该发送Varnish一个私人头来改变这个URL的TTL,但是为其他人发送一个较短的公共头。
这将允许您设置Varnish服务内容(比如说)1年,同时发送标题告诉客户每10分钟回来一次。
在这种情况下,您需要添加一个清除清漆的制度。
为了让你开始我有我的application_controller中的第二个方法:
def set_private_cache_control(duration=5.seconds) # logged in users never have cached content so no TTL allowed if ! current_user # This header MUST be a string or the app will crash if duration response.headers["X-Varnish-TTL"] = duration.to_s end end end
而在我的vcl_fetch我有这个:
call set_varnish_ttl_from_header;
而vcl的功能是这样的:
sub set_varnish_ttl_from_header { if (beresp.http.X-Varnish-TTL) { C{ char *x_end = 0; const char *x_hdr_val = VRT_GetHdr(sp, HDR_BERESP, "\016X-Varnish-TTL:"); /* "\016" is length of header plus colon in octal */ if (x_hdr_val) { long x_cache_ttl = strtol(x_hdr_val, &x_end, 0); if (ERANGE != errno && x_end != x_hdr_val && x_cache_ttl >= 0 && x_cache_ttl < INT_MAX) { VRT_l_beresp_ttl(sp, (x_cache_ttl * 1)); } } }C remove beresp.http.X-Varnish-TTL; } }
这就是说,头文件不会传递给任何上游缓存(s-max-age)。
安装方法如下所示:
def setup # check if it is old. This code could be anything if news.last_updated_at < 1.months.ago set_public_cache_control 10.minutes set_private_cache_control 1.year else set_public_cache_control 10.minutes end end
随意问任何补充问题,我会更新这个答案!