Tracing Agent原理
以 User调用project-test-projectA为例
1 | http://ali03:8888/projectA/admin |
User -> Tomcat7 -> SpringMvc(projectA/{name})-> 线程内调用 -> FeignClient(projectB/{name})
EntrySpan
ContextManager.createEntrySpan()
TracingContext#createEntrySpan()
检测EntrySpan是否已创建,如果是,则不会创建新的EntrySpan,只是重新调用一下其start()方法即可1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30public AbstractSpan createEntrySpan(final String operationName) {
// 默认配置下,每个TraceSegment只能放300个Span
if (isLimitMechanismWorking()) {
NoopSpan span = new NoopSpan(); // 超过300就放NoopSan
return push(span); // 将Span记录到activeSpanStack栈中
}
AbstractSpan entrySpan;
TracingContext owner = this;
final AbstractSpan parentSpan = peek(); // 读取栈顶Span,即当前Span
final int parentSpanId = parentSpan == null ? -1 : parentSpan.getSpanId();
if (parentSpan != null && parentSpan.isEntry()) {
profilingRecheck(parentSpan, operationName);
// 更新operationName
parentSpan.setOperationName(operationName);
entrySpan = parentSpan;
// 重新调用start()方法,strart()方法会重置operationName之外的其他字段
return entrySpan.start();
} else {
// 新建EntrySpan对象,spanIdGenerator生成Span ID并递增
entrySpan = new EntrySpan(
spanIdGenerator++, parentSpanId,
operationName, owner
);
// 调用start方法,第一次调用start()方法会设置startTime
entrySpan.start();
// 将新建的Span添加到activeSpanStack栈的栈顶
return push(entrySpan);
}
}LocalSpan
ContextManager#createLocalSpan()
TracingContext#createLocalSpan()
1 | if (isLimitMechanismWorking()) { |
ExitSpan
ContextManager#createExitSpan()
TraingContext#createExitSpan()
1 | public AbstractSpan createExitSpan(final String operationName, final String remotePeer) { |
stopSpan()
ContextManager.stopSpan()
TracingContext#stopSpan()
会将当前activeSpanStack栈顶的Span关闭并出栈,同时整个activeSpanStack栈空了之后,会尝试关闭当前TraceSegment。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23public boolean stopSpan(AbstractSpan span) {
// 获取当前栈顶的Span对象
AbstractSpan lastSpan = peek();
if (lastSpan == span) { // 只能关闭当前活跃的Span对象,否则抛出异常
if (lastSpan instanceof AbstractTracingSpan) {
AbstractTracingSpan toFinishSpan = (AbstractTracingSpan) lastSpan;
//添加span到segment中 并记录结束时间
if (toFinishSpan.finish(segment)) { // 尝试关闭Span
// 当Span完全关闭之后,会将其出栈(即从activeSpanStack中删除)
pop();
}
} else {
pop();
}
} else {
throw new IllegalStateException("Stopping the unexpected span = " + span);
}
//如果该节点是最后一个节点
finish();
return activeSpanStack.isEmpty();
}关闭TraceSegment
放入内存队列中,等待发送collector1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24private void finish() {
if (isRunningInAsyncMode) {
asyncFinishLock.lock();
}
try {
boolean isFinishedInMainThread = activeSpanStack.isEmpty() && running;
if (isFinishedInMainThread) {
/*
* Notify after tracing finished in the main thread.
*/
TracingThreadListenerManager.notifyFinish(this);
}
//TraceSegmentServiceClient#afterFinished()放入内存队列中
if (isFinishedInMainThread && (!isRunningInAsyncMode || asyncSpanCounter == 0)) {
TraceSegment finishedSegment = segment.finish(isLimitMechanismWorking());
TracingContext.ListenerManager.notifyFinish(finishedSegment);
running = false;
}
} finally {
if (isRunningInAsyncMode) {
asyncFinishLock.unlock();
}
}
}
扫描二维码,分享此文章