go-gin-api 路由中间件 - Jaeger 链路追踪
概述
首先同步下项目概况:
上篇文章分享了,路由中间件 - 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 链路追踪的更多相关文章
- [系列] go-gin-api 路由中间件 - Jaeger 链路追踪(五)
概述 首先同步下项目概况: 上篇文章分享了,路由中间件 - 捕获异常,这篇文章咱们分享:路由中间件 - Jaeger 链路追踪. 啥是链路追踪? 我理解链路追踪其实是为微服务架构提供服务的,当一个请求 ...
- [系列] go-gin-api 路由中间件 - Jaeger 链路追踪(六)
[DOC] 概述 首先同步下项目概况: 上篇文章分享了,路由中间件 - Jaeger 链路追踪(理论篇),这篇文章咱们接着分享:路由中间件 - Jaeger 链路追踪(实战篇). 这篇文章,确实让大家 ...
- go-zero docker-compose 搭建课件服务(八):集成jaeger链路追踪
0.转载 go-zero docker-compose 搭建课件服务(八):集成jaeger链路追踪 0.1源码地址 https://github.com/liuyuede123/go-zero-co ...
- [系列] go-gin-api 路由中间件 - 签名验证(七)
目录 概览 MD5 组合 AES 对称加密 RSA 非对称加密 如何调用? 性能测试 PHP 与 Go 加密方法如何互通? 源码地址 go-gin-api 系列文章 概览 首先同步下项目概况: 上篇文 ...
- go-gin-api 路由中间件 - 签名验证(七)
概览 首先同步下项目概况: 上篇文章分享了,路由中间件 - Jaeger 链路追踪(实战篇),文章反响真是出乎意料, 「Go中国」 公众号也转发了,有很多朋友加我好友交流,直呼我大神,其实我哪是什么大 ...
- 微服务从代码到k8s部署应有尽有系列(十二、链路追踪)
我们用一个系列来讲解从需求到上线.从代码到k8s部署.从日志到监控等各个方面的微服务完整实践. 整个项目使用了go-zero开发的微服务,基本包含了go-zero以及相关go-zero作者开发的一些中 ...
- .NET Core 中的日志与分布式链路追踪
目录 .NET Core 中的日志与分布式链路追踪 .NET Core 中的日志 控制台输出 非侵入式日志 Microsoft.Extensions.Logging ILoggerFactory IL ...
- 带你十天轻松搞定 Go 微服务系列(九、链路追踪)
序言 我们通过一个系列文章跟大家详细展示一个 go-zero 微服务示例,整个系列分十篇文章,目录结构如下: 环境搭建 服务拆分 用户服务 产品服务 订单服务 支付服务 RPC 服务 Auth 验证 ...
- Jaeger Client Go 链路追踪|入门详解
目录 从何说起 Jaeger 部署 Jaeger 从示例了解 Jaeger Client Go 了解 trace.span tracer 配置 Sampler 配置 Reporter 配置 分布式系统 ...
随机推荐
- Python struct与小端存储
参考链接:https://www.liaoxuefeng.com/wiki/1016959663602400/1017685387246080 在使用Python 实现字符向字节数据类型转换的时候,P ...
- 汇编指令之JMP,CALL,RET(修改EIP的值!!!)
简单介绍了,JMP指令按市面上的意思来说是跳转到指定地址,但我这里不这么说,JMP, CALL, RET三个指令均为修改EIP值的指令,EAX, ECX, EBX, EDX, ESP, EBP, ES ...
- Fundebug后端Node.js插件更新至0.2.0,支持监控Express慢请求
摘要: 性能问题也是BUG,也需要监控. Fundebug后端Node.js异常监控服务 Fundebug是专业的应用异常监控平台,我们Node.js插件fundebug-nodejs可以提供全方位的 ...
- springboot使用vue打包过的页面资源
(一)webpack打包 如果在vue基于webpack的,build打包后得到的是如下的资源文件: webstorm中提示如下: 这个大致的意思就是这边的文件需要放在http服务器上访问,如果直接打 ...
- python关于SSL的认证--pycurl模块使用
今天在做微信支付退款接口的时候,因为需要使用到双向证书的认证,所以一开始是没有头绪的,后来在网上找到了相类似的教程,发现了pycurl模块,才成功实现了证书认证,教程链接:http://blog.cs ...
- 201871010125 王玉江《面向对象程序设计(java)》第十三周学习总结
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...
- python-分割url字符串
url = ' http://images.jupiterimages.com/common/detail/27/68/22986827.jpg' url.strip().split('/')[-1] ...
- Docker安装(二)
一.前提条件 目前,CentOS 仅发行版本中的内核支持 Docker. Docker 运行在 CentOS 7 上,要求系统为64位.系统内核版本为 3.10 以上. Docker 运行在 Cent ...
- zzL4自动驾驶中感知系统遇到的挑战及解决方案
本次分享的大纲: Perception Introduction Sensor Setup & Sensor Fusion Perception Onboard System Percepti ...
- 树莓派“Wlan0: Not associated”报错解决方案
当执行 ifconfig wlan0 时,是有wlan0的网卡信息输出的. 当执行 ifconfig wlan0 up 是没问题的(即没有任何输出). 执行 iwlist wlan0 scan | g ...