Kibana 将仪表板加载时间最多缩短了 25%——以下是其背后的轮询策略
了解 Kibana 如何使用连续轮询和浏览器端 HTTP/2 检测将仪表板加载时间减少多达 25%,并自动回退到 HTTP/1。
由于采用了连续轮询,Kibana 仪表板和 Discover 的加载速度现在最多可提升 25%。现在,Kibana 不再在定期检查之间休眠,而是保持 HTTP 连接开放,并在 Elasticsearch 查询结果准备就绪时立即提供。在 HTTP/2+(Kibana 默认从 9.0 开始使用)上,此功能会自动启动,无需任何配置。在 HTTP/1 上,Kibana 会回退到传统轮询以防止连接池耗尽。
Kibana 在加载仪表板时如何获取数据
打开仪表板后,大部分面板(我们在内部称之为嵌入式面板)都会启动一个或多个 Elasticsearch 查询。但我们使用的不是同步 (sync) 搜索的简单调用和响应,而是异步 (async) 搜索(文档)的强大功能。
使用异步搜索,查询结果会保存在 Elasticsearch 中,而无需依赖任何特定的 HTTP 请求。这非常重要,因为它
使数据加载不受网络动荡的影响
为我们的后台搜索功能提供支持,让用户在等待长时间运行的仪表板或 Discover 会话时,仍能在 Kibana 中处理其他任务
提交初始查询后,Kibana 会监测搜索,以检测搜索何时完成并检索结果集。
传统轮询如何影响 Kibana 仪表板的加载时间
在传统轮询中,Kibana 会提交查询,关闭初始连接,然后定期检查 Elasticsearch 是否完成。

传统轮询策略
我们确实会在查询提交后给 Elasticsearch 一小段时间来完成搜索并返回结果。如果搜索完成得这么快,那就相当于一次简单的请求与响应。但是对于较长的搜索,初始连接会关闭,Kibana 开始定期检查搜索是否完成。这被称为轮询。
传统轮询的性能缺陷
从上图可以看出,这种方法的性能缺陷是:搜索很可能在 Kibana 的某个休眠间隔期间完成,从而造成时间损失。

传统民意调查的阴暗面
在最坏的情况下(搜索在休眠期开始时完成),整个轮询间隔的时间都将浪费。
退避策略的影响
在进行轮询时,采用退避策略是一种标准做法。这意味着搜索时间越长,我们的轮询频率越低。

轮询间隔退避时间表
然而,这也意味着潜在的损失时间会随着搜索持续时间的增加而扩展。
轮询间隔如何产生锯齿延迟模式
将这些因素综合起来,我们损失的时间就成了一个阶梯状的锯齿函数。

查询持续时间造成的时间损失
在这里,峰值是最坏的情况,峰谷是最好的情况。这表明,传统轮询的成本取决于搜索持续时间(以及网络状况),可能从零到整个轮询间隔的全部时长不等。
持续轮询:Kibana 如何消除等待时间
传统轮询的问题在于 Kibana 和 Elasticsearch 之间缺乏基本的协调。理想情况下,Kibana 能够立即知道结果是否可用。那么,如果我们将轮询模式颠倒,使几乎所有时间都用于检查 Elasticsearch,而不再有任何休眠时间,会怎么样?

连续轮询:解决损失时间的解决方案
通过这种长轮询和取消睡眠间隔,因此一旦准备就绪,就能立即获得结果。
HTTP/1 降级
这个理论很可靠。那么,为什么启用连续轮询后,Kibana 部署的性能会下降这么多?

连续轮询会导致通过 HTTP/1 连接的客户端性能下降
关键在于,此部署通过 HTTP/1 运行。在 HTTP/1 中,HTTP 请求与 TCP 连接一一对应。因此,多个长期轮询请求占用了浏览器有限的连接池,导致其他请求排队等待。
另一方面,在 HTTP/2+ 中,网络请求可以通过多路复用共享 TCP 连接,因此我们不会遇到这个问题。

HTTP/1 和 HTTP/2+ 之间 HTTP-TCP 映射的差异
因此,在 HTTP/2+ 中,持续轮询是一种优点,但在 HTTP/1 中,它却变成了一种缺点。
HTTP/1 | HTTP/2+ | |
|---|---|---|
TCP 连接 | 每个 HTTP 请求均有一个 | 多路复用(多个请求共享连接) |
连续轮询行为 | 性能下降(连接池耗尽) | 全面获益(立即见效) |
Kibana 如何检测 HTTP 协议以优化轮询
HTTP/2 是推荐使用的协议,而且自 9.0 版起已成为 Kibana 的默认协议,因此不提供这项性能提升将是一大遗憾。另一方面,HTTP/1 体验已严重下降,任何尚未升级协议的本地部署均不应冒险使用该协议。答案显而易见:我们需要检测正在使用的协议,并采用最佳轮询策略。
Kibana 服务器当然有可能知道它使用的是哪种协议。但有一个问题:限制因素是浏览器的连接池。这意味着,真正重要的是浏览器所传达的信息。
由于代理的存在,这些并不总是相同的。

