之前分析了sr,ss,接下来分析cr,cs 下面以okhttp client为例:
@Bean
public OkHttpClient okHttpClient(Brave brave) {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(
new BraveOkHttpRequestResponseInterceptor(
brave.clientRequestInterceptor(),
brave.clientResponseInterceptor(),
new DefaultSpanNameProvider()))
.build();
return client;
}
上面代码创建了OkHttpClient,并且织入了拦截器,在真正请求执行前、后触发。
下面看BraveOkHttpRequestResponseInterceptor的intercept方法
@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;
}
首先看前置处理:
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);
}
}
}
下面看后置处理:
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,它的使用方法如下:
//生成新的span
localTracer.startNewSpan("codec", "encode");
try {
//业务处理
} finally {
tracer.finishSpan();
}
localTracer可以嵌入业务代码,根据自己的业务需求添加,跟踪代码块比如file io操作,业务指标比如下单次数等。
总结
1.zipkin brave基于ServerRequestInterceptor、ServerResponseInterceptor、ClientRequestInterceptor、ClientResponseInterceptor四种拦截器来处理的。