Jaeger-2.客户端使用 (Java版本)
主要用到了opentracing相关的jar包,而且用到了jaeger的java客户端实现。
一段简单的代码
首先创建一个简单的loveyou
类,里面有一个简单的方法hello
。本部分之与OpenTracing有关,与Jaeger关系并不是很大。在hello
方法体的前后,加入几行简单的代码,主要是根据OpenTracing规范定义的api进行一些调用信息等内容的添加。
public class LoveYou {
Tracer tracer;
public LoveYou() {
tracer = JaegerTracerHelper.initTracer("loveYouService");
}
public void hello(String name) {
Span span = tracer.buildSpan("hello").start();
span.setTag("name", name);
System.out.println("Hello " + name);
span.log("Love service say hello to " + name);
span.finish();
}
public static void main(String[] args) {
new LoveYou().hello("小姐姐味道");
}
}
代码主要加入了以下几个重要的信息。
1、构建了一个新的span
,每个span有三个id:rootid、parentid、id。它们构成了树状调用链的每个具体节点。
2、给新加的span添加了一个tag
信息,用来进行一些自定义标识。tag有一些标准的清单,但也可以自定义。
3、给新加的span添加了log。log信息会附着
在信息span上,一块被收集起来,仅定义一些比较重要的信息,包括异常栈等。一些不重要的信息不建议使用log,它会占用大量存储空间。
执行代码后,可以在jaeger的ui端看到这次的调用信息。如下:
构建jaeger实现
我们的OpenTracing数据是如何构建,并发送到Jaeger的server端呢?就是通过下面的代码完成的。
public class JaegerTracerHelper {
public static JaegerTracer initTracer(String service) {final String endPoint = "http://10.30.94.8:14268/api/traces";final CompositeReporter compositeReporter = new CompositeReporter(new RemoteReporter.Builder().withSender(new HttpSender.Builder(endPoint).build()).build(),new LoggingReporter());
final Metrics metrics = new Metrics(new NoopMetricsFactory());
JaegerTracer.Builder builder = new JaegerTracer.Builder(service).withReporter(compositeReporter).withMetrics(metrics).withExpandExceptionLogs().withSampler(new ConstSampler(true));
return builder.build();
}
}
实现一个2层深度的链
以上代码,仅产生了一个span,也就是一个方法调用。接下来,我们看一下如何完成一个多层的调用链条。接下来还是要修改LoveYou类。我们把调用方法hello
拆解一下,拆成dispatch
和hello
两个方法,并在hello方法里sleep一秒钟。
期望生成两条trace信息。
dispatch
public void dispatch(String cmd, String content) {
Span span = tracer.buildSpan("dispatch").start();
tracer.activateSpan(span);
if (cmd.equals("hello")) {
this.hello(content);
}
if (null != span) {
span.setTag("cmd", cmd);
span.finish();
}
}
hello
public void hello(String name) {Span span = tracer.buildSpan("hello").start();
tracer.activateSpan(span);
System.out.println("Hello " + name);
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(1));
} catch (InterruptedException e) {
e.printStackTrace();
}
span.setTag("name", name);
span.log("Love service say hello to " + name);
span.finish();
}
与示例一不同的是,每次生成span之后,我们还要将其激活一下
scope
中。这样,链条就串起来了。
以下是程序运行后的效果。
采样
有时候,我们的服务QPS非常高,瞬间能够生成大量的trace信息。这些信息是非常相近的,且会给存储产生很大的压力。
如果不需要统计一些QPS之类的信息,就可以使用sampler,仅收集部分trace。
还记得我们使用javaapi构建的jaeger实例么?其中,有这么一行代码:
.withSampler(new ConstSampler(true))
这就是最简单的采样
,意思是收集所有的信息。jaeger支持四种不同的采样类型。
Constant
这是一个布尔开关,如果sampler.param=1
,则代表收集所有的trace,如果为0
,则代表什么都不收集。
Probabilistic
基于概率进行采样,比如sampler.param=0.1,则代表有1/10的trace将被收集。
Rate Limiting
限流方式,使用令牌桶限流。 sampler.param=2.0
则代表每秒有2个trace被收集,超出的将被抛弃。
Remote
通过远程配置方式配置,这也是默认的方式。比如在Collector中配置strategies.json
{
"service_strategies": [
{
"service": "foo",
"type": "probabilistic",
"param": 0.8,
"operation_strategies": [
{
"operation": "op1",
"type": "probabilistic",
"param": 0.2
},
{
"operation": "op2",
"type": "probabilistic",
"param": 0.4
}
]
},
{
"service": "bar",
"type": "ratelimiting",
"param": 5
}
],
"default_strategy": {
"type": "probabilistic",
"param": 0.5
}
}
通过OpenTracing的Api,可以很容易的实现调用链功能。但可以看到,由于存在各种各样的客户端,主要工作量就集中在对这些客户端的兼容上。比如线程池、SpringCloud、MQ、数据库连接池等等等等。
使用Aop可以省去一些编码和侵入,但可控制性会弱一些。
接下来,我们给一个简单的OkHttp+SpringBoot调用,也就是分布式应用,添加trace功能。
本文来自博客园,作者:洛神灬殇,转载请注明原文链接:https://www.cnblogs.com/liboware/p/12491916.html,任何足够先进的科技,都与魔法无异。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix