Spring Sleuth - 追踪失败

时间:2016-11-10 10:36:03

标签: spring spring-cloud-sleuth

在微服务环境中,我看到在整个业务流程中通过所有微服务实例跟踪请求的两个主要好处。

  1. 查找服务实例之间或服务实例之间的延迟差距
  2. 找出失败的根源,无论是技术还是业务案例
  3. 使用Zipkin,有一个工具可以解决第一个问题。但是如何使用跟踪来揭示微服务领域的失败?我绝对想要追踪所有错误折磨的跨度,但不是每个请求都没有出错。 如上所述here,可以使用自定义采样器。

      

    或者,您可以注册自己的Sampler bean定义,并以编程方式决定应该对哪些请求进行采样。您可以更明智地选择要跟踪的内容,例如,忽略成功的请求,可能检查某个组件是否处于错误状态,或者其他任何内容。

    所以我试图实现它,但它不起作用或我用错了。 因此,正如博客文章所示,我注册了自己的采样器:

        @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)仅被调用一次,但HttpZipkinSpanReporter.report(Span)被执行了3次。

    那么用例是什么样的,只传输具有错误跨度的痕迹?这是使用任意“error_”标记标记跨度的正确方法吗?

1 个答案:

答案 0 :(得分:0)

采样决定是为了追踪。这意味着当第一个请求进入并创建范围时,您必须做出决定。此时您没有任何标签/行李,因此您不能依赖标签的内容来做出此决定。这是一种错误的做法。

你正在采取一种非常自定义的方法。如果您想采用这种方式(不建议这样做),您可以创建ValueLstNode m_ValueLstNode = ValueLstNode::GetInstance(); m_ValueLstNode[0] = NULL; - https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanReporter.java#L30的自定义实施。 SpanReporter是向zipkin发送跨度的人。您可以创建一个包装现有SpanReporter实现的实现,并仅在某些标记值匹配时将执行委托给它。但从我的角度来看,这听起来并不合适。