hincky的主页 hincky的主页
  • 学习笔记

    • Vue笔记
    • Vuepress
    • nginx
  • 语言类

    • java
    • go
    • python
    • 设计模式
  • 框架类

    • Spring
    • Spring Security
    • Mybatis
  • 容器技术

    • docker
    • k8s
    • helm
    • prometheus
    • grafana
    • jenkins
  • 命令集合

    • linux命令
    • docker命令
    • git命令
    • vim命令
    • k8s命令
  • 数据库

    • sql
    • mysql
  • 协议

    • 网络模型
    • http/1.1
    • WebSocket
    • http/2
    • TLS/SSL
    • tcp
    • IP
    • tcpdump抓包命令
    • wireshark抓包工具
  • 通用

    • Git
  • 技术分享

    • git push/pull总是超时怎么办
    • idea debug技巧
    • postman使用
    • 问题总结
    • idea使用技巧
  • Oauth2

    • Oauth2原理
  • 项目列表

    • redis项目
    • 微服务项目
  • 分类
  • 标签
  • 归档
  • 随笔
GitHub (opens new window)

Hincky

当有趣的人,做想做的事
  • 学习笔记

    • Vue笔记
    • Vuepress
    • nginx
  • 语言类

    • java
    • go
    • python
    • 设计模式
  • 框架类

    • Spring
    • Spring Security
    • Mybatis
  • 容器技术

    • docker
    • k8s
    • helm
    • prometheus
    • grafana
    • jenkins
  • 命令集合

    • linux命令
    • docker命令
    • git命令
    • vim命令
    • k8s命令
  • 数据库

    • sql
    • mysql
  • 协议

    • 网络模型
    • http/1.1
    • WebSocket
    • http/2
    • TLS/SSL
    • tcp
    • IP
    • tcpdump抓包命令
    • wireshark抓包工具
  • 通用

    • Git
  • 技术分享

    • git push/pull总是超时怎么办
    • idea debug技巧
    • postman使用
    • 问题总结
    • idea使用技巧
  • Oauth2

    • Oauth2原理
  • 项目列表

    • redis项目
    • 微服务项目
  • 分类
  • 标签
  • 归档
  • 随笔
GitHub (opens new window)
  • java

  • python

  • Spring

  • SpringMVC

  • SpringSecurity

  • Mybatis

  • 设计模式

  • Go

    • 基础语法

    • Gin框架

    • Go gRPC

    • go-gin-api [文档]

      • 使用 go modules 初始化项目
        • 概述
        • 初始化
        • 添加依赖包
        • go mod 命令
        • 小结
        • 源码地址
      • 规划项目目录和参数验证
        • 概述
        • 规划目录结构
        • 模型绑定和验证
        • 自定义验证器
        • 制定 API 返回结构
        • 源码地址
        • go-gin-api 系列文章
        • 备注
      • 路由中间件 - 日志记录
        • 概述
        • gin.Logger()
        • 自定义 Logger()
        • 源码地址
        • go-gin-api 系列文章
      • 路由中间件 - 捕获异常
        • 概述
        • 什么是异常?
        • 怎么捕获异常?
        • 封装发邮件方法
        • 自定义邮件模板
        • 封装一个中间件
        • 备注
        • 源码地址
        • go-gin-api 系列文章
      • 路由中间件 - 链路追踪(Jaeger)
        • 概述
        • 如何设计日志记录?
        • 开源工具
        • Jaeger 架构图
        • Jaeger Span
        • Jaeger 部署
        • Jaeger 端口
        • Jaeger 采样率
        • Jaeger 缺点
        • 实战
        • 源码地址
        • go-gin-api 系列文章
      • 路由中间件 - 链路追踪(Jaeger)实战
        • 概述
        • Jaeger 部署
        • 准备测试服务
          • 听(listen)
          • 说(speak)
          • 读(read)
          • 写(write)
          • 唱(sing)
        • 应用示例
          • 实例化 Tracer
          • HTTP 注入
          • HTTP 拦截
          • gRPC 注入
          • gRPC 拦截
        • 运行
          • 启动服务
          • 访问路由
        • 效果
        • API 源码地址
        • Service 源码地址
        • go-gin-api 系列文章
      • 路由中间件 - 签名验证
        • 概览
        • MD5 组合
          • 生成签名
          • 验证签名
          • 中间件 - 代码实现
        • AES 对称加密
          • 生成签名
          • 验证签名
          • 中间件 - 代码实现
        • RSA 非对称加密
          • 创建签名
          • 验证签名
          • 中间件 - 代码实现
        • 如何调用?
        • 性能测试
          • MD5
          • AES
          • RSA
        • PHP 与 Go 加密方法如何互通?
        • 源码地址
        • go-gin-api 系列文章
    • go基本介绍
      • 安装go
      • hello world
      • 变量类型
      • 变量和声明
        • 定义和赋值分开
        • 定义和赋值合并
        • 最简单的写法
        • 最简写法结合函数
        • 多个变量同时赋值
        • 变量总结
      • if
      • 导入包
      • 运行go代码
      • 函数声明
        • 返回值个数
        • 参数接收
        • 两个参数都接收
        • 只接收其中一个参数
    • Go结构体
      • 定义结构体
      • 声明和初始化
        • 结构体字段
        • 结构体初始化
        • 函数参数传递方式
        • 镜像复制
        • 指针
      • 结构体上的函数
      • 构造器
        • new
    • Go相关项目推荐
      • 收录golang的一些好的开源项目
  • 后端
  • Go
  • go-gin-api [文档]
