zipkin-java-brave源碼分析(三)

什麼是brave

brave是zipkin官方提供的java版本zipkin-client實現java

brave提供的功能

<modules>
    <module>brave-core</module>
    <module>brave-benchmarks</module>
    <module>brave-http</module>
    <module>brave-core-spring</module>
    <module>brave-resteasy-spring</module>
    <module>brave-resteasy3-spring</module>
    <module>brave-spancollector-http</module>
    <module>brave-spancollector-scribe</module>
    <module>brave-spancollector-kafka</module>
    <module>brave-spancollector-local</module>
    <module>brave-sampler-zookeeper</module>
    <module>brave-jersey</module>
    <module>brave-jersey2</module>
    <module>brave-jaxrs2</module>
    <module>brave-grpc</module>
    <module>brave-apache-http-interceptors</module>
    <module>brave-spring-web-servlet-interceptor</module>
    <module>brave-spring-resttemplate-interceptors</module>
    <module>brave-mysql</module>
    <module>brave-web-servlet-filter</module>
    <module>brave-okhttp</module>
  </modules>

基於http提供brave源碼分析

brave-spancollector-http

image 提供httpCollector收集器mysql

brave-web-servlet-filter

image 基於http請求提供過濾器git

brave-apache-http-interceptors

image 基於apache-http-client發起氣球提供攔截器github

基於springboot啓動

step1配置

  • 針對collector的SpanCollector
  • 針對http請求的filter BraveServletFilter
  • 針對數據發送的Brave
  • 針對http-client請求的攔截器BraveHttpRequestInterceptor,BraveHttpResponseInterceptor
@Configuration
public class ZipkinConfig {
    //span(一次請求信息或者一次鏈路調用)信息收集器  
    @Bean  
    public SpanCollector spanCollector() {  
        Config config = HttpSpanCollector.Config.builder()  
                .compressionEnabled(false)// 默認false,span在transport以前是否會被gzipped  
                .connectTimeout(5000)  
                .flushInterval(1)  
                .readTimeout(6000)  
                .build();  
        return HttpSpanCollector.create("http://localhost:9411", config, new EmptySpanCollectorMetricsHandler());  
    }  
      
    //做爲各調用鏈路,只須要負責將指定格式的數據發送給zipkin  
    @Bean  
    public Brave brave(SpanCollector spanCollector){  
        Builder builder = new Builder("service1");//指定serviceName  
        builder.spanCollector(spanCollector);  
        builder.traceSampler(Sampler.create(1));//採集率  
        return builder.build();  
    }  
  
  
    //設置server的(服務端收到請求和服務端完成處理,並將結果發送給客戶端)過濾器  
    @Bean  
    public BraveServletFilter braveServletFilter(Brave brave) {  
        BraveServletFilter filter = new BraveServletFilter(brave.serverRequestInterceptor(),  
                brave.serverResponseInterceptor(), new DefaultSpanNameProvider());  
        return filter;  
    }  
      
    //設置client的(發起請求和獲取到服務端返回信息)攔截器  
    @Bean  
    public CloseableHttpClient okHttpClient(Brave brave){  
       CloseableHttpClient httpclient = HttpClients.custom()
                .addInterceptorFirst(new BraveHttpRequestInterceptor(brave.clientRequestInterceptor(), new DefaultSpanNameProvider()))
                .addInterceptorFirst(new BraveHttpResponseInterceptor(brave.clientResponseInterceptor()))
                .build();
        return httpclient;  
    }
    
}

基於http發起請求服務端處理

post or get url : http://localhost/service1web

相關代碼請查看 zipkin簡單介紹及環境搭建(一)spring

流程圖 brave-http-collector-receive pointsql

針對請求,若是Sampledheader包含(X-B3-Sampled)會獲取header中的ParentSpanId,TraceId,SpanId直接返回,否者會認爲這是一個新的請求會構建Span
HttpServerRequestAdapter.getTraceData()
public TraceData getTraceData() {
        final String sampled = serverRequest.getHttpHeaderValue(BraveHttpHeaders.Sampled.getName());
        if (sampled != null) {
            if (sampled.equals("0") || sampled.toLowerCase().equals("false")) {
                return TraceData.builder().sample(false).build();
            } else {
                final String parentSpanId = serverRequest.getHttpHeaderValue(BraveHttpHeaders.ParentSpanId.getName());
                final String traceId = serverRequest.getHttpHeaderValue(BraveHttpHeaders.TraceId.getName());
                final String spanId = serverRequest.getHttpHeaderValue(BraveHttpHeaders.SpanId.getName());

                if (traceId != null && spanId != null) {
                    SpanId span = getSpanId(traceId, spanId, parentSpanId);
                    return TraceData.builder().sample(true).spanId(span).build();
                }
            }
        }
        return TraceData.builder().build();
    }
針對請求的採樣
traceSampler().isSampled(newTraceId),沒有使用zk狀況下CountingSampler來決定
public synchronized boolean isSampled(long traceIdIgnored) {
    boolean result = sampleDecisions.get(i++);
    if (i == 100) i = 0;
    return result;
  }

基於apache-http發起請求

流程圖 brave-http-client-sendapache

如何在代碼中添加本身的annotation or binaryAnnotation

直接注入Brave便可 ps(不建議這樣作,代碼侵入。 zipkin不建議添加大量數據)springboot

@RestController
public class ZipkinBraveController {

    @Autowired
    private CloseableHttpClient httpClient;
    @Autowired
    private com.github.kristofa.brave.Brave brave;
    
    @GetMapping("/service1")
    public String myboot() throws Exception {
        brave.serverTracer().submitBinaryAnnotation("狀態", "成功"); 
        Thread.sleep(100);//100ms
        HttpGet get = new HttpGet("http://localhost:81/test");
        CloseableHttpResponse execute = httpClient.execute(get);
        /*
         * 一、執行execute()的先後,會執行相應的攔截器(cs,cr)
         * 二、請求在被調用方執行的先後,也會執行相應的攔截器(sr,ss)
         */
        return EntityUtils.toString(execute.getEntity(), "utf-8");
    }
}

ps

  • 若是collector要使用kafka直接切換spanController便可,須要server端進行對應配置
client端
        KafkaSpanCollector.create(KafkaSpanCollector.Config.builder().kafkaProperties(null).build(), new EmptySpanCollectorMetricsHandler());

server端須要配置kafka配置
final class KafkaZooKeeperSetCondition extends SpringBootCondition {
  static final String PROPERTY_NAME = "zipkin.collector.kafka.zookeeper";

  @Override
  public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata a) {
    String kafkaZookeeper = context.getEnvironment().getProperty(PROPERTY_NAME);
    return kafkaZookeeper == null || kafkaZookeeper.isEmpty() ?
        ConditionOutcome.noMatch(PROPERTY_NAME + " isn't set") :
        ConditionOutcome.match();
  }
}

連接

相關文章
相關標籤/搜索