【学习笔记】分布式追踪Tracing (2)

一个Span代表系统中具有开始时间和执行时长的逻辑运行单元。Span之间通过嵌套或者顺序排列建立逻辑因果关系。Span可以被理解为一次方法调用, 一个程序块的调用, 或者一次RPC/数据库访问,只要是一个具有完整时间周期的程序访问,都可以被认为是一个span。每个Span包含以下的状态:

An operation name,操作名称 

A start timestamp,起始时间

A finish timestamp,结束时间

Span Tag,一组键值对构成的Span标签集合。键值对中,键必须为string,值可以是字符串,布尔,或者数字类型

Span Log,一组span的日志集合。每次log操作包含一个键值对,以及一个时间戳。键值对中,键必须为string,值可以是任意类型

SpanContext,Span上下文对象

References,Span间关系,目前定义了两种关系:ChildOf(父子,父级span某种程度上取决于子span) 和 FollowsFrom(跟随,父级节点不以任何方式依然他们子节点的执行结果)

 

SpanContext

Span上下文对象,代表跨越进程边界,传递到下级span的状态。每一个SpanContext包含以下状态:

任何一个OpenTracing的实现,都需要将当前调用链的状态(例如:trace和span的id),依赖一个独特的Span去跨进程边界传输

Baggage Items,Trace的随行数据,是一个键值对集合,它存在于trace中,也需要跨进程边界传输

OpenTracing的使用者仅仅需要,在创建span、向传输协议Inject(注入)和从传输协议中Extract(提取)时,使用SpanContext和References。

 

2. Jaeger

Jaeger是Uber开源的一款分布式追踪系统(https://github.com/jaegertracing/jaeger),兼容OpenTracing API(支持Java语言:https://github.com/jaegertracing/jaeger-client-java)。

jaeger-client:Jaeger的客户端,实现了OpenTracing的API,支持主流编程语言。客户端直接集成在应用程序中,把trace信息按指定的采样策略传递给jaeger-agent,这个过程通常被称为埋点。

jaeger-agent:一个监听在UDP端口上接收trace信息的网络守护进程,会将数据批量发送给jaeger-collector。它被设计成一个基础组件,部署到所有的宿主机上,agent将client和collector解耦,为client屏蔽路由和发现collector的细节。

jaeger-collector:负责接收jaeger-agent发送来的数据,然后异步处理,最终将数据存储到DB中。它被设计成无状态的组件,因此可以同时运行任意数量的jaeger-collector。

jaeger-query:接收查询请求,然后从DB中检索 trace信息并通过 UI 进行展示。Query是无状态的,可以启动多个实例,把它们部署在nginx这样的负载均衡器后面。

jaeger-ingester:中文名称“摄食者”,从kafka读取数据然后写到jaeger的后端存储,比如Cassandra和Elasticsearch。

【学习笔记】分布式追踪Tracing

 

分布式追踪系统大体分为三个部分,数据采集、数据持久化、数据展示。

数据采集是指在代码中埋点,设置请求中要上报的阶段,以及设置当前记录的阶段隶属于哪个上级阶段。

数据持久化则是指将上报的数据落盘存储,例如Jaeger就支持多种存储后端,可选用Cassandra或者Elasticsearch。

数据展示则是前端根据TraceId查询与之关联的请求阶段,并在界面上呈现。

 

3. dd-trace-java

dd-trace-java(https://github.com/DataDog/dd-trace-java)是Datadog开源的一个java版本的APM(应用性能管理)客户端。它依赖了jaeger-client-java中的jaeger-core,采用字节码注入技术(JavaAgent)进行埋点,支持针对不同组件(http、kafka、jdbc等)进行插件化开发。

启动入口在AgentBootstrap的premain方法:

AgentInstaller.installBytebuddyAgent:注册各种支持不同组件的埋点插件

TracerInstaller.installGlobalTracer:注册一个全局的Tracer

【学习笔记】分布式追踪Tracing

【学习笔记】分布式追踪Tracing

1 public class AgentInstaller { 2 3 public static ResettableClassFileTransformer installBytebuddyAgent(final Instrumentation inst) { 4 AgentBuilder agentBuilder = 5 new AgentBuilder.Default() 6 .disableClassFormatChanges() 7 .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION) 8 .with(new RedefinitionLoggingListener()) 9 .with(AgentBuilder.DescriptionStrategy.Default.POOL_ONLY) 10 .with(AgentTooling.poolStrategy()) 11 .with(new TransformLoggingListener()) 12 .with(new ClassLoadListener()) 13 .with(AgentTooling.locationStrategy()) 14 .ignore(any(), skipClassLoader()) 15 .or(nameStartsWith("datadog.trace.")) 16 .or(nameStartsWith("datadog.opentracing.")) 17 .or(nameStartsWith("datadog.slf4j.")) 18 .or(nameStartsWith("java.").and(not(nameStartsWith("java.util.concurrent.")))) 19 .or(nameStartsWith("com.sun.")) 20 .or(nameStartsWith("sun.").and(not(nameStartsWith("sun.net.")))) 21 .or(nameStartsWith("jdk.")) 22 .or(nameStartsWith("org.aspectj.")) 23 .or(nameStartsWith("org.groovy.")) 24 .or(nameStartsWith("com.p6spy.")) 25 .or(nameStartsWith("org.slf4j.")) 26 .or(nameContains("javassist")) 27 .or(nameContains(".asm.")) 28 .or(nameMatches("com\\.mchange\\.v2\\.c3p0\\..*Proxy")); 29 30 for (final Instrumenter instrumenter : ServiceLoader.load(Instrumenter.class)) { 31 log.info("Loading instrumentation {}", instrumenter.getClass().getName()); 32 agentBuilder = instrumenter.instrument(agentBuilder); 33 } 34 return agentBuilder.installOn(inst); 35 } 36 }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyspww.html