常见问题
Jaeger 常见问题解答。
为什么依赖关系页面是空的?
依赖项页面显示了 Jaeger 跟踪的服务图以及它们之间的连接。当您使用带内存存储的 all-in-one
二进制文件时,该图是根据内存中存储的所有跟踪按需计算的。但是,如果您使用真正的分布式存储(如 Cassandra 或 OpenSearch/Elasticsearch),扫描数据库中的所有数据来构建服务图的成本会非常高。相反,Jaeger 项目提供了“大数据”作业,可用于从跟踪中提取服务图数据
- https://github.com/jaegertracing/spark-dependencies - 较早的 Spark 作业,可定期运行
- https://github.com/jaegertracing/jaeger-analytics - 新的(实验性)流式 Flink 作业,可持续运行并在较短的时间间隔内构建服务图
为什么我在 Jaeger 中看不到任何 Span?
请参阅故障排除指南。
jaeger-agent 发生了什么?
由于 Jaeger 客户端库已被弃用,并且 OpenTelemetry SDK 已逐步停止支持 Jaeger Thrift 格式,因此 jaeger-agent 不再需要且不再受支持。有关替代部署选项,请参阅架构页面。
有时仍然需要运行主机代理
- 如果希望 SDK 将跟踪数据直接发送到 jaeger-collector,我们必须向它们提供 HTTP 端点的 URL。这意味着我们的应用程序需要包含此参数的额外配置,特别是当我们运行多个 Jaeger 安装(例如在不同的可用区或区域)并希望将数据发送到附近的安装时。相比之下,使用主机代理时,库不需要额外配置,因为代理始终可通过
localhost
访问。它充当 Sidecar 并将请求代理到相应的 jaeger-collector。 - 主机代理可以配置为通过向 Span 添加额外标签(例如当前区域、地区等)来丰富跟踪数据,使其包含基础设施特定的元数据。如果主机代理作为主机守护程序运行,它将由同一主机上运行的所有应用程序共享。如果主机代理作为真正的 Sidecar 运行(即每个应用程序一个),它可以提供额外的功能,例如强身份验证、多租户(请参阅这篇博客文章 )、Pod 名称等。
- 主机代理允许对 jaeger-collector 实施流量控制。如果数据中心有数千台主机,每台主机运行多个应用程序,并且每个应用程序都直接向 jaeger-collector 发送数据,那么每个 jaeger-collector 可能需要处理过多的开放连接。代理可以通过更少的连接来负载均衡此流量。
如果您的环境需要主机代理,您可以部署 OpenTelemetry Collector 来承担此角色。
推荐的存储后端是什么?
Jaeger 团队推荐 OpenSearch/Elasticsearch 作为存储后端,而不是 Cassandra,原因如下:
Cassandra 是一个键值数据库,因此它更适合通过跟踪 ID 检索跟踪,但它不提供与 OpenSearch 相同的强大搜索功能。实际上,Jaeger 后端在客户端实现了搜索功能,基于键值存储,这既有限又可能产生不一致的结果(有关更多详细信息,请参阅issue-166 )。OpenSearch 不存在这些问题,从而提供了更好的可用性。OpenSearch 也可以直接查询,例如从 Kibana 仪表板中查询,并提供有用的分析和聚合。
根据过去的性能实验,我们观察到 Cassandra 中的单次写入比 OpenSearch 快得多,这可能表明它能够支持更高的写入吞吐量。然而,由于 Jaeger 后端需要在键值存储之上实现搜索功能,将 Span 写入 Cassandra 实际上会受到很大的写入放大影响:除了为 Span 本身写入记录外,Jaeger 还会为服务名称和操作名称索引执行额外的写入,并为每个标签执行额外的索引写入。相比之下,将 Span 保存到 OpenSearch 是一次性写入,所有索引都发生在 OpenSearch 节点内部。因此,Cassandra 的总体吞吐量与 OpenSearch 相当。
Cassandra 后端的一个好处是由于其对数据 TTL 的原生支持而简化了维护。在 OpenSearch 中,数据过期通过索引轮换管理,这需要额外的设置(请参阅Elasticsearch Rollover)。
为什么 Jaeger 跟踪 ID 在 Kafka 和 UI 中的显示不同?
在内部,从数据模型层面来看,Jaeger 跟踪 ID 是一个 16 字节的序列。然而,这 16 字节可以用许多不同的方式表示
- 在 UI 中,我们历史上将它们表示为十六进制编码字符串,例如
7e90c0eca22784ec7e90c0eca22784ec
。当使用 128 位 ID(在 OpenTelemetry 中更常见)时,这些字符串可以是 32 个字符长,如果 ID 是在旧的 64 位模式下生成的,则可以是 16 个字符。 - 在 Jaeger 后端代码的领域模型 中,我们使用大端编码将跟踪 ID 表示为一对无符号 64 位整数。这样做是为了提高效率,因为 Go 中的字节切片需要额外的内存分配。
- 在原始的Thrift 模型 中,我们也将其表示为一对无符号 64 位整数
- 在Protobuf 模型 中,ID 表示为字节序列。当 Protobuf 序列化为二进制负载时,这些字节会按原样传输。然而,Protobuf 也支持 JSON 编码,其中字节序列使用 base64 编码进行序列化。因此,如果您将 collector-Kafka-ingester 管道配置为使用 JSON 编码,您将看到类似
fpDA7KInhOx+kMDsoieE7A==
的跟踪 ID。这些 ID 可以使用 https://base64.guru/converter/encode/hex 等在线工具转换为 UI 识别的十六进制编码 ID。
我需要运行多个 Collector 吗?
jaeger-collector 的高可用性是否能提高整体系统性能,例如减少丢弃的 Span 数量和减少跟踪收集中断?是否推荐使用?如果是,为什么?
以下是运行多个实例的原因:
- 您的客户端发送的数据量太大,单个 jaeger-collector 无法足够快地接收。
- 您希望实现更高的可用性,例如,当您对 jaeger-collector 进行滚动重启以进行升级时,仍有一些实例在运行并能够处理入站数据。
以下不是运行多个实例的原因:
- 为了避免数据丢失。当后端存储无法足够快地保存数据时,jaeger-collector 会丢弃数据。增加 jaeger-collector 的数量,并为其内部队列分配更多内存,可以提供少量、临时的缓解,但并不能消除存储后端的瓶颈。
如何配置 Jaeger UI 的认证?
Jaeger UI 不支持任何账户或角色的概念,因此无需对用户进行身份验证。如果您需要身份验证来简单地限制谁可以访问 Jaeger UI,我们建议在其前面运行反向代理,例如 HAProxy、Nginx、Keycloak 等。使用标准反向代理的优势在于它们支持与各种身份验证和单点登录服务的广泛集成,这是 Jaeger UI 永远无法匹敌的。