博客

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 是否完成。

Kibana 中的传统轮询示意图。Kibana 时间线显示,提交查询后,有一段短暂的连接开放期,随后是长时间的休眠期,然后是短暂的状态轮询,最后才交付结果。Elasticsearch 时间线运行的查询在 Kibana 的休眠期中途完成,这说明了导致时间损失的协调问题。

传统轮询策略

我们确实会在查询提交后给 Elasticsearch 一小段时间来完成搜索并返回结果。如果搜索完成得这么快,那就相当于一次简单的请求与响应。但是对于较长的搜索,初始连接会关闭,Kibana 开始定期检查搜索是否完成。这被称为轮询

传统轮询的性能缺陷

从上图可以看出,这种方法的性能缺陷是:搜索很可能在 Kibana 的某个休眠间隔期间完成,从而造成时间损失。

显示传统轮询性能成本的时间线图。Kibana 时间线显示了连接打开阶段、一个较长的休眠阶段、一次状态轮询,然后交付结果。Elasticsearch 时间线显示,查询在 Kibana 休眠中途完成,随后出现一段红色的损失时间——即 Kibana 唤醒并检索结果之前被浪费的时间。

传统民意调查的阴暗面

在最坏的情况下(搜索在休眠期开始时完成),整个轮询间隔的时间都将浪费。

退避策略的影响

在进行轮询时,采用退避策略是一种标准做法。这意味着搜索时间越长,我们的轮询频率越低。

水平条形图显示了 Kibana 按查询持续时间划分的轮询间隔退避计划。1.5 秒以下的查询使用大约 0.5 秒的间隔;1.5——5 秒的查询使用 1 秒间隔;5——20 秒的查询使用大约 2.5 秒间隔;20 秒以上的查询使用 5 秒的轮询间隔。

轮询间隔退避时间表

然而,这也意味着潜在的损失时间会随着搜索持续时间的增加而扩展。

轮询间隔如何产生锯齿延迟模式

将这些因素综合起来,我们损失的时间就成了一个阶梯状的锯齿函数。

折线图显示了以秒为单位的损失时间与以秒为单位的查询完成时间之间的关系,呈现出锯齿状模式,即损失时间反复上升然后下降到零,随着查询持续时间从 0 秒增加到 30 秒,损失时间峰值从不到 1 秒增至 5 秒。

查询持续时间造成的时间损失

在这里,峰值是最坏的情况,峰谷是最好的情况。这表明,传统轮询的成本取决于搜索持续时间(以及网络状况),可能从零到整个轮询间隔的全部时长不等。

持续轮询:Kibana 如何消除等待时间

传统轮询的问题在于 Kibana 和 Elasticsearch 之间缺乏基本的协调。理想情况下,Kibana 能够立即知道结果是否可用。那么,如果我们将轮询模式颠倒,使几乎所有时间都用于检查 Elasticsearch,而不再有任何休眠时间,会怎么样?

显示 Kibana 中连续轮询的时间线图。Kibana 时间线完全是蓝色的——从查询提交到两次连接刷新,连接一直保持打开状态,直到结果交付,没有休眠期。Elasticsearch 时间轴显示了查询的完成情况和立即交付的结果。图例中被划掉的“损失时间”表示该选项已排除。

连续轮询:解决损失时间的解决方案

通过这种长轮询和取消睡眠间隔,因此一旦准备就绪,就能立即获得结果。

HTTP/1 降级

这个理论很可靠。那么,为什么启用连续轮询后,Kibana 部署的性能会下降这么多?

显示 Kibana 仪表板加载“示例日志数据”数据集的的动态屏幕录制,展示了多个面板依次填充的过程,包括响应代码时间序列、美国地图上的总请求数、唯一访客数量、HTTP 错误率指标,以及机器操作系统与目标数据的桑基图。

连续轮询会导致通过 HTTP/1 连接的客户端性能下降

关键在于,此部署通过 HTTP/1 运行。在 HTTP/1 中,HTTP 请求与 TCP 连接一一对应。因此,多个长期轮询请求占用了浏览器有限的连接池,导致其他请求排队等待。

另一方面,在 HTTP/2+ 中,网络请求可以通过多路复用共享 TCP 连接,因此我们不会遇到这个问题。

Kibana 连续轮询的 HTTP/1 与 HTTP/2 的对比图。HTTP/1 每次请求都需要一个 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 服务器当然有可能知道它使用的是哪种协议。但有一个问题:限制因素是浏览器的连接池。这意味着,真正重要的是浏览器所传达的信息。

由于代理的存在,这些并不总是相同的。

架构图显示了三个水平连接的组件:左侧是 Kibana 服务器,中间是可选的代理,右侧是 Kibana 客户端。服务器到代理的跳转由 kibana.yml server.protocol 标记,表示已知的协议。代理到客户端的跳转被标记为三个问号,表示该最终跳转所使用的协议未知,可能有所不同。

每个网络跳转的协议可能不同

如果我们基于服务器协议进行优化,可能会有两种原因出错。

  1. 在不应进行连续轮询的情况下进行轮询,会降低体验。

  2. 未能在需要时应用连续轮询,就会错过优化机会。

幸运的是,现代浏览器提可以通过使用 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 中获得了很多乐趣)。

条形图显示了 Kibana 连续轮询的实验室测试结果:与传统轮询相比,在 1 至 23 秒的查询持续时间内节省的时间。根据查询完成时间相对于轮询间隔边界的位置不同,节省的时间在接近零到 4.9 秒之间变化,这证实了退避计划所预测的锯齿状延迟模式。

按查询时长划分的仪表板加载时间

该模式与我们最初的锯齿状图相呼应。对于某些查询时长,收益很小,而对于其他查询时长,收益可达数秒。

结论

这一优化成功地用更高效的连续轮询策略取代了传统轮询固有的延迟。主要挑战在于有条件地实施此优化,以防止 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 设置为低于超时的值。

相关内容

人工智能驱动的仪表盘:从设想到 Kibana

Jeffrey Rengifo

使用 Kibana 将地理空间数据输入 Elasticsearch,以便在 ES|QL 中使用

Craig Taverner

使用变量控件来提高 Kibana 仪表板的交互性

Teresa Alvarez Soler

用描述代替手动绘制:通过 MCP 和 ES|QL 构建 AI 原生 Kibana 仪表板。

Stratoula Kalafateli

Spotify Wrapped 第 2 部分:数据分析和可视化

Philipp Kahr

准备好打造最先进的搜索体验了吗?

足够先进的搜索不是一个人的努力就能实现的。Elasticsearch 由数据科学家、ML 操作员、工程师以及更多和您一样对搜索充满热情的人提供支持。让我们联系起来,共同打造神奇的搜索体验,让您获得想要的结果。

亲自试用