概述

首先同步下项目概况:

上篇文章分享了,路由中间件 - Jaeger 链路追踪(理论篇)。

这篇文章咱们分享:路由中间件 - Jaeger 链路追踪(实战篇)。

说实话,这篇文章确实让大家久等了,主要是里面有一些技术点都是刚刚研究的,没有存货。

先看下咱们要实现的东西:


API 调用了 5 个服务,其中 4 个 gRPC 服务,1 个 HTTP 服务,服务与服务之间又相互调用:

Speak 服务,又调用了 Listen 服务 和 Sing 服务。

Read 服务,又调用了 Listen 服务 和 Sing 服务。

Write 服务,又调用了 Listen 服务 和 Sing 服务。

咱们要实现的就是查看 API 调用的链路。

关于一些理论的东西,大家可以去看看上篇文章或查阅一些资料,这篇文章就是实现怎么用。

OK,开整。

Jaeger 部署

咱们使用 All in one 的方式,进行本地部署。

下载地址:https://www.jaegertracing.io/download/

我的电脑是 macOS 选择 -> Binaries -> macOS

下载后并解压,会发现以下文件:

    example-hotrod

    jaeger-agent

    jaeger-all-in-one

    jaeger-collector

    jaeger-ingester

    jaeger-query

进入到解压后的目录执行:

./jaeger-all-in-one

目测启动后,访问地址:

http://127.0.0.1:16686/


这里我还准备了一分学习图和资料,如下:

链接:https://pan.baidu.com/s/1v5gm7n0L7TGyejCmQrMh2g 提取码:x2p5

免费分享,但是X度限制严重,如若链接失效点击链接或搜索加群 群号518475424

到这,Jaeger 已经部署成功了。

准备测试服务

准备的五个测试服务如下:
听(listen)

端口:9901

通讯:gRPC

说(speak)

端口:9902

通讯:gRPC

读(read)

端口:9903

通讯:gRPC

写(write)

端口:9904

通讯:gRPC

唱(sing)

端口:9905

通讯:HTTP

听、说、读、写、唱,想这几个服务的名称就花了好久 ~

我默认大家都会写 grpc 服务,如果不会写的,可以查看下我原来的文章《Go gRPC Hello World》。

应用示例

实例化 Tracer

    func NewJaegerTracer(serviceName string, jaegerHostPort string) (opentracing.Tracer, io.Closer, error) {
cfg := &jaegerConfig.Configuration {
Sampler: &jaegerConfig.SamplerConfig{
Type : "const", //固定采样
Param : 1, //1=全采样、0=不采样
},
Reporter: &jaegerConfig.ReporterConfig{
LogSpans : true,
LocalAgentHostPort : jaegerHostPort,
},
ServiceName: serviceName,
}
tracer, closer, err := cfg.NewTracer(jaegerConfig.Logger(jaeger.StdLogger))
if err != nil {
panic(fmt.Sprintf("ERROR: cannot init Jaeger: %v\n", err))
}
opentracing.SetGlobalTracer(tracer)
return tracer, closer, err
} HTTP 注入 injectErr := jaeger.Tracer.Inject(span.Context(), opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(req.Header))
if injectErr != nil {
log.Fatalf("%s: Couldn't inject headers", err)
} HTTP 拦截 spCtx, err := opentracing.GlobalTracer().Extract(opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(c.Request.Header))
if err != nil {
ParentSpan = Tracer.StartSpan(c.Request.URL.Path)
defer ParentSpan.Finish()
} else {
ParentSpan = opentracing.StartSpan(
c.Request.URL.Path,
opentracing.ChildOf(spCtx),
opentracing.Tag{Key: string(ext.Component), Value: "HTTP"},
ext.SpanKindRPCServer,
)
defer ParentSpan.Finish()
} gRPC 注入 func ClientInterceptor(tracer opentracing.Tracer, spanContext opentracing.SpanContext) grpc.UnaryClientInterceptor {
return func(ctx context.Context, method string,
req, reply interface{}, cc *grpc.ClientConn,
invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
span := opentracing.StartSpan(
"call gRPC",
opentracing.ChildOf(spanContext),
opentracing.Tag{Key: string(ext.Component), Value: "gRPC"},
ext.SpanKindRPCClient,
)
defer span.Finish()
md, ok := metadata.FromOutgoingContext(ctx)
if !ok {
md = metadata.New(nil)
} else {
md = md.Copy()
}
err := tracer.Inject(span.Context(), opentracing.TextMap, MDReaderWriter{md})
if err != nil {
span.LogFields(log.String("inject-error", err.Error()))
}
newCtx := metadata.NewOutgoingContext(ctx, md)
err = invoker(newCtx, method, req, reply, cc, opts...)
if err != nil {
span.LogFields(log.String("call-error", err.Error()))
}
return err
}
} gRPC 拦截 func serverInterceptor(tracer opentracing.Tracer) grpc.UnaryServerInterceptor {
return func(ctx context.Context,
req interface{},
info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler) (resp interface{}, err error) {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
md = metadata.New(nil)
}
spanContext, err := tracer.Extract(opentracing.TextMap, MDReaderWriter{md})
if err != nil && err != opentracing.ErrSpanContextNotFound {
grpclog.Errorf("extract from metadata err: %v", err)
} else {
span := tracer.StartSpan(
info.FullMethod,
ext.RPCServerOption(spanContext),
opentracing.Tag{Key: string(ext.Component), Value: "gRPC"},
ext.SpanKindRPCServer,
)
defer span.Finish()
ParentContext = opentracing.ContextWithSpan(ctx, span)
}
return handler(ParentContext, req)
}
}

