jaeger链路追踪php,使用 Jaeger 完成服务间的链路追踪

本文介绍了如何在 PHP 服务中使用 Jaeger 进行链路追踪,详细讲解了 Jaeger 的体系结构、追踪信息概念以及如何在 Node.js 和 Go 服务间实现追踪。通过示例展示了如何在不同服务中配置 Jaeger 客户端,创建和传播 Span,从而在复杂的分布式系统中进行监控和问题排查。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

世上本没有路,走的人多了,便变成了路 -- 鲁迅

87992e30fd80df1140155a42fcb9a7a5.png

本次讨论的话题就是需要在各个服务之间踏出条"路",让 bug 有"路"可循。

至于为什么用 jaeger... 这个支持多语言方案算么?遵循 opentracing 规范算么?开箱即用算么?还有更多?

至于为什么遵循 opentracing 规范的好... 这个...杠精同学,文末地址可参考

反正先撸袖开干...

了解 Jaeger

使用之前先了解:

Jaeger: open source, end-to-end distributed tracing

Jaeger: 开源的、分布式系统的端到端追踪

Monitor and troubleshoot transactions in complex distributed systems

在复杂的分布式系统之间做监控及问题排查的事务处理。

jaeger 体系和流程如下图

0815fcf6210342cb48bef023c84cdd6c.png

jaeger-client (OpenTracing API 各语言的实现,用于在应用中塞入信息采集点)

jaeger-agent (负责发送的进程,对 spans 进行处理并发送给 collector,监听 spans 的 UDP 发送。设计这层是为了作为基础组件部署到主机上,从 client 中抽象出了 collector 的发现和路由。注意:1.这层应该是部署在应用本地;2.如果配置报告的 endpoint,则直接将 spans 发送到 collector,不需要 agent。)

jaeger-collector (收集追踪 spans,并通过管道对追踪数据进行处理。当前的管道支持追踪的验证、索引、转换,最后存储数据)

data store (追踪信息的存储)

jaeger-query (从存储中检索追踪信息并通过 UI 展示)

jaeger-ui (UI 展示层,基于 React)

注意:jaeger 的存储是可插拔组件,目前支持 Cassandra、ElasticSearch 和 Kafka。

基于以上的体系结构,本文关注点在 jaeger-client 部分,怎么实现服务之间和服务内部的 tracing。

了解追踪信息

Span:追踪中的逻辑单元,比如一次请求的过程/一个函数的执行,包含操作名称、开始时间、持续时间。

SpanContext:表示需要传播到下游 Spans 和跨应用/进程的 Span 数据,可以简单理解为串在各个系统里的统一标识对象。

Baggage:字符串组成的键值对,和 Span/SpanContext 互相关联,会在所有的下游 Spans 中进行传播。(可以做一些强大的功能,如在整个链路夹带数据,使用成本高,小心使用)

Tracer:项目中的追踪实例,追踪项目里数据变化/函数执行的过程,可以认为是一个定向非循环的 spans 的集合图。

Tracer 和 Span 如下图:

5aacecc9401f6df40d89a3508df73412.png

对于 jaeger-ui 效果如下图:

f1bbf1000ae56057af99c958f194ab41.png

jaeger-client 是 opentracing 的实现,于是 jaeger-client api 几乎等同于 opentracing api。

Api 和配置参考

本文以 Nodejs 为主,Go 为辅(因为当前刚好涉及到这两种服务的链路追踪方案 )。

这里大致介绍一下 Configuration/Tracer/Span ,以便实现一个基础的 tracing 。

Configuration

{

serviceName: "string",

disable: "boolean",

sampler: {

type: "string", // required

param: "number", // required

hostPort: "string",

host: "string",

port: "number",

refreshIntervalMs: "number"

},

reporter: {

logSpans: "boolean",

agentHost: "string",

agentPort: "number",

collectorEndpoint: "string",

username: "string",

password: "string",

flushIntervalMs: "number"

},

throttler: {

host: "string",

port: "number",

refreshIntervalMs: "number"

}

}

Tracer

{

objects: {

_tags: "object", // tags 信息,含 jaeger-version/hostname/ip/client-uuid

_metrics: "object", // Metrics 度量实例

_serviceName: "string", // 服务名称

_reporter: "object", // 提交实例

_sampler: "object", // 采样器实例

_logger: "object", // 日志实例,默认 NullLogger

_baggageSetter: "object", // BaggageSetter 实例

_debugThrottler: "object", // DefaultThrottler 配置实例

_injectors: "object", // 注入器列表

_extractors: "object", // 提取器列表

_process: "object" // process 信息,含 serviceName/tags

},

// 文件位置 ./jaeger-client-node/blob/master/src/tracer.js

methods: {

_startInternalSpan: "void", // 创建基础 span ,供 startSpan 方法调用 / params: spanContext(SpanContext) operationName(string) startTime(number) userTags(any) internalTags(any) parentContext?(SpanContext) rpcServer(boolean) references(Array) / retuen Span

_report: "void", // 发起数据提交,提交到jaeger后端 / params: span(Span)

registerInjector: "void", // 向 tracer 注入 "注入 SpanContext 内容的方式" / params: format(string) injector(Injector)

registerExtractor: "void", // 向 tracer 注入 "提取 SpanContext 内容的方式" / params: format(string) extractor(Extractor)

startSpan: "void", // 创建一个 Span / params: operationName(string) options?:{ operationName(string) childOf(SpanContext) references(Array) tags(object) startTime(number) }

inject: "void", // 将 SpanContext 注入到序列化格式的 carrier 中 / params: SpanContext(SpanContext) format(string) carrier(any)

extract: "void", // 从序列化格式的 carrier 中提取 SpanContext / params: format(string)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值