Varnish和ESI,性能如何?

9

我想知道ESI模块的性能现在怎么样?我在网上读到一些帖子说,Varnish上的ESI性能实际上比真正的东西慢。

假设我有一个包含超过3500个ESI包含的页面,这会如何表现? ESI是否设计用于此类使用?


1
我可以想到一种方法来找出答案!制作一个包含3500个文件的页面并进行基准测试,我会非常关注结果 :) - ZoFreX
1
我很乐意去做,但是我对Varnish非常陌生,我认为这样的基准测试应该由专业人士来执行。 - netbrain
2
你为什么想在一个页面中包含3500个元素?只是试图想象这样的使用情况。 - Suor
1
我在考虑使用JSON文档。特别是大型文档。可以使用esi:includes将不同的“子文档”链接在一起。例如,假设您有一个文档,其中列出了员工列表,但仅提供了员工的ID而没有其他信息。然后,使用ESI,您可以根据ID包含员工信息。 - netbrain
我可能会将获取员工列表的操作作为单个请求包含在必要的员工列表中,而不是对每个员工进行迭代。 - Jan Algermissen
3个回答

18
我们正在使用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次/秒的请求速度看起来不是很好,但考虑文档的大小。214066K字节/秒可以充分利用1G位接口。

使用带有缓存的单个请求 ab(ab -c 1 -n 1 ...)显示83ms / req。

后端本身基于Redis。我们在NewRelic中测量了平均响应时间为0.9ms [sic]。在重新启动Varnish后,第一个具有冷缓存(ab -c 1 -n 1 ...)的请求显示3158ms / rec。这意味着在生成响应时,Varnish和我们的后端每个ESI包含大约需要3ms。这是一个标准的带有8个核心的core i7比萨盒子。我在满负荷下测量了这个数字。以这种方式提供大约1.5亿次请求/月,命中率为0.9。这些数字确实表明ESI-包含是串行解析的。

设计这样的系统时必须考虑以下因素:1)在Varnish重新启动时缓存为空时,您的后端能够承受负荷;2)通常您的资源不会全部同时过期。对于我们的站点,它们每小时过期一次,但我们将到期头添加了最多120秒的随机值。

希望这可以帮到你。


1
我刚刚想起来我们在Varnish 3.0.0版本中遇到了问题,具体是超过250个ESI包含。请确保使用3.0.2或更高版本。 - Niko
1
关于过期时间的观点非常好,你的解决方案非常聪明。一定会借鉴的! - ZoFreX

2

我不是第一手资料,但我听说Varnish的当前ESI实现序列化包含请求;也就是说,它们不是并发的。

如果是这样的话,在你提到的情况下,性能确实会很差。

我会尝试让有第一手经验的人来评论。


这实际上是真的,这是Varnish在ESI实现中已知的缺陷。 - José Lorenzo Rodríguez
1
我可以在一个PHP Symfony 2.6安装上进行实际测试以确认: 有一个简单的主控制器/视图,它使用render_esi呈现两个“子”控制器,每个控制器都有一个“sleep(n)”暂停。渲染页面将按照以下方式顺序进行: 首先渲染父视图,然后渲染第一个esi:include标记,然后渲染第二个。 在我的示例中,只有父页面具有共享最大年龄为600,而且如预期的那样,这两个子页面从未被缓存。 我希望它们会同时获取,但实际上它们是顺序获取的。 - cernio
2
cernio - 用的是哪个版本的Varnish? - Mark Nottingham

0

并行 ESI 请求在 varnish 的 **商业**版本中可用:https://www.varnish-software.com/plus/parallel-esi/。片段请求的并行性显然使由多个片段组成的页面的组装更快。

(这将是一条评论,但我声望不足以这样做)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接