以前分析了sr,ss,接下來分析cr,cs 下面以okhttp client爲例:ide
@Bean public OkHttpClient okHttpClient(Brave brave) { OkHttpClient client = new OkHttpClient.Builder() .addInterceptor( new BraveOkHttpRequestResponseInterceptor( brave.clientRequestInterceptor(), brave.clientResponseInterceptor(), new DefaultSpanNameProvider())) .build(); return client; }
上面代碼建立了OkHttpClient,而且織入了攔截器,在真正請求執行前、後觸發。ui
下面看BraveOkHttpRequestResponseInterceptor的intercept方法this
@Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Request.Builder builder = request.newBuilder(); OkHttpRequest okHttpRequest = new OkHttpRequest(builder, request); //前置處理 clientRequestInterceptor.handle(new HttpClientRequestAdapter(okHttpRequest, spanNameProvider)); if(request.url()!=null&&request.url().query()!=null){ clientTracer.submitBinaryAnnotation("params",request.url().query()); } //真正的請求處理 Response response = chain.proceed(builder.build()); //後置處理 clientResponseInterceptor.handle(new HttpClientResponseAdapter(new OkHttpResponse(response))); return response; }
首先看前置處理:url
public class ClientRequestInterceptor { private final ClientTracer clientTracer; public ClientRequestInterceptor(ClientTracer clientTracer) { this.clientTracer = checkNotNull(clientTracer, "Null clientTracer"); } /** * Handles outgoing request. * * @param adapter The adapter deals with implementation specific details. */ public void handle(ClientRequestAdapter adapter) { //經過clientTracer建立SpanId,對應有ServerTracer SpanId spanId = clientTracer.startNewSpan(adapter.getSpanName()); if (spanId == null) { // We will not trace this request. adapter.addSpanIdToRequest(null); } else { //將span信息放入header中,便於傳遞 adapter.addSpanIdToRequest(spanId); //jiang將uri信息存入binaryAnnotation for (KeyValueAnnotation annotation : adapter.requestAnnotations()) { clientTracer.submitBinaryAnnotation(annotation.getKey(), annotation.getValue()); } //添加cs annotation到span recordClientSentAnnotations(adapter.serverAddress()); } } private void recordClientSentAnnotations(Endpoint serverAddress) { if (serverAddress == null) { clientTracer.setClientSent(); } else { clientTracer.setClientSent(serverAddress); } } }
下面看後置處理:spa
public class ClientResponseInterceptor { private final ClientTracer clientTracer; public ClientResponseInterceptor(ClientTracer clientTracer) { this.clientTracer = checkNotNull(clientTracer, "Null clientTracer"); } /** * Handle a client response. * * @param adapter Adapter that hides implementation details. */ public void handle(ClientResponseAdapter adapter) { try { //將響應碼添加到BinaryAnnotation for (KeyValueAnnotation annotation : adapter.responseAnnotations()) { clientTracer.submitBinaryAnnotation(annotation.getKey(), annotation.getValue()); } } finally { //設置cr狀態,而且提交span clientTracer.setClientReceived(); } } }
其實還有一種trace,那就是lc,即localTracer,它的使用方法以下:code
//生成新的span localTracer.startNewSpan("codec", "encode"); try { //業務處理 } finally { tracer.finishSpan(); }
localTracer能夠嵌入業務代碼,根據本身的業務需求添加,跟蹤代碼塊好比file io操做,業務指標好比下單次數等。server
1.zipkin brave基於ServerRequestInterceptor、ServerResponseInterceptor、ClientRequestInterceptor、ClientResponseInterceptor四種攔截器來處理的。ip