首页 > 其他分享 >如何使用Spring Cloud Sleuth

如何使用Spring Cloud Sleuth

时间:2022-12-02 14:01:43浏览次数:37  
标签:Sleuth span 批注 创建 使用 newSpan Spring 跨度 Cloud

如何使用Spring Cloud Sleuth_显式

本节将更详细地介绍如何使用Spring Cloud Sleuth。 它涵盖了诸如使用 Spring Cloud Sleuth API 或通过注释控制跨度生命周期等主题。 我们还介绍了一些Spring Cloud Sleuth最佳实践。

如果您从Spring Cloud Sleuth开始,则在进入本节之前,您可能应该阅读入门指南。

1. 使用春云侦探的 API 跨越生命周期

其模块中的春云侦探核心包含由跟踪器实现的所有必要接口。 该项目带有OpenZipkin Brave实现。 您可以通过查看来检查跟踪器如何桥接到侦探的 API。​​api​​​​org.springframework.cloud.sleuth.brave.bridge​

最常用的接口是:

  • ​org.springframework.cloud.sleuth.Tracer​​- 使用跟踪器,可以创建捕获请求关键路径的根跨度。
  • ​org.springframework.cloud.sleuth.Span​​- 跨度是需要启动和停止的单个工作单元。 包含计时信息以及事件和标记。

您也可以直接使用跟踪器实现的 API。

让我们看一下以下 Span 生命周期操作。

  • 开始:启动跨度时,将分配其名称并记录开始时间戳。
  • end:跨度完成(记录跨度的结束时间),如果跨度被采样,则有资格收集(例如到 Zipkin)。
  • 继续:跨度继续,例如在另一个线程中。
  • 使用显式父项创建:您可以创建新的范围并为其设置显式父项。

春云侦探为您创建一个实例。 为了使用它,您可以自动连线它。​​Tracer​

1.1. 创建和结束跨度

您可以使用 手动创建跨度,如以下示例所示:​​Tracer​

// Start a span. If there was a span present in this thread it will become
// the `newSpan`'s parent.
Span newSpan = this.tracer.nextSpan().name("calculateTax");
try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan.start())) {
// ...
// You can tag a span
newSpan.tag("taxValue", taxValue);
// ...
// You can log an event on a span
newSpan.event("taxCalculated");
}
finally {
// Once done remember to end the span. This will allow collecting
// the span to send it to a distributed tracing system e.g. Zipkin
newSpan.end();
}

在前面的示例中,我们可以看到如何创建跨度的新实例。 如果此线程中已存在跨度,则它将成为新跨度的父级。

创建范围后始终清洁。

如果范围包含大于 50 个字符的名称,则该名称将被截断为 50 个字符。 你的名字必须明确和具体。 大牌会导致延迟问题,有时甚至会导致异常。

1.2. 连续跨度

有时,您不想创建一个新的跨度,但想要继续一个。 这种情况的示例可能如下所示:

  • AOP:如果在达到一个方面之前已经创建了一个跨度,您可能不希望创建新跨度。

要继续跨度,您可以将跨度存储在一个线程中,然后将其传递给另一个线程,如下例所示。

Span spanFromThreadX = this.tracer.nextSpan().name("calculateTax");
try (Tracer.SpanInScope ws = this.tracer.withSpan(spanFromThreadX.start())) {
executorService.submit(() -> {
// Pass the span from thread X
Span continuedSpan = spanFromThreadX;
// ...
// You can tag a span
continuedSpan.tag("taxValue", taxValue);
// ...
// You can log an event on a span
continuedSpan.event("taxCalculated");
}).get();
}
finally {
spanFromThreadX.end();
}

1.3. 使用显式父级创建范围

您可能希望开始一个新的跨度,并提供该跨度的显式父级。 假设跨度的父级位于一个线程中,并且您希望在另一个线程中启动新的跨度。 每当您调用时,它都会创建一个范围来引用当前范围内的范围。 可以将范围放在作用域中,然后调用,如以下示例所示:​​Tracer.nextSpan()​​​​Tracer.nextSpan()​

// let's assume that we're in a thread Y and we've received
// the `initialSpan` from thread X. `initialSpan` will be the parent
// of the `newSpan`
Span newSpan = null;
try (Tracer.SpanInScope ws = this.tracer.withSpan(initialSpan)) {
newSpan = this.tracer.nextSpan().name("calculateCommission");
// ...
// You can tag a span
newSpan.tag("commissionValue", commissionValue);
// ...
// You can log an event on a span
newSpan.event("commissionCalculated");
}
finally {
// Once done remember to end the span. This will allow collecting
// the span to send it to e.g. Zipkin. The tags and events set on the
// newSpan will not be present on the parent
if (newSpan != null) {
newSpan.end();
}
}

