1,安装zipkin:https://zipkin.io/pages/quickstart.html
推荐使用docker去安装zipkin服务,下载安装执行都有了。缺点是下载要等待一段时间
2,使用php来构造tracing数据,投递给zipkin
用的包是:https://github.com/jcchavezs/zipkin-php
安装推荐使用composer,找个空目录直接执行composer命令就好
实战1:demo先跑起来
<?php require "vendor/autoload.php"; use Zipkin\Annotation; use Zipkin\Endpoint; use Zipkin\Samplers\BinarySampler; use Zipkin\TracingBuilder; use Zipkin\Reporters\Http; $endpoint = Endpoint::createFromGlobals(); $reporter = new Http(); $sampler = BinarySampler::createAsAlwaysSample(); $tracing = TracingBuilder::create() ->havingLocalEndpoint($endpoint) ->havingSampler($sampler) ->havingReporter($reporter) ->build(); $tracer = $tracing->getTracer(); $span = $tracer->newTrace(); $span->setName("encode"); $span->start(); try { usleep(100000); } finally { $span->finish(); } $tracer->flush();
执行以上脚本,打开zipkin的查看界面:127.0.0.1:9411,找到cli然后可以看到一条追踪记录。
可以看到zipkin的查看界面中多了条tracing记录。
这里需要解释下图中的东西:
1,cli:是serviceName,对应于你的服务名称(比如图片服务等)
2,执行时间:100ms,对应这次服务时间,从请求到相应是100ms;
3,encode;这个表示span的名称,span在zipkin的函数是某个节点(或者记录),和html的span有类似的含义。是个树状结构,可以有平级兄弟,和父子节点。
再次解释下图中的东西和原始数据的关系:
1,cli是serviceName,它是在这个动作中埋入的:Endpoint::createFromGlobals(),可以看到源码中有:new self(PHP_SAPI, ...);
2,执行时间:100ms,对应到usleep函数;
3,encode:是span的名称,对应的函数是setName()操作。
然后我们来分析下tracing主要做的事情:
1,在每个节点处(span)打点,初始化时设置context上下文(暂时忽略这个概念),name(span名称);
2,span节点开始时执行start操作,记录当前时间戳;
3,span节点结束时执行finish操作,记录结束时间戳;
这样就产生了一条span记录,包含:context,span-name,start-time,end-time。
然后我们再理解下context有哪些数据项。
traceId:追踪链的根节点id,刚才说span是树状结构,那么就需要个根节点id,类似于root-id;
spanId:当前span节点的id,和树的node-id是类似的;
parentId:当前span的父节点id,和树的parent-id是类似的;
context中可以设置traceId,和parentId,需要上下文传递过来,接下来有具体的例子来设置span的context。
spanId如何设置的呢?$tracer->newTrace() 这个操作是生成一个新的span节点,生成节点时会先生成TraceContext,同步会初始化spanId。
实战2:生成父子节点,生成兄弟节点
<?php require "vendor/autoload.php"; use Zipkin\Annotation; use Zipkin\Endpoint; use Zipkin\Samplers\BinarySampler; use Zipkin\TracingBuilder; use Zipkin\Reporters\Http; $endpoint = Endpoint::createFromGlobals(); $endpoint = Endpoint::create("php-demo"); $reporter = new Http(); $sampler = BinarySampler::createAsAlwaysSample(); $tracing = TracingBuilder::create() ->havingLocalEndpoint($endpoint) ->havingSampler($sampler) ->havingReporter($reporter) ->build(); $tracer = $tracing->getTracer(); $span = $tracer->newTrace(); $span->setName("encode"); $span->start(); try { $parentContext = $span->getContext(); $childSpan = $tracer->newChild($parentContext); $childSpan->setName("encode1"); $childSpan->start(); usleep(100000); $childSpan->finish(); $childSpan2 = $tracer->newChild($parentContext); $childSpan2->setName("encode2"); $childSpan2->start(); usleep(100000); $childSpan2->finish(); } finally { $span->finish(); } $tracer->flush();
zipkin的追踪结果:
可以看到有三个span,encode是根节点,有两个儿子(encode1和encode2)。
重点就是newChild($parentContext),把父节点的信息传入到新的span节点就能实现两者之间的对应关系了。
相关的文章链接:
zipkin核心数据结构:https://my.oschina.net/guol/blog/871678
zipkin api接口:https://zipkin.io/zipkin-api/#/default/post_spans
zipkin api文档:https://github.com/openzipkin/zipkin-api/blob/master/zipkin-api.yaml#L56
jwt入门介绍:https://www.cnblogs.com/zaixiuxing/p/6005968.html
golang body长度:https://stackoverflow.com/questions/43021058/golang-read-request-body