Java版 Jaeger的客户端采样配置(积家Jaeger)

欢迎访问我的GitHubhttps://github.com/zq2599/blog_demos
内容:所有原创文章分类汇总及配套源码 , 涉及Java、Docker、Kubernetes、DevOPS等;
关于采样(Sampling)

  • 采样很好理解:使用Jaeger时 , 未必需要将所有请求都上报到Jaeger , 有时候只要抽取其中一部分观察即可 , 这就是按照一定策略进行采样;
  • Jaeger SDK是支持多种采样配置的 , 在分布式系统中 , 他们遵循的原则是前置判定(consistent upfront 或者head-based) , 简单来说 , 假如consumer服务调用provider服务 , 那么某一次请求只要consumer决定不采样 , 那么provider在处理这个请求的时候也不会采样 , 也就是说对于一次完整的trace , 只要最前面的服务不上报到jaeger , 那么整个trace后面涉及的服务都不会上报到jaeger
  • Jaeger采样配置分为客户端和服务端两种配置 , 默认用的是服务端配置
  • 本文咱们来了解如何在客户端(也就是接入Jaeger的应用)配置采样 , 并且动手验证效果 , 常用的客户端采样策略有以下三种:
  1. 固定:要么全部采样 , 要门全部不采样
  2. 比例:按照指定比例采样
  3. 限速:固定时间周期内采样固定数量 , 例如每秒一个
  • 接下来 , 逐个配置和体验这三种采样的效果
关于实战用的工程
  • 采样配置实战不涉及编码 , 只需要改一些配置 , 所以没必要大张旗鼓的新建工程写代码 , 用《Jaeger开发入门(java版)》一文中的两个maven子工程即可:服务提供方jaeger-service-provider和服务调用方jaeger-service-consumer , 都做成docker镜像 , 用docker-compose启动 , 网络架构如下图:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 请确保项目的日志模板中已添加了traceIdspanIdsampled等变量 , 如下图红框所示 , 有了这些配置 , 咱们在日志中就能看到对应的trace是否被采样(这一步非常重要):

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 为了方便修改代码后重新部署启动 , 我写了个名为full.sh的shell脚本文件 , 运行即可将修改后的代码制作成最新的镜像并用docker-compose运行起来:
#!/bin/bashecho "停止docker-compose"cd jaeger-service-provider && docker-compose down && cd ..echo "编译构建"mvn clean package -U -DskipTestsecho “创建provider镜像”cd jaeger-service-provider && docker build -t bolingcavalry/jaeger-service-provider:0.0.1 . && cd ..echo “创建consumer镜像”cd jaeger-service-consumer && docker build -t bolingcavalry/jaeger-service-consumer:0.0.1 . && cd ..echo "清理无效资源"docker system prune --volumes -fecho "启动docker-compose"cd jaeger-service-provider && docker-compose up -d && cd ..
  • 如果您用的是IDEA , 在下图红框位置添加一个自定义命令 , 选中上述shell文件 , 就可以在IDEA中用run命令来编译构建部署了:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 现在准备工作已经完成 , 开始实战吧 , 从最简单的固定采样开始;
固定采样
  • 【Java版 Jaeger的客户端采样配置(积家Jaeger)】固定采样的逻辑很简单:要么全部上报 , 要么一个也不报
  • 固定采样的配置方式如下图红框所示:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 要注意的是:根据前置判定(consistent upfront 或者head-based)原则 , 只要将上述配置写入jaeger-service-consumer项目的配置文件即可 , 至于jaeger-service-provider维持原状不做任何改动
  • 执行前面写的full.sh脚本 , 编译构建部署
  • 浏览器访问http://localhost:18080/hello , 产生一些web请求 , 多访问几次
  • 看jaeger-service-consumer容器的日志 , 如下图 , 红框中的sampled=false表示未采样 , 三此请求的日志都是如此:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 再看jaeger-service-provider容器的日志 , 如下图红框 , 也全部都没有采样 , 这证明Jaeger的前置判定原则(consistent upfront 或者head-based)是准确的 , jaeger-service-consumer是一次trace的源头 , 被它关闭了采样的trace , 在后续的服务中也会自动关闭采样:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 去Jaeger的web页面看看 , 空空如也 , 连服务列表中都没有jaeger-service-consumer和jaeger-service-provider:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 试过了全部不采样 , 再来试试全部采样的配置 , 如下图红框:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 重新部署 , 再产生几次请求 , 去看jaeger-service-consumer容器的日志 , 如下图红框 , 全部都被采样了:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 去看jaeger-service-provider容器的日志 , 也是如此 , 所有trace都被采样:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 打开Jaeger的web页面 , 可见jaeger-service-consumer的三次请求对应的trace全部上报:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 至此 , 最简单的固定采样已完成 , 来看看更实用的比例采样