每个网络跳转的协议可能不同
如果我们基于服务器协议进行优化,可能会有两种原因出错。
在不应进行连续轮询的情况下进行轮询,会降低体验。
未能在需要时应用连续轮询,就会错过优化机会。
幸运的是,现代浏览器提可以通过使用 PerformanceObserver 来检测任何已完成请求的最后一个网络跳转的协议。因此,我们会关注首次提交查询的协议,并在此基础上进行优化。
new PerformanceObserver((list) => {
const entries = list.getEntries();
const entry = entries.find(({ name }) => name.includes('/internal/search/'));
if (entry) {
this.protocolSupportsMultiplexing = ['h2', 'h3'].includes(entry.nextHopProtocol);
}
});实验室结果:Kibana 中的连续轮询与传统轮询的对比
为了验证连续轮询,我们创建了查询延迟时间为 1 至 23 秒的仪表板,并测量了已启用和未启用优化的加载时间。然后,我们加载了带连续轮询和不带连续轮询的仪表板,以衡量收益(我们在 race-for-the-prize 中获得了很多乐趣)。

按查询时长划分的仪表板加载时间
该模式与我们最初的锯齿状图相呼应。对于某些查询时长,收益很小,而对于其他查询时长,收益可达数秒。
结论
这一优化成功地用更高效的连续轮询策略取代了传统轮询固有的延迟。主要挑战在于有条件地实施此优化,以防止 HTTP/1 部署的性能下降。我们使用浏览器的 PerformanceObserver 来可靠地检测最终网络跳转所使用的协议,从而解决了这个问题。
实验室测试验证了这一理论,表明连续轮询可以在结果准备就绪后立即提供结果。平均而言,这将显著改善用户体验,使数据加载速度提高 25%。
这项工作是我们致力于缩短用户获得见解时间的最新举措。通过使 Kibana 成为 Elasticsearch 数据的更透明代理,我们推动了自身影响范围内的性能极限。更多精彩,敬请期待!
(在 2025 年,Thomas Neirynk 对提升 Kibana 仪表板性能的方法和动机进行了精彩的概述。这是该计划的最新进展。)
常见问题
连续轮询如何提升仪表板在 Kibana 中的加载速度?
仪表板加载速度取决于 Kibana 从 Elasticsearch 检索查询结果的速度。传统的轮询会定期检查完成状态,这可能会导致检索结果时出现延迟。借助 HTTP/2+,Kibana 可自动启用连续轮询,通过保持连接开放来消除延迟,并在准备就绪时立即提供结果。
什么是连续轮询,它如何提升 Kibana 的性能?
连续轮询通过在等待 Elasticsearch 查询结果时保持 HTTP 连接开启,而不是在周期性检查之间进行休眠,从而颠覆了传统模式。这样可以避免浪费时间,并在结果准备就绪后立即交付,从而加快仪表板和 Discover 的速度。
连续轮询是否适用于 HTTP/1 连接?
不。连续轮询仅适用于 HTTP/2+ 连接,在这种连接中,多路复用可防止长期请求阻塞其他流量。Kibana 会使用浏览器的 PerformanceObserver API 自动检测协议,并在 HTTP/1 上应用传统轮询以避免性能下降。
使用连续轮询时,Kibana 仪表板的速度能提升多少?
实验室测试表明,根据查询持续时间的长短,仪表板的加载时间最多可缩短 25%。查询时间越长,节省的绝对时间就越多,对于查询时间非常短的查询则几乎没有差异。
Kibana 如何检测应使用连续轮询还是传统轮询?
Kibana 使用浏览器的 PerformanceObserver API 来检测第一个查询请求的 HTTP 协议。如果协议是 HTTP/2 或 HTTP/3(支持复用),则启用连续轮询。如果检测到 HTTP/1,将使用传统轮询以防止连接池耗尽。
持续轮询会导致您的网络代理或负载均衡器出现问题吗?
连续轮询依靠 HTTP/2+ 多路复用来避免浏览器连接池耗尽。如果您的代理将代理和浏览器之间的连接降级为 HTTP/1,Kibana 将检测到这一点,并改用传统的轮询方式。该优化将根据浏览器实际使用的协议有条件地应用。
我遇到了超时问题。我该怎么办?
如果您的代理使用 HTTP/2+ 但强制执行低于 30 秒的超时时间,您将会看到搜索超时。要修复此问题,您可以增加代理的超时时间,或者在 kibana.yml 中将 data.search.asyncSearch.pollLength 设置为低于超时的值。




