在微服务环境中,我看到通过整个业务流程中的所有微服务实例跟踪请求有两个主要好处。
- 查找服务实例之间或之中的延迟差距
- 寻找失败的根源,无论是技术上的还是与商业案例有关的
Zipkin有一个工具可以解决第一个问题。但是如何使用跟踪来揭示微服务环境中的故障?我绝对想跟踪所有受错误影响的跨度,但不是每个请求都没有出错。正如这里提到的,可以使用自定义采样器。
或者,您可以注册自己的 Sampler bean 定义并以编程方式决定应该对哪些请求进行采样。您可以对要跟踪的内容做出更明智的选择,例如,忽略成功的请求,也许检查某个组件是否处于错误状态,或者其他任何事情。
所以我试图实现它,但它不起作用或者我用错了。因此,正如博客文章所建议的那样,我注册了自己的 Sampler:
@Bean
Sampler customSampler() {
return new Sampler() {
@Override
public boolean isSampled(Span span) {
boolean isErrorSpan = false;
for(String tagKey : span.tags().keySet()){
if(tagKey.startsWith("error_")){
isErrorSpan = true;
}
}
return isErrorSpan ;
}
};
}
在我的控制器中,我创建了一个新的 Span,如果引发异常,它将被标记为错误
private final Tracer tracer;
@Autowired
public DemoController(Tracer tracer) {
this.tracer = tracer;
}
@RequestMapping(value = "/calc/{i}")
public String calc(@PathVariable String i){
Span span = null;
try {
span = this.tracer.createSpan("my_business_logic");
return "1 / " + i + " = " + new Float(1.0 / Integer.parseInt(i)).toString();
}catch(Exception ex){
log.error(ex.getMessage(), ex);
span.logEvent("ERROR: " + ex.getMessage());
this.tracer.addTag("error_" + ex.hashCode(), ex.getMessage());
throw ex;
}
finally{
this.tracer.close(span);
}
}
现在,这行不通。如果我请求 /calc/a,则在 Controller 方法抛出 NumberFormatException 之前调用方法 Sampler.isSampled(Span)。这意味着,当 isSampled() 检查 Span 时,它还没有标签。并且在该过程的后期不会再次调用 Sampler 方法。只有当我打开采样器并允许对每个跨度进行采样时,我才会稍后在 Zipkin 中看到我标记的错误跨度。在这种情况下, Sampler.isSampled(Span) 只被调用了 1 次,但 HttpZipkinSpanReporter.report(Span) 被执行了 3 次。
那么用例会是什么样子,只传输具有错误跨度的跟踪?这甚至是用任意“error_”标签标记跨度的正确方法吗?