比例采样
  • 顾名思义 , 就是按照一定的百分比采样 , 配置如下图所示:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 执行前面写的full.sh脚本 , 编译构建部署
  • 测试比例采样的方法就是发多个请求 , 检查采样的trace是否是总数的十分之一 , 我这里用jmeter来执行多次请求 , 您可以选择自己擅长的工具 , 或者写代码写脚本 , 甚至手动访问多次
  • 使用jmeter可以控制请求次数 , 用的是Loop Controller , 如下图红框所示:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 向jaeger-service-consumer的/hello接口发送完一百次请求后 , 可以从docker容器日志中检查采样情况 , 这里使用grepwc命令的组合来统计日志中出现sampled=truesampled=false的行数 , 完整的命令如下:
docker logs jaeger-service-consumer| grep 'sampled=true'|wc -l
  • 100个请求 , 采样率百分之十 , 但是用上述命令得到的结果并不是精确值10 , 而是8 , 再统计未采样的日志行数(把true改成false) , 得到的结果是92 , 总数对得上 , 但是采样数并非精确的百分之十 , 如下图:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 然后将请求总数增加到一千条 , 得到的采样比例接近百分之十 , 如下:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 打开Jaeger的web页面 , 可见果然只有106个trace:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 比例采样完成了 , 接下来是限速采样
限速采样
  • 关于限速 , 似乎不够具体不便于理解 , 但是看看官方文档上的关键字leaky bucket , 如下图红框 , 聪明的您一定想到了其中的关键 , 漏桶限流算法(注意 , 是漏桶 , 不是令牌桶 , 漏桶算法的峰值和桶大小有关):

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 配置如下图红框所示:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 执行前面写的full.sh脚本 , 编译构建部署
  • 咱们的配置是每秒钟一次采样 , 所以验证的时候要控制好发送请求的时长 , 我这里还是用jmeter来发请求的 , 如下图红框所示 , jmeter有种Runtime Controller类型的控制器 , 可以控制持续请求的时长 , 我这里设置为10秒:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 用jmeter持续发送10秒的请求 , 从jmeter的汇总报告中可见一共发了70个请求:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 用命令docker logs jaeger-service-consumer| grep 'sampled=true'|wc -l查看采样总数 , 10秒的预期是10个 , 结果如下 , 并不精确 , 只是接近而已:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 清掉所有数据 , 将时长改成100秒试试 , 一共发出次852请求:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 采样总数为96 , 接近预期:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
  • 打开Jaeger的web页面也是96次trace:

Java版 Jaeger的客户端采样配置(积家Jaeger)

文章插图
服务端配置一瞥
  • 还记得《分布式调用链跟踪工具Jaeger?两分钟极速体验》、《Jaeger开发入门(java版)》等文章中的操作吗?那时咱们并没有添加任何与采样有关的配置 , 但是每次请求都能在Jaeger的web页面上查到对应的trace , 也就是说所有请求全部被采样了 , 这是为啥?
  • 如果配置文件中没有采样相关的内容 , 那么默认使用的就是远程配置 , 具体的信息就在jaeger的all-in-one容器中 , 执行下面这个命令 , 就能看到远程采样配置:
docker exec jaeger cat /etc/jaeger/sampling_strategies.json
  • 上述命令可以看到sampling_strategies.json的内容如下 , 原来服务端的配置是比例采样 , 不过比例是百分之百 , 这就能解释为何所有请求都能在Jaeger的web页面查到trace信息了:
{"default_strategy": {"type": "probabilistic","param": 1}}
  • 至此 , 采样配置实战已经完成 , 希望能给您提供一些参考 , 辅助您针对实际情况定制更加合适的采样策略
你不孤单 , 欣宸原创一路相伴
  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 数据库+中间件系列
  6. DevOps系列
欢迎关注公众号:程序员欣宸微信搜索「程序员欣宸」 , 我是欣宸 , 期待与您一同畅游Java世界...
https://github.com/zq2599/blog_demos