Span生命周期

优质
小牛编辑
157浏览
2023-12-01

您可以通过org.springframework.cloud.sleuth.Tracer接口在Span上执行以下操作:

  • 开始 - 当您启动一个span时,它的名称被分配,并且记录开始时间戳。
  • 关闭 - 跨度完成(记录跨度的结束时间),如果跨度可导出,则它将有资格收集到Zipkin。该跨度也从当前线程中移除。
  • 继续 - 将创建一个新的跨度实例,而它将是它继续的一个副本。
  • 分离 - 跨度不会停止或关闭。它只从当前线程中删除。
  • 使用显式父项创建 - 您可以创建一个新的跨度,并为其设置一个显式父级
提示Spring为您创建了一个Tracer的实例。为了使用它,你需要的只是自动连接它。

创建和关闭spans

您可以使用Tracer界面手动创建spans 。

// Start a span. If there was a span present in this thread it will become
// the `newSpan`'s parent.
Span newSpan = this.tracer.createSpan("calculateTax");
try {
	// ...
	// You can tag a span
	this.tracer.addTag("taxValue", taxValue);
	// ...
	// You can log an event on a span
	newSpan.logEvent("taxCalculated");
} finally {
	// Once done remember to close the span. This will allow collecting
	// the span to send it to Zipkin
	this.tracer.close(newSpan);
}

在这个例子中,我们可以看到如何创建一个新的跨度实例。假设这个线程中已经存在跨度,那么它将成为该跨度的父代。

重要创建跨度后始终清洁!如果要将其发送到Zipkin,请不要忘记关闭跨度。
重要如果您的span包含的名称大于50个字符,则该名称将被截断为50个字符。你的名字必须是明确而具体的。大名称导致延迟问题,有时甚至引发异常。

继续spans

有时你不想创建一个新的跨度,但你想继续。这种情况的例子可能是(当然这取决于用例):

  • AOP - 如果在达到方面之前已经创建了一个跨度,则可能不想创建一个新的跨度。
  • Hystrix - 执行Hystrix命令很可能是当前处理的逻辑部分。实际上,它只是一个技术实现细节,你不一定要反映在跟踪中作为一个单独的存在。

持续的跨度实例等于它继续的范围:

Span continuedSpan = this.tracer.continueSpan(spanToContinue);
assertThat(continuedSpan).isEqualTo(spanToContinue);

要继续跨度,您可以使用Tracer界面。

// let's assume that we're in a thread Y and we've received
// the `initialSpan` from thread X
Span continuedSpan = this.tracer.continueSpan(initialSpan);
try {
	// ...
	// You can tag a span
	this.tracer.addTag("taxValue", taxValue);
	// ...
	// You can log an event on a span
	continuedSpan.logEvent("taxCalculated");
} finally {
	// Once done remember to detach the span. That way you'll
	// safely remove it from the current thread without closing it
	this.tracer.detach(continuedSpan);
}
重要创建跨度后始终清洁!如果在一个线程(例如线程X)中开始了某些工作,并且正在等待其他线程(例如Y,Z)完成,请不要忘记分离跨距。那么线程Y,Z中的spans在工作结束时应该被分离。当收集结果时,螺纹X中的跨度应该被关闭。

用明确的父代创建spans

您可能想要开始一个新的跨度,并提供该跨度的显式父级。假设跨度的父项在一个线程中,并且要在另一个线程中启动一个新的跨度。Tracer接口的startSpan方法是您要查找的方法。

// 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 = this.tracer.createSpan("calculateCommission", initialSpan);
try {
	// ...
	// You can tag a span
	this.tracer.addTag("commissionValue", commissionValue);
	// ...
	// You can log an event on a span
	newSpan.logEvent("commissionCalculated");
} finally {
	// Once done remember to close the span. This will allow collecting
	// the span to send it to Zipkin. The tags and events set on the
	// newSpan will not be present on the parent
	this.tracer.close(newSpan);
}
重要创建这样一个跨度后,记得关闭它。否则,您将在您的日志中看到很多警告,其中有一个事实,即您在当前线程中存在一个跨度,而不是您要关闭的线程。更糟糕的是,您的spans不会正确关闭,因此不会收集到Zipkin。