Jaeger
Jaeger是一个基于opentracing规范的链路追踪工具,官方地址:https://www.jaegertracing.io/
jaeger架构
jaeger分为5个模块,分别为:
1:Jaeger-client
jaeger-client即是代码层客户端,我们通过引入sdk,通过调用代码,将数据传输到agent层
2:Jaeger-Agent
jaeger-agent将client的数据收集,然后批量上传到Collector
3:Jaeger-Collector
将agent的数据进行收集,处理,索引,然后存储到数据库中
4:Data Store
最终存储链路数据,支持Cassandra,Elasticsearch,Kafka 和内存存储(生产环境不建议)方式
5:Query&UI
数据查询和展现层
6:jaeger-ingester
直接将kafka数据写入到数据存储端
安装
安装方式有很多,本文将使用docker Ubuntu环境手动安装,觉得麻烦的可以通过docker拉取镜像,一次性安装:
docker pull jaegertracing/all-in-one:1.12 docker run -d --name jaeger \ -e COLLECTOR\_ZIPKIN\_HTTP_PORT=9411 \ -p 5775:5775/udp \ -p 6831:6831/udp \ -p 6832:6832/udp \ -p 5778:5778 \ -p 16686:16686 \ -p 14268:14268 \ -p 9411:9411 \ jaegertracing/all-in-one:1.12
由上面的架构可看出,Jaeger只需要安装collector和query&ui就可以直接运行了,客户端不通过agent,直接到收集器
首先运行一个Ubuntu:
docker run -itd --name=jaeger-study \ -p 5775:5775/udp \ -p 6831:6831/udp \ -p 6832:6832/udp \ -p 5778:5778 \ -p 16686:16686 \ -p 14268:14268 \ -p 9411:9411 \ ubuntu bash docker exec -it jaeger-study bash
目前不清楚开放这些端口有啥用,先开着以备不时之需
初始化Ubuntu 包管理:
apt-get update apt-get install -y wget
下载二进制执行包:
二进制包下载地址:https://github.com/jaegertracing/jaeger/releases/
wget https://github.com/jaegertracing/jaeger/releases/download/v1.32.0/jaeger-1.32.0-linux-amd64.tar.gz
解压后:
root@8f0790b17e84:/tmp/jaeger-1.32.0# tar -zvxf jaeger-1.32.0-linux-amd64.tar.gz jaeger-1.32.0-linux-amd64/ jaeger-1.32.0-linux-amd64/example-hotrod jaeger-1.32.0-linux-amd64/jaeger-ingester jaeger-1.32.0-linux-amd64/jaeger-collector jaeger-1.32.0-linux-amd64/jaeger-agent jaeger-1.32.0-linux-amd64/jaeger-query jaeger-1.32.0-linux-amd64/jaeger-all-in-one
启动elasticsearch
docker pull elasticsearch:7.8.0 docker run -itd -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" --name elastic_search elasticsearch:7.8.0
启动elasticsearch成功后,需要与Jaeger 容器互通,通过创建个network实现:
(base) tioncico@appledeMacBook-Pro ~ % docker network create jaeger_network ceec8b0ea1f40f12c0d7f7e3d2e4ee386351d8cb57d3203da8f4705b825aefd8 (base) tioncico@appledeMacBook-Pro ~ % docker network connect jaeger_network jaeger-study (base) tioncico@appledeMacBook-Pro ~ % docker network connect jaeger\_network elastic\_search (base) tioncico@appledeMacBook-Pro ~ %
启动collector:
./jaeger-collector --span-storage.type=elasticsearch --es.server-urls=http://elastic_search:9200
将监听以下端口:
- 14267 tcp agent发送jaeger.thrift格式数据
- 14250 tcp agent发送proto格式数据(背后gRPC)
- 14268 http 直接接受客户端数据
- 14269 http 健康检查
启动agent
./jaeger-agent --reporter.grpc.host-port=127.0.0.1:14250
启动成功后,将监听:
- 5775 UDP协议,接收兼容zipkin的协议数据
- 6831 UDP协议,接收兼容jaeger的兼容协议
- 6832 UDP协议,接收jaeger的二进制协议
- 5778 HTTP协议,数据量大不建议使用
通过Jaeger-client直接传输到agent:
package main import ( "context" "fmt" "io" "time" "github.com/opentracing/opentracing-go" "github.com/opentracing/opentracing-go/log" "github.com/uber/jaeger-client-go" "github.com/uber/jaeger-client-go/config" ) /** 初始化 */ func initJaeger(service string) (opentracing.Tracer, io.Closer) { cfg := &config.Configuration{ Sampler: &config.SamplerConfig{ Type: "const", Param: 1, }, Reporter: &config.ReporterConfig{ LogSpans: true, LocalAgentHostPort: "127.0.0.1:6831", }, ServiceName: service, } tracer, closer, err := cfg.NewTracer(config.Logger(jaeger.StdLogger)) if err != nil { panic(fmt.Sprintf("Error: connot init Jaeger: %v\\n", err)) } return tracer, closer } func main() { tracer, closer := initJaeger("jager-test-demo") defer closer.Close() //设置全局的tracer opentracing.SetGlobalTracer(tracer) //设置顶级span span := tracer.StartSpan("main") ctx := opentracing.ContextWithSpan(context.Background(), span) //调用栈1,例如查询数据 _ = selectData("test", ctx) //调用栈2,例如写入日志 _ = writeLog("log", ctx) span.Finish() fmt.Println("调用栈完成") } func selectData(data string, ctx context.Context) (reply string) { //创建子span span, _ := opentracing.StartSpanFromContext(ctx, "selectData") defer span.Finish() //结束后调用完成 span.SetTag("data", data) span.SetTag("reply", reply) span.LogFields( log.String("event", "selectData"), log.String("value", "666666"), ) time.Sleep(time.Second / 2) //模拟查询了2秒 reply = "select data" return } func writeLog(data string, ctx context.Context) (reply string) { //创建子span span, _ := opentracing.StartSpanFromContext(ctx, "writeLog") defer span.Finish() //结束后调用完成 span.LogFields( log.String("log", data), ) reply = "writeLog" return }
query&ui查看链路追踪日志
启动query:
./jaeger-query --span-storage.type=elasticsearch --es.server-urls=http://elastic_search:9200
打开:http://127.0.0.1:16686/ 网页
即可查看到链路追踪日志