创建这样的跨度后,您必须完成它。 否则不报告(例如向Zipkin报告)。

您还可以使用版本显式提供父跨度。​​Tracer.nextSpan(Span parentSpan)​

2. 命名跨度

选择范围名称并非易事。 范围名称应描述操作名称。 名称应为低基数,因此不应包含标识符。

由于正在进行大量检测,因此某些跨度名称是人为的:

  • ​controller-method-name​​当由方法名称为controllerMethodName
  • ​async​​对于使用包装和接口完成的异步操作。CallableRunnable
  • 方法批注返回类的简单名称。@Scheduled

幸运的是,对于异步处理,您可以提供显式命名。

2.1.@SpanName注解

您可以使用注释显式命名范围,如以下示例所示:​​@SpanName​

@SpanName("calculateTax")
class TaxCountingRunnable implements Runnable {

@Override
public void run() {
// perform logic
}

}

在这种情况下,当以下列方式处理时,范围被命名为:​​calculateTax​

Runnable runnable = new TraceRunnable(this.tracer, spanNamer, new TaxCountingRunnable());
Future<?> future = executorService.submit(runnable);
// ... some additional logic ...
future.get();

2.2.toString()Method

创建单独的类是非常罕见的。 通常,创建这些类的匿名实例。 不能批注此类类。 为了克服这个限制,如果存在noannotation,我们检查类是否具有该方法的自定义实现。​​Runnable​​​​Callable​​​​@SpanName​​​​toString()​

运行此类代码会导致创建名为 span 的范围,如以下示例所示:​​calculateTax​

Runnable runnable = new TraceRunnable(this.tracer, spanNamer, new Runnable() {
@Override
public void run() {
// perform logic
}

@Override
public String toString() {
return "calculateTax";
}
});
Future<?> future = executorService.submit(runnable);
// ... some additional logic ...
future.get();

3. 使用注释管理跨度

使用批注管理跨度有很多很好的理由,包括:

  • 与 API 无关意味着跨度协作。 使用批注允许用户添加到跨度,而不需要库依赖跨度 API。 这样做可以让 Sleuth 更改其核心 API,以减少对用户代码的影响。
  • 减少了基本跨度操作的表面积。 如果没有此功能,则必须使用 span api,该 API 具有可能不正确使用的生命周期命令。 通过仅公开范围、标记和日志功能,您可以在不意外中断跨度生命周期的情况下进行协作。
  • 与运行时生成的代码协作。 使用Spring Data和Feign等库,接口的实现是在运行时生成的。 因此,对象的跨度包装很乏味。 现在,您可以提供接口注释和这些接口的参数。

3.1. 创建新跨度

如果不想手动创建局部范围,可以使用注释。 此外,我们还提供注释以自动方式添加标签。​​@NewSpan​​​​@SpanTag​

现在我们可以考虑一些用法示例。

@NewSpan
void testMethod();

在没有任何参数的情况下批注方法会导致创建一个新范围,其名称等于批注的方法名称。

@NewSpan("customNameOnTestMethod4")
void testMethod4();

如果在批注中提供值(直接或通过设置参数),则创建的范围会将提供的值作为名称。​​name​

// method declaration
@NewSpan(name = "customNameOnTestMethod5")
void testMethod5(@SpanTag("testTag") String param);

// and method execution
this.testBean.testMethod5("test");

您可以组合名称和标签。 让我们关注后者。 在这种情况下,批注方法的参数运行时值的值将成为标记的值。 在我们的示例中,标签键是,标签值是。​​testTag​​​​test​

@NewSpan(name = "customNameOnTestMethod3")
@Override
public void testMethod3() {
}

您可以在类和接口上放置注释。 如果您覆盖接口的方法并为注释提供不同的值,则最具体的值获胜(在本例中为 set)。​​@NewSpan​​​​@NewSpan​​​​customNameOnTestMethod3​

3.2. 连续跨度

如果要向现有范围添加标记和注释,可以使用注释,如以下示例所示:​​@ContinueSpan​

// method declaration
@ContinueSpan(log = "testMethod11")
void testMethod11(@SpanTag("testTag11") String param);

// method execution
this.testBean.testMethod11("test");
this.testBean.testMethod13();

