怎么通过接口获取zipkin里面的 dynatraceeId

分布式跟踪系统(二):Zipkin的Span模型 - 开源软件 - ITeye资讯
在《分布式跟踪系统(一):Zipkin的背景和设计》一文中,已经初步的介绍了Zipkin的设计和数据模型,本文将详细介绍Zipkin的Span模型,以及其他“另类”Span模型的设计。
这里多一句嘴,其实专业点的叫法应该是分布式追踪系统——Distributed Tracing System,跟踪比较适合用于人的场景,比如某人被跟踪了,而追踪更适合用于计算机领域。然并卵?本文将继续使用“跟踪”。
Zipkin的Span模型几乎完全仿造了Dapper中Span模型的设计,我们知道,Span用来描述一次RPC调用,所以一个RPC调用只应该关联一个spanId(不算父spanId),Zipkin中的Span主要包含三个数据部分:
基础数据:用于跟踪树中节点的关联和界面展示,包括traceId、spanId、parentId、name、timestamp和duration,其中parentId为null的Span将成为跟踪树的根节点来展示,当然它也是调用链的起点,为了节省一次spanId的创建开销,让顶级Span变得更明显,顶级Span中spanId将会和traceId相同。timestamp用于记录调用的起始时间,而duration表示此次调用的总耗时,所以timestamp+duration将表示成调用的结束时间,而duration在跟踪树中将表示成该Span的时间条的长度。需要注意的是,这里的name用于在跟踪树节点的时间条上展示。
Annotation数据:用来记录关键事件,只有四种,cs(Client Send)、sr(Server Receive)、ss(Server Send)、cr(Client Receive),所以在Span模型中,Annotation是一个列表,长度最多为4。每种关键事件包含value、timestamp和endpoint,value就是cs、sr、ss和cr中的一种,timestamp表示发生的时间,endpoint用于记录发生的机器(ip)和服务名称(serviceName)。可以很自然的想到,cs和cr、sr和ss的机器名称是相同的,为了简单起见,cs和cr的服务名称可以一样,sr和ss的服务名称可以一样。Annotation数据主要用于用户点击一个Span节点时展示具体的Span信息。
BinaryAnnotation数据:我们并不满足在跟踪树上只展示调用链的时间信息,如果需要绑定一些业务数据(日志)的话,可以将数据写入BinaryAnnotation中,它的结构和Annotation数据一模一样,在Span中也是一个列表,这里就不再阐述,但BinaryAnnotation中不宜放太多数据,不然将导致性能和体验的下降。
现在我们已经了解了一个Span的内部结构,但这是Span的最终形态,也就是说这是Zipkin在收集完数据并展现给用户锁看到的最终形态。Span的产生是“不完整”的,Zipkin服务端需要将搜集的有同一个traceId和spanId的Span组装成最终完整的Span,也就是上面说到的Span。可能这样说不太直观,我们沿用下图来举例说明:
zipkin数据收集(图1)
上图在我的第一篇Zipkin博文中已经用到过,这里不再详细阐述,我们直接看该图对应的内部Span细节图:
span数据流转(图2)
注意,上图并没有显示Span的所有细节(比如name和binaryAnnotation等),但这并不影响我们分析问题。上图的①和⑥是一次完整的RPC调用,它发生在服务器0和服务器1之间,显而易见的是,用于描述该RPC调用的Span的spanId是1000,所以,这是同一个Span的,只是它的数据来源于两台不同的服务器(应用):服务器0和服务器1。往低层说,该Span由两条跟踪日志表示,一条在服务器0上被采集,另一条在服务器1上被采集,他们的Span的traceId、spanId和parentSpanId都是一样的!而且该Span将成为跟踪树中的顶节点,因为他们的parentSpanId为null。对于步骤①来说,服务器1上的sr减去服务器0上的cs的时间就是约等于网络耗时(这里忽略不同服务器时钟的差异),同理,对于其他步骤,sr-cs和cr-ss得到的都是网络耗时。我们接着看请求步骤②和④,从跟踪树的层次来说他们属于①下的子调用,所以它们的parentSpanId就是①的1000。步骤②和④都会分别产生一个spanId(上面的),所以如上图,看似一次简单的RPC过程,其实共产生了6条Span日志,它们将在Zipkin服务端组装成3个Span。
那么,问题来了,此次调用在服务器1上出现了3个spanId:1000、,如果我想记录服务器1上和此次调用的业务数据(通过BinaryAnnotation来记录),是将这些数据绑定到哪个Span上呢?如果让我们选择,我们肯定选择1000,因为服务器1上此次请求中调用下游的服务是不确定的(虽然图中只画了服务器2和服务器3),有可能它会调用下游的十几个服务,产生十几个spanId,相对而将业务数据言绑定到这些Span的父Span(1000)上似乎更合理。并且在产生业务日志时,有可能还没开始进行下游调用,所以也只能绑定在1000上。
我们先来看看图2中的Span在Zipkin的跟踪树中大概会显示成什么样子,如下图:
Zipkin跟踪树(图3)
当然,部分数据会和图2中的不一样(比如timestamp和duration),但并不影响我们分析问题。可以看出,在Zipkin中最小的时间单位是微秒(千分之一毫秒),所以图3中展现的此次RPC总耗时为96.2ms,有人刚开始看肯定会疑问,为啥经历过四个服务器的RPC调用在图中的跟踪树中只有三个节点?因为在跟踪树中, 一个Span(准确的说是一个spanId)只会展现成一个树节点,比如树节点Service1表示了Gateway(服务器0)调用Service1(服务器1)的过程,树节点Service2表示Service1(服务器1)调用Service2(服务器2)的过程。有人肯定会问,对于树节点Service1,我们记录了cs、sr、ss和cr四个时间,但时间条的显示只用到了cs和cr(耗时duration=cr-cs),那么sr和ss去哪了(别忘了我们可以通过sr-cs和cr-ss计算网络耗时)?我们可以单击Serice1节点,于是打开了Span的详细信息(Span的annotation和binaryAnnotation数据),如下图:
Span详细信息(图4)
Relative Time 是相对时间,表示此事件(cs、sr、ss、cr)已经发生了多久(相对起始时间点),因为Service1是顶级节点,所以第一行的Relative Time是空的,于是乎,该请求的网络耗时(Gateway请求Service1)为10ms,应答的网络耗时(Service1应答Gateway)为96.3-94.3=2ms,所以,从Zipkin目前的页面设计来看,网络耗时只能通过点树节点的详细信息页面来看,而且还需要做简单的计算,并不直观。淘宝的鹰眼系统通过在时间条上分为两种颜色来显示,使用了cs、sr、ss和cr四个时间戳,更加直观。
可能大多数人觉得对于跨四个系统的RPC调用却只显示三个节点,有些别扭。对于图1的调用,我们更希望是Gateway的节点下挂着一个Service1节点,表示Gateway调用了Service1,而Service1节点下挂着Service2和Service3两个节点,表示Service1调用了Service2和Service3,这样更容易理解。于是我们想到了在RPC链路中经过某个节点(服务器应用),那么这个节点就产生几个spanId,这样的话,在图中RPC经过Gateway、Service1、Service2和Service3各一次,所以一共将产生4个spanId(Zipkin在图2中只产生3个spanId),这样就变成了spanId和节点个数一致(前提是RPC链路中只经过每个节点各一次,也就是节点之间没有相互依赖)。这样设计Span数据的流转如下图:
修改过的Span数据流转(图5)
图5中可以很明显的看出,还是6条Span的日志,每个服务器节点上会产生一个spanId(1000、1001、),而不是像原有图2一样只有3个spanId。这样还有一个好处,就是RPC调用时只需要传递traceId和spanId,而不是像Zipkin的设计那样,需要传递traceId、spanId还有parentSpanId。但立马我们就发现了问题,在图5的服务器1的节点上,1001的spanId记录了两套cs和cr,则也导致了无法区分哪个对应的是调用服务器2,哪个对应的是调用服务器3,所以,这种设计方案直接被否决了。
于是我们换一种思路,不采用spanId和parentSpanId,换成spanId和childSpanId,childSpanId由父亲节点生成并传递给子节点,如下图:
新的Span数据流转(图6)
&!--StartFragment--& &!--EndFragment--&
从图6可以看到明显的变化,不再有parentSpanId,而使用了childSpanId,这样RPC之间传递的就是traceId和childSpanId,这也直接解决了图5中所遇到的问题。虽然图5和图6的设计违背了一次RPC调用由一个spanId的数据来进行维护的设计理念,但确实在跟踪树的界面展示上更容易让人接受和理解(树节点和服务器节点对应),而且还减少了RCP间的数据传送,何乐而不为?SpringCloud(十二):分布式链路跟踪Sleuth与Zipkin【Finchley版】发表于|随着业务发展,系统拆分导致系统调用链路愈发复杂一个前端请求可能最终需要调用很多次后端服务才能完成,当整个请求变慢或不可用时,我们是无法得知该请求是由某个或某些后端服务引起的,这时就需要解决如何快读定位服务故障点,以对症下药。于是就有了分布式系统调用跟踪的诞生。现今业界分布式服务...
Spring Cloud(十二):分布式链路跟踪 Sleuth 与 Zipkin【Finchley 版】
随着业务发展,系统拆分导致系统调用链路愈发复杂一个前端请求可能最终需要调用很多次后端服务才能完成,当整个请求变慢或不可用时,我们是无法得知该请求是由某个或某些后端服务引起的,这时就需要解决如何快读定位服务故障点,以对症下药。于是就有了分布式系统调用跟踪的诞生。
现今业界分布式服务跟踪的理论基础主要来自于 Google 的一篇论文《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》,使用最为广泛的开源实现是 Twitter 的 Zipkin,为了实现平台无关、厂商无关的分布式服务跟踪,CNCF 发布了布式服务跟踪标准 Open Tracing。国内,淘宝的 “鹰眼”、京东的 “Hydra”、大众点评的 “CAT”、新浪的 “Watchman”、唯品会的 “Microscope”、窝窝网的 “Tracing” 都是这样的系统。
Spring Cloud Sleuth 也为我们提供了一套完整的解决方案。在本章中,我们将详细介绍如何使用 Spring Cloud Sleuth + Zipkin 来为我们的微服务架构增加分布式服务跟踪的能力。
Spring Cloud Sleuth
一般的,一个分布式服务跟踪系统主要由三部分构成:
根据系统大小不同,每一部分的结构又有一定变化。譬如,对于大规模分布式系统,数据存储可分为实时数据和全量数据两部分,实时数据用于故障排查(Trouble Shooting),全量数据用于系统优化;数据收集除了支持平台无关和开发语言无关系统的数据收集,还包括异步数据收集(需要跟踪队列中的消息,保证调用的连贯性),以及确保更小的侵入性;数据展示又涉及到数据挖掘和分析。虽然每一部分都可能变得很复杂,但基本原理都类似。
服务追踪的追踪单元是从客户发起请求(request)抵达被追踪系统的边界开始,到被追踪系统向客户返回响应(response)为止的过程,称为一个trace。每个 trace 中会调用若干个服务,为了记录调用了哪些服务,以及每次调用的消耗时间等信息,在每次调用服务时,埋入一个调用记录,称为一个span。这样,若干个有序的 span 就组成了一个 trace。在系统向外界提供服务的过程中,会不断地有请求和响应发生,也就会不断生成 trace,把这些带有 span 的 trace 记录下来,就可以描绘出一幅系统的服务拓扑图。附带上 span 中的响应时间,以及请求成功与否等信息,就可以在发生问题的时候,找到异常的服务;根据历史数据,还可以从系统整体层面分析出哪里性能差,定位性能优化的目标。
Spring Cloud Sleuth 为服务之间调用提供链路追踪。通过 Sleuth 可以很清楚的了解到一个服务请求经过了哪些服务,每个服务处理花费了多长。从而让我们可以很方便的理清各微服务间的调用关系。此外 Sleuth 可以帮助我们:
耗时分析: 通过 Sleuth 可以很方便的了解到每个采样请求的耗时,从而分析出哪些服务调用比较耗时;
可视化错误: 对于程序未捕捉的异常,可以通过集成 Zipkin 服务界面上看到;
链路优化: 对于调用比较频繁的服务,可以针对这些服务实施一些优化措施。
Spring Cloud Sleuth 可以结合 Zipkin,将信息发送到 Zipkin,利用 Zipkin 的存储来存储信息,利用 Zipkin UI 来展示数据。
这是 Spring Cloud Sleuth 的概念图:
Zipkin 是 Twitter 的一个开源项目,它基于 Google Dapper 实现,它致力于收集服务的定时数据,以解决微服务架构中的延迟问题,包括数据的收集、存储、查找和展现。我们可以使用它来收集各个服务器上请求链路的跟踪数据,并通过它提供的 REST API 接口来辅助我们查询跟踪数据以实现对分布式系统的监控程序,从而及时地发现系统中出现的延迟升高问题并找出系统性能瓶颈的根源。除了面向开发的 API 接口之外,它也提供了方便的 UI 组件来帮助我们直观的搜索跟踪信息和分析请求链路明细,比如:可以查询某段时间内各用户请求的处理时间等。Zipkin 提供了可插拔数据存储方式:In-Memory、MySql、Cassandra 以及 Elasticsearch。接下来的测试为方便直接采用 In-Memory 方式进行存储,生产推荐 Elasticsearch。
上图展示了 Zipkin 的基础架构,它主要由 4 个核心组件构成:
Collector:收集器组件,它主要用于处理从外部系统发送过来的跟踪信息,将这些信息转换为 Zipkin 内部处理的 Span 格式,以支持后续的存储、分析、展示等功能。
Storage:存储组件,它主要对处理收集器接收到的跟踪信息,默认会将这些信息存储在内存中,我们也可以修改此存储策略,通过使用其他存储组件将跟踪信息存储到数据库中。
RESTful API:API 组件,它主要用来提供外部访问接口。比如给客户端展示跟踪信息,或是外接系统访问以实现监控等。
Web UI:UI 组件,基于 API 组件实现的上层应用。通过 UI 组件用户可以方便而有直观地查询和分析跟踪信息。
Zipkin 分为两端,一个是 Zipkin 服务端,一个是 Zipkin 客户端,客户端也就是微服务的应用。客户端会配置服务端的 URL 地址,一旦发生服务间的调用的时候,会被配置在微服务里面的 Sleuth 的监听器监听,并生成相应的 Trace 和 Span 信息发送给服务端。发送的方式主要有两种,一种是 HTTP 报文的方式,还有一种是消息总线的方式如 RabbitMQ。
不论哪种方式,我们都需要:
一个 Eureka 服务注册中心,这里我们就用之前的eureka项目来当注册中心。
一个 Zipkin 服务端。
两个微服务应用,trace-a和trace-b,其中trace-a中有一个 REST 接口/trace-a,调用该接口后将触发对trace-b应用的调用。
方式一:HTTP
在 Spring Cloud Sleuth 中对 Zipkin 的整合进行了自动化配置的封装,所以我们可以很轻松的引入和使用它。
Zipkin 服务端
关于 Zipkin 的服务端,在使用 Spring Boot 2.x 版本后,官方就不推荐自行定制编译了,反而是直接提供了编译好的 jar 包来给我们使用,详情请看upgrade to Spring Boot 2.0 NoClassDefFoundError UndertowEmbeddedServletContainerFactory · Issue #1962 · openzipkin/zipkin · GitHub
并且以前的@EnableZipkinServer也已经被打上了@Deprecated
If you decide to make a custom server, you accept responsibility for troubleshooting your build or configuration problems, even if such problems are a reaction to a change made by the OpenZipkin maintainers. In other words, custom servers are possible, but not supported.
EnableZipkinServer.javagithub.com/openzipkin/zipkin/blob/master/zipkin-server/src/main/java/zipkin/server/EnableZipkinServer.java
简而言之就是:私自改包,后果自负。
所以官方提供了一键脚本
curl -sSL https://zipkin.io/quickstart.sh | bash -sjava -jar zipkin.jar
如果用 Docker 的话,直接
docker run -d -p
openzipkin/zipkin
任一方式启动后,访问http://localhost:9411/zipkin/就能看到如下界面,嗯还有汉化看起来不错
至此服务端就 OK 了。
微服务应用
创建两个基本的 Spring Boot 工程,名字分别为trace-a和trace-b。
两个工程的 pom.xml 均引入以下依赖坐标
12345678910111213141516在Go 1.7,我们有一个新包/ HTTP / httptrace提供了一个方便的机制,观察一个HTTP请求时会发生什么。在本文中,将说明如何能在分布式跟踪的情况下被使用,通过使用跟踪观察一个客户端和一个服务器,并可视化的结果显示在 。什么是分布式跟踪和OpenTracing?分布式跟踪是监测和分析微服务架构系统,导出结果到为X-TRACE,如谷歌的Dapper和Twitter的Zipkin 。 它们的底层原理是分布式环境传播 ,其中涉及的某些元数据与进入系统的每个请求相关联,并且跨线程和进程边界传播元数据跟随请求进出各种微服务调用。 如果我们为每个入站请求分配一个唯一的ID并将其作为分布式上下文的一部分,那么我们可以将来自多个线程和多个进程的各种性能分析数据合并到统一的表示我们系统执行请求的“跟踪”中。分布式跟踪需要使用Hook钩子和上下文传播机制来测试应用程序代码(或其使用的框架)。 当我们在Uber开始构建我们的分布式跟踪系统时,我们很快意识到,没有良好的API为开发人员提供在编程语言之间内部一致性,那就无法绑定到指定的跟踪系统。原来,不只是我们有这种思维,2015年10月一个新的社区形成,催生了OpenTracing API,一个开放的,厂商中立的,与语言无关的分布式跟踪标准。你可以阅读更多关于Ben Sigelman有关OpenTracing动机和设计原理背后的文章 。让我们看看代码:import (
"net/http"
"net/http/httptrace"
"github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/log"
"golang.org/x/net/context")// We will talk about this latervar tracer opentracing.Tracerfunc AskGoogle(ctx context.Context) error {
// retrieve current Span from Context
var parentCtx opentracing.SpanContext
parentSpan := opentracing.SpanFromContext(ctx);
if parentSpan != nil {
parentCtx = parentSpan.Context()
// start a new Span to wrap HTTP request
span := tracer.StartSpan(
"ask google",
opentracing.ChildOf(parentCtx),
// make sure the Span is finished once we're done
defer span.Finish()
// make the Span current in the context
ctx = opentracing.ContextWithSpan(ctx, span)
// now prepare the request
req, err := http.NewRequest("GET", "http://google.com", nil)
if err != nil {
return err
// attach ClientTrace to the Context, and Context to request
trace := NewClientTrace(span)
ctx = httptrace.WithClientTrace(ctx, trace)
req = req.WithContext(ctx)
// execute the request
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
// Google home page is not too exciting, so ignore the result
res.Body.Close()
return nil}
这里有几点要注意:1.回避了tracer变量初始化的问题。2.AskGoogle函数接受context.Context对象。这是为开发分布式应用程序的Go推荐方式,因为上下文对象是要让分布式环境传播。3.我们假设上下文已经包含父跟踪Span。 OpenTracing API中的Span是用于表示由微服务执行的工作单元。HTTP调用就是可以包裹在跟踪Span中的操作案例。 当我们运行处理入站请求的服务时,服务通常会为每个请求创建一个跟踪范围,并将其存储在上下文中,以便在对另一个服务进行下游调用时可用(在我们的示例中为google.com )。4.我们启动一个新的子Span来包装出站HTTP调用。 如果父Span缺失,这是好方法。5.最后,在做出HTTP请求之前,我们实例化一个ClientTrace并将其附加到请求。ClientTrace结构是httptrace的基本构建块 。它允许我们在HTTP请求的生命周期内注册将由HTTP客户端执行的回调函数。 例如,ClientTrace结构有这样的方法:type ClientTrace struct {...
// DNSStart is called when a DNS lookup begins.
DNSStart func(DNSStartInfo)
// DNSDone is called when a DNS lookup ends.
DNSDone func(DNSDoneInfo)...} 我们在NewClientTrace方法中创建这个结构的一个实例:func NewClientTrace(span opentracing.Span) *httptrace.ClientTrace {
trace := &clientTrace{span: span}
return &httptrace.ClientTrace {
DNSStart: trace.dnsStart,
trace.dnsDone,
}}// clientTrace holds a reference to the Span and// provides methods used as ClientTrace callbackstype clientTrace struct {
span opentracing.Span}func (h *clientTrace) dnsStart(info httptrace.DNSStartInfo) {
h.span.LogKV(
log.String("event", "DNS start"),
log.Object("host", info.Host),
)}func (h *clientTrace) dnsDone(httptrace.DNSDoneInfo) {
h.span.LogKV(log.String("event", "DNS done"))}
我们为DBBStart和DNSDone事件实现注册两个回调函数,通过私有结构clientTrace保有一个指向跟踪Span。 在回调方法中,我们使用Span的键值记录API来记录事件的信息,以及Span本身隐含捕获的时间戳。你不是说关于UI的东西吗?OpenTracing API的工作方式是,一旦调用跟踪Span的Finish()方法,Span捕获的数据将发送到跟踪系统后端,通常在后台异步发送。然后,我们可以使用跟踪系统UI来查找跟踪并在时间线上将其可视化。 然而,上述例子只是为了说明使用OpenTracing与httptrace的原理。对于真正的工作示例,我们将使用现有的库https://github.com/opentracing-contrib/go-stdlib 。 使用这个库我们的客户端代码不需要担心跟踪实际的HTTP调用。但是,我们仍然希望创建一个顶层跟踪Span来表示客户端应用程序的整体执行,并记录任何错误。package mainimport (
"io/ioutil"
"net/http"
"github.com/opentracing-contrib/go-stdlib/nethttp"
"github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/ext"
otlog "github.com/opentracing/opentracing-go/log"
"golang.org/x/net/context")func runClient(tracer opentracing.Tracer) {
// nethttp.Transport from go-stdlib will do the tracing
c := &http.Client{Transport: &nethttp.Transport{}}
// create a top-level span to represent full work of the client
span := tracer.StartSpan(client)
span.SetTag(string(ext.Component), client)
defer span.Finish()
ctx := opentracing.ContextWithSpan(context.Background(), span)
req, err := http.NewRequest(
fmt.Sprintf("http://localhost:%s/", *serverPort),
if err != nil {
onError(span, err)
req = req.WithContext(ctx)
// wrap the request in nethttp.TraceRequest
req, ht := nethttp.TraceRequest(tracer, req)
defer ht.Finish()
res, err := c.Do(req)
if err != nil {
onError(span, err)
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
onError(span, err)
fmt.Printf("Received result: %s\n", string(body))}func onError(span opentracing.Span, err error) {
// handle errors by recording them in the span
span.SetTag(string(ext.Error), true)
span.LogKV(otlog.Error(err))
log.Print(err)} 上面的客户端代码调用本地服务器。 让我们实现它。 package mainimport (
"net/http"
"github.com/opentracing-contrib/go-stdlib/nethttp"
"github.com/opentracing/opentracing-go")func getTime(w http.ResponseWriter, r *http.Request) {
log.Print("Received getTime request")
t := time.Now()
ts := t.Format("Mon Jan _2 15:04:05 2006")
io.WriteString(w, fmt.Sprintf("The time is %s", ts))}func redirect(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r,
fmt.Sprintf("http://localhost:%s/gettime", *serverPort), 301)}func runServer(tracer opentracing.Tracer) {
http.HandleFunc("/gettime", getTime)
http.HandleFunc("/", redirect)
log.Printf("Starting server on port %s", *serverPort)
http.ListenAndServe(
fmt.Sprintf(":%s", *serverPort),
// use nethttp.Middleware to enable OpenTracing for server
nethttp.Middleware(tracer, http.DefaultServeMux))} 注意,客户端向根端点“/”发出请求,但服务器将其重定向到“/ gettime”端点。 这样做允许我们更好地说明如何在跟踪系统中捕获跟踪。[该贴被banq于 09:00修改过]
b]安装运行在这篇文章中使用的所有源代码可在上 。 假设你有一个本地安装的Go 1.7,以及一个运行Docker,我们将用来运行Zipkin服务器。该演示项目使用glide进行依赖管理,请先安装它。 例如,在Mac OS上,您可以:
$ brew install glide 然后获取演示代码,构建并运行它: $ go get github.com/yurishkuro/opentracing-go-nethttp-demo$ cd $GOPATH/src/github.com/yurishkuro/opentracing-go-nethttp-demo$ glide install# ... lots of output ...$ go build .$ ./opentracing-go-nethttp-demo 00:10:54 Starting server on port 8000 现在在另一个终端,让我们开始Zipkin服务器 $ docker run -d -p 10-9411 openzipkin/zipkin:1.12.0Unable to find image 'openzipkin/zipkin:1.12.0' locally1.12.0: Pulling from openzipkin/zipkin4d06f2521e4f: Already exists93bf0c6c4f8d: Already existsa3ed95caeb02: Pull complete3db054dce565: Pull complete9cc214bea7a6: Pull completeDigest: sha256:bf60e4b0ba064b3febf08ff640d657b1f798b6b87c40Status: Downloaded newer image for openzipkin/zipkin:1.12.0dac0b492ff4f52ff13a0dda67cb044f 如果你没有Docker,另一种运行Zipkin服务器的方法是直接从jar开始:
$ wget -O zipkin.jar'https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=LATEST&c=exec'
$ java -jar zipkin.jar 打开UI: http://localhost:9411/请注意,屏幕UI界面中服务名称下拉列表为空,因为我们还没有生成任何跟踪。现在打开另一个终端并运行:$ cd $GOPATH/src/github.com/yurishkuro/opentracing-go-nethttp-demo$ ./opentracing-go-nethttp-demo -actor clientReceived result: The time is Thu Oct
6 00:23:22 2016如果您重新加载UI页面,您应该会在第一个下拉列表中看到“客户端”。。。。。补充,之前提到跟踪变量初始化问题,tracer是是OpenTracing API的实际实现。 在我的例子用了https://github.com/uber/jaeger-client-go ,这是来自Jaeger的开源项目,是Uber的分布式跟踪系统的与OpenTracing兼容的客户端库。我们计划在2016年年底之前开源后端和UI。这个例子中的主程序看起来像这样: package mainimport (
"github.com/uber/jaeger-client-go"
"github.com/uber/jaeger-client-go/transport/zipkin")var (
zipkinURL = flag.String("url",
"http://localhost:9411/api/v1/spans", "Zipkin server URL")
serverPort = flag.String("port", "8000", "server port")
= flag.String("actor", "server", "server or client"))const (
server = "server"
client = "client")func main() {
flag.Parse()
if *actorKind != server && *actorKind != client {
log.Fatal("Please specify '-actor server' or '-actor client'")
// Jaeger tracer can be initialized with a transport that will
// report tracing Spans to a Zipkin backend
transport, err := zipkin.NewHTTPTransport(
*zipkinURL,
zipkin.HTTPBatchSize(1),
zipkin.HTTPLogger(jaeger.StdLogger),
if err != nil {
log.Fatalf("Cannot initialize HTTP transport: %v", err)
// create Jaeger tracer
tracer, closer := jaeger.NewTracer(
*actorKind,
jaeger.NewConstSampler(true), // sample all traces
jaeger.NewRemoteReporter(transport, nil),
if *actorKind == server {
runServer(tracer)
runClient(tracer)
// Close the tracer to guarantee that all spans that could
// be still buffered in memory are sent to the tracing backend
closer.Close()}Jaeger跟踪系统本身不同于Zipkin,但是我们目前使用的是Zipkin兼容的Thrift数据模型,它允许我使用Zipkin服务器来显示跟踪。结论我们使用几个组件的组合来说明跨过进程边界HTTP请求的简单跟踪,并深入了解实际的HTTP请求执行:1.标准的net/http/httptrace package,2.https://github.com/opentracing-contrib/go-stdlib instrumentation library,3.Jaeger Go client https://github.com/uber/jaeger-client-go that implements OpenTracing API, and4.Zipkin server and UI from https://github.com/openzipkin/zipkin.本案例演示源码:https://github.com/yurishkuro/opentracing-go-nethttp-demo.
企业级软件架构解决之道
如有意见请与我们联系 Powered by JdonFramework

我要回帖

更多关于 尿检trace是什么意思 的文章

 

随机推荐