欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-07-02 12:58:44
[TOC] 概述 首先同步下项目概况: 上篇文章分享了,路由中间件 捕获异常,这篇文章咱们分享:路由中间件 Jaeger 链路追踪。 啥是链路追踪? 我理解链路追踪其实是为微服务架构提供服务的,当一个请求中,请求了多个服务单元,如果请求出现了错误或异常,很难去定位是哪个服务出了问题,这时就需要链路追 ......

概述

首先同步下项目概况:

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

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

啥是链路追踪?

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

咱们先看一张图:

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

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

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

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

[系列] go-gin-api 路由中间件 - 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()
    }
}

每个 request 和 response 日志中都要包含 x-request-id。

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

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

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

开源工具

  • jaeger:
  • zipkin:
  • appdash:

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

我为什么选择 jaeger

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

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

jaeger 架构图

[系列] go-gin-api 路由中间件 - 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

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

图片来源于官网。

怎么操作 span 呢?span 有哪些可以调用的 api ?

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

jaeger 部署

all in one

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

启动成功后,访问 就可以看到 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实现;

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

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

实战

  • jaeger 部署
  • jaeger 在 gin 中使用
  • jaeger 在 grpc 中使用

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

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

下篇文章再给大家分享。

源码地址

go-gin-api 系列文章