我们使用 Varnish 和 ESI 将子文档嵌入到 JSON 文档中。基本上,我们的应用服务器的响应如下所示:
[
<esi:include src="/station/best_of_80s" />,
<esi:include src="/station/herrmerktradio" />,
<esi:include src="/station/bluesclub" />,
<esi:include src="/station/jazzloft" />,
<esi:include src="/station/jahfari" />,
<esi:include src="/station/maximix" />,
<esi:include src="/station/ondalatina" />,
<esi:include src="/station/deepgroove" />,
<esi:include src="/station/germanyfm" />,
<esi:include src="/station/alternativeworld" />
]
包含的资源本身就是完整且有效的 JSON 响应。所有站点的完整列表大约为 1070。因此,当缓存冷且完整的站点列表是第一个请求时,varnish 在我们的后端发出 1000 个请求。缓存热时ab是这样的:
$ ab -c 100 -n 1000 http://127.0.0.1/stations
[...]
Document Path: /stations
Document Length: 2207910 bytes
Concurrency Level: 100
Time taken for tests: 10.075 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 2208412000 bytes
HTML transferred: 2207910000 bytes
Requests per second: 99.26 [#/sec] (mean)
Time per request: 1007.470 [ms] (mean)
Time per request: 10.075 [ms] (mean, across all concurrent requests)
Transfer rate: 214066.18 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 11 7.3 9 37
Processing: 466 971 97.4 951 1226
Waiting: 0 20 16.6 12 86
Total: 471 982 98.0 960 1230
Percentage of the requests served within a certain time (ms)
50% 960
66% 985
75% 986
80% 988
90% 1141
95% 1163
98% 1221
99% 1229
100% 1230 (longest request)
$
100 rec/sec 看起来不太好,但请考虑文档的大小。 214066Kbytes/sec 使 1Gbit 接口过饱和。
带有热缓存 ab (ab -c 1 -n 1 ...) 的单个请求显示 83ms/req。
后端本身是基于 redis 的。我们在 NewRelic 中测量了 0.9 毫秒 [原文如此] 的平均响应时间。重新启动 Varnish 后,第一个使用冷缓存的请求(ab -c 1 -n 1 ...)显示 3158ms/rec。这意味着在生成响应时,每个 ESI 包含 Varnish 和我们的后端大约 3 毫秒。这是一个标准的核心 i7 比萨盒,有 8 个核心。我是在满载时测量的。我们以这种方式每月服务约 150mio req,命中率为 0.9。这些数字确实表明 ESI 包含是串行解析的。
在设计这样的系统时,您必须考虑 1) 当缓存冷时,您的后端能够在 Varnish 重新启动后承担负载,以及 2) 通常您的资源不会一次全部过期。对于我们的站点,它们每整小时过期一次,但我们会在过期标头中添加最多 120 秒的随机值。
希望对您有所帮助。