上面是一些核心的代码,涉及到的全部代码我都会上传到 github,供下载。

运行
启动服务

 // 启动 Listen 服务
cd listen && go run main.go
// 启动 Speak 服务
cd speak && go run main.go
// 启动 Read 服务
cd read && go run main.go
// 启动 Write 服务
cd write && go run main.go
// 启动 Sing 服务
cd sing && go run main.go
// 启动 go-gin-api 服务
cd go-gin-api && go run main.go

访问路由

http://127.0.0.1:9999/jaeger_test

效果


基本实现了,就到这吧。

go-gin-api 路由中间件 - Jaeger 链路追踪的更多相关文章

  1. [系列] go-gin-api 路由中间件 - Jaeger 链路追踪(五)

    概述 首先同步下项目概况: 上篇文章分享了,路由中间件 - 捕获异常,这篇文章咱们分享:路由中间件 - Jaeger 链路追踪. 啥是链路追踪? 我理解链路追踪其实是为微服务架构提供服务的,当一个请求 ...

  2. [系列] go-gin-api 路由中间件 - Jaeger 链路追踪(六)

    [DOC] 概述 首先同步下项目概况: 上篇文章分享了,路由中间件 - Jaeger 链路追踪(理论篇),这篇文章咱们接着分享:路由中间件 - Jaeger 链路追踪(实战篇). 这篇文章,确实让大家 ...

  3. go-zero docker-compose 搭建课件服务(八):集成jaeger链路追踪

    0.转载 go-zero docker-compose 搭建课件服务(八):集成jaeger链路追踪 0.1源码地址 https://github.com/liuyuede123/go-zero-co ...

  4. [系列] go-gin-api 路由中间件 - 签名验证(七)

    目录 概览 MD5 组合 AES 对称加密 RSA 非对称加密 如何调用? 性能测试 PHP 与 Go 加密方法如何互通? 源码地址 go-gin-api 系列文章 概览 首先同步下项目概况: 上篇文 ...

  5. go-gin-api 路由中间件 - 签名验证(七)

    概览 首先同步下项目概况: 上篇文章分享了,路由中间件 - Jaeger 链路追踪(实战篇),文章反响真是出乎意料, 「Go中国」 公众号也转发了,有很多朋友加我好友交流,直呼我大神,其实我哪是什么大 ...

  6. 微服务从代码到k8s部署应有尽有系列(十二、链路追踪)

    我们用一个系列来讲解从需求到上线.从代码到k8s部署.从日志到监控等各个方面的微服务完整实践. 整个项目使用了go-zero开发的微服务,基本包含了go-zero以及相关go-zero作者开发的一些中 ...

  7. .NET Core 中的日志与分布式链路追踪

    目录 .NET Core 中的日志与分布式链路追踪 .NET Core 中的日志 控制台输出 非侵入式日志 Microsoft.Extensions.Logging ILoggerFactory IL ...

  8. 带你十天轻松搞定 Go 微服务系列(九、链路追踪)

    序言 我们通过一个系列文章跟大家详细展示一个 go-zero 微服务示例,整个系列分十篇文章,目录结构如下: 环境搭建 服务拆分 用户服务 产品服务 订单服务 支付服务 RPC 服务 Auth 验证 ...

  9. Jaeger Client Go 链路追踪|入门详解

    目录 从何说起 Jaeger 部署 Jaeger 从示例了解 Jaeger Client Go 了解 trace.span tracer 配置 Sampler 配置 Reporter 配置 分布式系统 ...