hincky
2022-11-21
目录

路由中间件 - 链路追踪(Jaeger)

# 概述

首先同步下项目概况:

上篇文章分享了,路由中间件 - 捕获异常,这篇文章咱们分享:路由中间件 - Jaeger 链路追踪。

啥是链路追踪?

我理解链路追踪其实是为微服务架构提供服务的,当一个请求中,请求了多个服务单元,如果请求出现了错误或异常,很难去定位是哪个服务出了问题,这时就需要链路追踪。

咱们先看一张图:

这张图的调用链还比较清晰,咱们想象一下,随着服务的越来越多,服务与服务之间调用关系也越来越多,可能就会发展成下图的情况。

这调用关系真的是... 看到这,我的内心是崩溃的。

那么问题来了,这种情况下怎么快速定位问题?

# 如何设计日志记录?

我们自己也可以设计一个链路追踪,比如当发生一个请求,咱们记录它的:

  • 请求的唯一标识
  • 请求了哪些服务?
  • 请求的服务依次顺序?
  • 请求的 Request 和 Response 日志?
  • 对日志进行收集、整理,并友好展示

怎么去实现请求的唯一标识?

以 Go 为例 写一个中间件,在每次请求的 Header 中包含:X-Request-Id,代码如下:

func SetUp() gin.HandlerFunc {
	return func(c *gin.Context) {
		requestId := c.Request.Header.Get("X-Request-Id")
		if requestId == "" {
			requestId = util.GenUUID()
		}
		c.Set("X-Request-Id", requestId)
		c.Writer.Header().Set("X-Request-Id", requestId)
		c.Next()
	}
}
1
2
3
4
5
6
7
8
9
10
11

每个 Request 和 Response 日志中都要包含 X-Request-Id。

问题又来了,每次调用都记录日志,当调用的服务过多时,频繁的记录日志,就会有性能问题呀,肿么办?

哎,这么麻烦,看看市面上有没有一些开源工具呢?

# 开源工具

  • Jaeger:https://www.jaegertracing.io
  • Zipkin:https://zipkin.io/
  • Appdash:https://about.sourcegraph.com/

这个就不多做介绍了,基本上都能满足需求,至于优缺点,大家可以挨个去瞅瞅,喜欢哪个就用哪个?

我为什么选择 Jaeger ?

因为我目前只会用这个,其他还不会 ...

咱们一起看下 Jaeger 是怎么回事吧。

# Jaeger 架构图

