背景
当 2 个进程之间进行交互时,span 传递的上下文就会中断,需要有一种机制,在 RPC 期间,保持链路跟踪
思路
在 RPC 调用时,将必要的 Span 上下文数据作为附带信息传递给对方进程,在对方接收时识别附带的信息,并进行解码恢复 Span 上下文环境
TextMapPropagator
- TextMapPropagator 定义了 2 个方法
- inject 方法用于将当前上文环境数据注入到远程上下文环境中
- extract 方法用于在接收端数据时恢复上下文环境
- TextMapSetter 用于对目标对象设置传播字段属性值
- TextMapGetter 用于对目标对象获取传播字段属性值
接口定义
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
| public interface TextMapPropagator {
Collection<String> fields();
<C> void inject(Context context, @Nullable C carrier, TextMapSetter<C> setter);
<C> Context extract(Context context, @Nullable C carrier, TextMapGetter<C> getter); }
public interface TextMapSetter<C> {
void set(@Nullable C carrier, String key, String value); }
public interface TextMapGetter<C> {
Iterable<String> keys(C carrier);
@Nullable String get(@Nullable C carrier, String key); }
|
接口实现示例
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
| public class DemoPropagator implements TextMapPropagator { private static final String FIELD = "X-demo-field"; private static final ContextKey<Long> PROPAGATION_START_KEY = ContextKey.named("propagation.start");
@Override public List<String> fields() { return Collections.singletonList(FIELD); }
@Override public <C> void inject(Context context, C carrier, TextMapSetter<C> setter) { Long propagationStart = context.get(PROPAGATION_START_KEY); if (propagationStart == null) { propagationStart = System.currentTimeMillis(); } setter.set(carrier, FIELD, String.valueOf(propagationStart)); }
@Override public <C> Context extract(Context context, C carrier, TextMapGetter<C> getter) { String propagationStart = getter.get(carrier, FIELD); if (propagationStart != null) { return context.with(PROPAGATION_START_KEY, Long.valueOf(propagationStart)); } else { return context; } } }
|
ContextPropagators