随机推荐

  1. 在.NET Core 3.0 Preview上使用Windows窗体设计器

    支持使用基于Windows窗体应用程序的.NET Core 3.0(预览)的Windows窗体设计器 介绍 截至撰写本文时,Microsoft和社区目前正在测试.NET Core 3.0.如果您在.N ...

  2. CSS覆盖问题的说明

    最近在写css的时候,由于经常使用到很长的多级选择器,而碰到一些样式被覆盖或者覆盖不了的情况是相当的郁闷,所以专门花了一些时间对一些选择器做了对比测试.这里先说明一下,由于ie6不支持css2.0选择 ...

  3. ASP.NET MVC过滤器学习笔记

    1.过滤器的两个特征 1.他是一种特性,可以引用到控制器类和Action方法上.比如下图 这里控制器类和action方法都引用了过滤器,这个过滤器是用来做授权的 2.特征继承自FilterAttrib ...

  4. electron——ipcMain模块、ipcRenderer模块

    ipcMain 从 主进程 到 渲染进程 的异步通信. ipcMain模块是EventEmitter类的一个实例. 当在主进程中使用时,它处理从渲染器进程(网页)发送出来的异步和同步信息. 从渲染器进 ...

  5. 4. 移动安全渗透测试-(Android逆向基础)

    4.1 smali 基础 1.注释 smali中使用#来代表注释一行例如:# const-string v0, "aaa" #这句不会被执行 2.数据类型 V void,只能用于返 ...

  6. JVM源码分析之MetaspaceSize和MaxMetaspaceSize的区别

    JVM加载类的时候,需要记录类的元数据,这些数据会保存在一个单独的内存区域内,在Java 7里,这个空间被称为永久代(Permgen),在Java 8里,使用元空间(Metaspace)代替了永久代. ...

  7. nrm : 无法加载文件 C:\Users\TANG\AppData\Roaming\npm\nrm.ps1,因为在此系统上禁止运行脚本。

    1.win+s 搜索powershell 以管理身份运行 2.使用set-ExecutionPolicy RemoteSigned命令将计算机上的执行策略更改为 RemoteSigned,输入Y确定 ...

  8. emoji表情多终端适配解决方案

    emoji表情多终端适配解决方案 emoji,也叫 颜表情 是日本在无线通信中所使用的视觉情感符号,由栗田穰崇(Shigetaka Kurita)创作,并在日本网络及手机用户中流行.自苹果公司发布的i ...

  9. [TCP/IP] TCP如何保证可靠性

    1.数据包校验,发送方计算校验和,接收方结算校验和,进行对比2.应答机制,seq序列号与ack确认号 3.超时重传机制,发送后启动定时器,进行重传 4.连接管理,三次和四次5.对失序数据包重排序6.流 ...

  10. super与this用法

    super注意点: 1.当super调用父类的构造方法,必须在构造方法的第一个: 2.super必须只能出现在子类的方法或者构造方法中: 3.super和this不能同时调用构造方法: 4.super ...