图片来源于官网。

简单介绍下上图三个关键组件:

Agent

Agent是一个网络守护进程,监听通过UDP发送过来的Span,它会将其批量发送给collector。按照设计,Agent要被部署到所有主机上,作为基础设施。Agent将collector和客户端之间的路由与发现机制抽象了出来。

Collector

Collector从Jaeger Agent接收Trace,并通过一个处理管道对其进行处理。目前的管道会校验Trace、建立索引、执行转换并最终进行存储。存储是一个可插入的组件,现在支持Cassandra和elasticsearch。

Query

Query服务会从存储中检索Trace并通过UI界面进行展现,该UI界面通过React技术实现,其页面UI如下图所示,展现了一条Trace的详细信息。

其他组件,大家可以了解下并选择性使用。

# Jaeger Span

图片来源于官网。

怎么操作 Span 呢?Span 有哪些可以调用的 API ?

# Jaeger 部署

All in one

为了方便大家快速使用,Jaeger 直接提供一个 All in one 包,我们可以直接执行,启动一套完整的 Jaeger tracing 系统。

启动成功后,访问 http://localhost:16686 就可以看到 Jaeger UI。

独立部署

  • jaeger-agent
  • jaeger-collector
  • jaeger-query
  • jaeger-ingester
  • jaeger-operator
  • jaeger-cassandra-schema
  • jaeger-es-index-cleaner
  • spark-dependencies

可以自由搭配,组合使用。

# Jaeger 端口

  • 端口:6831

  • 协议:UDP

  • 所属模块:Agent

  • 功能:通过兼容性 Thrift 协议,接收 Jaeger thrift 类型数据

  • 端口:14267

  • 协议:HTTP

  • 所属模块:Collector

  • 功能:接收客户端 Jaeger thrift 类型数据

  • 端口:16686

  • 协议:HTTP

  • 所属模块:Query

  • 功能:客户端前端界面展示端口

# Jaeger 采样率

分布式追踪系统本身也会造成一定的性能低损耗,如果完整记录每次请求,对于生产环境可能会有极大的性能损耗,一般需要进行采样设置。

固定采样

(sampler.type=const)

  • sampler.param=1 全采样,
  • sampler.param=0 不采样;

按百分比采样

(sampler.type=probabilistic)

  • sampler.param=0.1 则随机采十分之一的样本;

采样速度限制

(sampler.type=ratelimiting)

  • sampler.param=2.0 每秒采样两个traces;

动态获取采样率

(sampler.type=remote)

  • 这个是默认配置,可以通过配置从 Agent 中获取采样率的动态设置。

# Jaeger 缺点

  • 接入过程有一定的侵入性;
  • 本身缺少监控和报警机制,需要结合第三方工具来实现,比如配合Grafana 和 Prometheus实现;

看到这,说的都是理论,大家的心里话可能是:

# 实战

  • Jaeger 部署
  • Jaeger 在 Gin 中使用
  • Jaeger 在 gRPC 中使用

关于实战的分享,我准备整理出 4 个服务,然后实现服务与服务之间进行相互调用,目前 Demo 还没写完...

下篇文章再给大家分享。

# 源码地址

https://github.com/xinliangnote/go-gin-api

# go-gin-api 系列文章

  • 1. 使用 go modules 初始化项目 (opens new window)
  • 2. 规划项目目录和参数验证 (opens new window)
  • 3. 路由中间件 - 日志记录 (opens new window)
  • 4. 路由中间件 - 捕获异常 (opens new window)
编辑 (opens new window)
路由中间件 - 捕获异常
路由中间件 - 链路追踪(Jaeger)实战

← 路由中间件 - 捕获异常 路由中间件 - 链路追踪(Jaeger)实战→

最近更新
01
人生前期重要的能力
05-17
02
防火墙命令
04-11
03
docker-compose部署mysql主从集群
03-22
更多文章>
Theme by Vdoing | Copyright © 2022-2023 Hincky | MIT License | 粤ICP备2022120427号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式