(请注意,与注释相比,您还可以使用参数添加日志。​​@NewSpan​​​​log​

这样,跨度就会继续,并且:

  • 已创建命名的日志条目。testMethod11.beforetestMethod11.after
  • 如果引发异常,则还会创建日志条目 namedis。testMethod11.afterFailure
  • 创建具有键 of 和值 of 的标记。testTag11test

3.3. 高级标签设置

有 3 种不同的方法可以将标签添加到范围。 所有这些都由注释控制。 优先级如下:​​SpanTag​

  1. 尝试使用类型的 bean 和提供的名称。TagValueResolver
  2. 如果尚未提供 Bean 名称,请尝试计算表达式。 我们寻找阿豆。 默认实现使用 SPEL 表达式解析。重要只能引用 SPEL 表达式中的属性。 由于安全约束,不允许方法执行。TagValueExpressionResolver
  3. 如果我们找不到任何要计算的表达式,则返回参数的值。toString()

3.3.1. 自定义提取器

以下方法的标记值由接口的实现计算。 它的类名必须作为属性的值传递。​​TagValueResolver​​​​resolver​

请考虑以下带批注的方法:

@NewSpan
public void getAnnotationForTagValueResolver(
@SpanTag(key = "test", resolver = TagValueResolver.class) String test) {
}

现在进一步考虑以下 Bean 实现:​​TagValueResolver​

@Bean(name = "myCustomTagValueResolver")
public TagValueResolver tagValueResolver() {
return parameter -> "Value from myCustomTagValueResolver";
}

前面的两个示例导致将标记值设置为等于。​​Value from myCustomTagValueResolver​

3.3.2. 解析值的表达式

请考虑以下带批注的方法:

@NewSpan
public void getAnnotationForTagValueExpression(
@SpanTag(key = "test", expression = "'hello' + ' characters'") String test) {
}

没有自定义实现会导致计算 SPEL 表达式,并且在跨度上设置了值为 of 的标记。 如果要使用其他表达式解析机制,可以创建自己的 Bean 实现。​​TagValueExpressionResolver​​​​hello characters​

3.3.3. 使用toString() 方法

请考虑以下带批注的方法:

@NewSpan
public void getAnnotationForArgumentToString(@SpanTag("test") Long param) {
}

使用值 of 运行上述方法,以设置具有 String 值为 的标记。​​15​​​​"15"​

4. 接下来要读什么

您现在应该了解如何使用Spring Cloud Sleuth以及应遵循的一些最佳实践。 您现在可以继续了解特定的Spring CloudSleuth功能,或者您可以跳过并阅读Spring Cloud Sleuth中可用的集成。

标签:Sleuth,span,批注,创建,使用,newSpan,Spring,跨度,Cloud
From: https://blog.51cto.com/u_15326439/5906979

相关文章

  • Spring Cloud Sleuth的特点
    本节深入探讨春云侦探的细节。在这里,您可以了解您可能想要使用和自定义的主要功能。如果您还没有这样做,您可能需要阅读“入门.html​”和“使用.html”部分,以便您在基础知......
  • Spring Cloud Schema Registry
    介绍当组织具有基于消息传递的发布/订阅体系结构并且多个创建者和使用者微服务相互通信时,所有这些微服务通常需要就基于架构的协定达成一致。当这样的架构需要发展以适应新......
  • 10分钟使用CXF和SPRING创建REST webservice应用
    CXF跟spring联合起来,搞restwebservice的确很方便的.下面快速学习下,用到的是CXF,SPRING和MAVEN1MAVEN配置...<dependency><groupId>org.spri......
  • spring接口重放过滤问题
    1、定义注释importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.anno......
  • Spring Cloud OpenFeign
    该项目通过自动配置为SpringBoot应用程序提供OpenFeign集成并绑定到Spring环境和其他Spring编程模型习语。1.声明式REST客户端:假装Feign是一个声明式Web服务......
  • 代码讲解spring中的singleton和prototype
    1.singleton配置中的bean定义可以看作是一个模板,容器会根据这个模板来构造对象。bean定义中的scope语义会决定:容器将根据这个模板构造多少对象实例,......
  • CXF spring jaxws:endpoint jaxws:server 区别 与 关系
    First,theyareallfortheserversideconfiguration.Second,jaxws:endpointiscomingfromJAXWSAPI,anditisusedtoconfiguretheo......
  • springIOC和AOP
    IOC(InverseofControl:控制反转)是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。Ioc在其他语言中也有应用,并非spring特有。Ioc容器是Spring用......
  • spring mvc中普通类获得request
    springmvc中,在控制层很容易获得request,response,但在其他层的话获得的话,其实必要性不大,但可以实现:在web.xml中加入<listener><list......
  • springsecurity中处理框架页
    X-Frame-Options响应头X-Frame-OptionsHTTP响应头是用来给浏览器指示允许一个页面可否在<frame>,</iframe>或者<object>中展现的标记。网站可以使用此功能,来确保自......