brave本身没有对AsyncHttpClient提供类似于brave-okhttp的ClientRequestInterceptor和ClientResponseInterceptor,所以需要我们定制,而ServerRequestInterceptor和ServerResponseInterceptor是在BraveServletFilter部分直接指定就好了(这在任何client技术下都可以复用)。
实际上,ClientRequestInterceptor和ClientResponseInterceptor也是我们的定制点。
一、代码
基本参考第二十七章 springboot + zipkin(brave-okhttp实现)
1、service1
1.1、pom.xml
<!-- zipkin brave --> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-core</artifactId> <version>3.9.0</version> </dependency> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-spancollector-http</artifactId> <version>3.9.0</version> </dependency> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-web-servlet-filter</artifactId> <version>3.9.0</version> </dependency> <!-- async-http-client --> <dependency> <groupId>com.ning</groupId> <artifactId>async-http-client</artifactId> <version>1.9.31</version> </dependency>
1.2、ZipkinConfig
package com.xxx.service1.zipkin.brave.async; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.github.kristofa.brave.Brave; import com.github.kristofa.brave.EmptySpanCollectorMetricsHandler; import com.github.kristofa.brave.Sampler; import com.github.kristofa.brave.SpanCollector; import com.github.kristofa.brave.http.DefaultSpanNameProvider; import com.github.kristofa.brave.http.HttpSpanCollector; import com.github.kristofa.brave.servlet.BraveServletFilter; import com.ning.http.client.AsyncHttpClient; @Configuration public class ZipkinConfig { @Bean public SpanCollector spanCollector() { HttpSpanCollector.Config spanConfig = HttpSpanCollector.Config.builder() .compressionEnabled(false)//默认false,span在transport之前是否会被gzipped。 .connectTimeout(5000)//5s,默认10s .flushInterval(1)//1s .readTimeout(6000)//5s,默认60s .build(); return HttpSpanCollector.create("http://localhost:9411", spanConfig, new EmptySpanCollectorMetricsHandler()); } @Bean public Brave brave(SpanCollector spanCollector) { Brave.Builder builder = new Brave.Builder("asyn1 - service1 - 1");//指定serviceName builder.spanCollector(spanCollector); builder.traceSampler(Sampler.create(1));//采集率 return builder.build(); } @Bean public BraveServletFilter braveServletFilter(Brave brave) { /** * 设置sr、ss拦截器 */ return new BraveServletFilter(brave.serverRequestInterceptor(), brave.serverResponseInterceptor(), new DefaultSpanNameProvider()); } @Bean public AsyncHttpClient asyncHttpClient(){ return new AsyncHttpClient(); } }
说明:指定了serviceName:"asyn1 - service1 - 1"
1.3、ZipkinAsyncController
package com.xxx.service1.zipkin.brave.async; import java.net.URI; import java.util.concurrent.Future; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.github.kristofa.brave.Brave; import com.github.kristofa.brave.http.DefaultSpanNameProvider; import com.github.kristofa.brave.http.HttpClientRequest; import com.github.kristofa.brave.http.HttpClientRequestAdapter; import com.github.kristofa.brave.http.HttpClientResponseAdapter; import com.github.kristofa.brave.http.HttpResponse; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.Request; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @Api("zipkin brave async api") @RestController @RequestMapping("/zipkin/async/service1") public class ZipkinAsyncController { @Autowired private AsyncHttpClient asyncHttpClient; @Autowired private Brave brave; @ApiOperation("trace第一步") @RequestMapping(value = "/test1", method = RequestMethod.GET) public String myboot() { try { RequestBuilder builder = new RequestBuilder(); String url = "http://localhost:8032/zipkin/async/service2/test2"; builder.setUrl(url); Request request = builder.build(); clientRequestInterceptor(request); Future<Response> response = asyncHttpClient.executeRequest(request); clientResponseInterceptor(response.get()); return response.get().getResponseBody(); } catch (Exception e) { e.printStackTrace(); return ""; } } private void clientRequestInterceptor(Request request) { brave.clientRequestInterceptor().handle(new HttpClientRequestAdapter(new HttpClientRequest() { @Override public URI getUri() { return URI.create(request.getUrl()); } @Override public String getHttpMethod() { return request.getMethod(); } @Override public void addHeader(String headerKey, String headerValue) { request.getHeaders().add(headerKey, headerValue); } }, new DefaultSpanNameProvider())); } private void clientResponseInterceptor(Response response) { brave.clientResponseInterceptor().handle(new HttpClientResponseAdapter(new HttpResponse() { public int getHttpStatusCode() { return response.getStatusCode(); } })); } }
说明:
- clientRequestInterceptor(com.ning.http.client.Request request)
- 其实就是在做cs
- clientResponseInterceptor(com.ning.http.client.Response response)
- 其实就是在做cr
2、service2
2.1、pom.xml
<!-- zipkin brave --> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-core</artifactId> <version>3.9.0</version> </dependency> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-spancollector-http</artifactId> <version>3.9.0</version> </dependency> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-web-servlet-filter</artifactId> <version>3.9.0</version> </dependency> <!-- async-http-client --> <dependency> <groupId>com.ning</groupId> <artifactId>async-http-client</artifactId> <version>1.9.31</version> </dependency>
2.2、ZipkinConfig
package com.xxx.service1.zipkin.brave.async; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.github.kristofa.brave.Brave; import com.github.kristofa.brave.EmptySpanCollectorMetricsHandler; import com.github.kristofa.brave.Sampler; import com.github.kristofa.brave.SpanCollector; import com.github.kristofa.brave.http.DefaultSpanNameProvider; import com.github.kristofa.brave.http.HttpSpanCollector; import com.github.kristofa.brave.servlet.BraveServletFilter; import com.ning.http.client.AsyncHttpClient; @Configuration public class ZipkinConfig { @Bean public SpanCollector spanCollector() { HttpSpanCollector.Config spanConfig = HttpSpanCollector.Config.builder() .compressionEnabled(false)//默认false,span在transport之前是否会被gzipped。 .connectTimeout(5000)//5s,默认10s .flushInterval(1)//1s .readTimeout(6000)//5s,默认60s .build(); return HttpSpanCollector.create("http://localhost:9411", spanConfig, new EmptySpanCollectorMetricsHandler()); } @Bean public Brave brave(SpanCollector spanCollector) { Brave.Builder builder = new Brave.Builder("asyn2 - service2 - 2");//指定serviceName builder.spanCollector(spanCollector); builder.traceSampler(Sampler.create(1));//采集率 return builder.build(); } @Bean public BraveServletFilter braveServletFilter(Brave brave) { /** * 设置sr、ss拦截器 */ return new BraveServletFilter(brave.serverRequestInterceptor(), brave.serverResponseInterceptor(), new DefaultSpanNameProvider()); } @Bean public AsyncHttpClient asyncHttpClient(){ return new AsyncHttpClient(); } }
说明:指定了serviceName:"asyn2 - service2 - 2"
2.3、ZipkinAsyncController
package com.xxx.service2.zipkin.brave.async; import java.net.URI; import java.util.concurrent.Future; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.github.kristofa.brave.Brave; import com.github.kristofa.brave.http.DefaultSpanNameProvider; import com.github.kristofa.brave.http.HttpClientRequest; import com.github.kristofa.brave.http.HttpClientRequestAdapter; import com.github.kristofa.brave.http.HttpClientResponseAdapter; import com.github.kristofa.brave.http.HttpResponse; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.Request; import com.ning.http.client.RequestBuilder; import com.ning.http.client.Response; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @Api("zipkin brave async api") @RestController @RequestMapping("/zipkin/async/service2") public class ZipkinAsyncController { @Autowired private AsyncHttpClient asyncHttpClient; @Autowired private Brave brave; @ApiOperation("trace第2步") @RequestMapping(value = "/test2", method = RequestMethod.GET) public String myboot2() { try { /*****************************serivce3*******************************/ RequestBuilder builder3 = new RequestBuilder(); String url3 = "http://localhost:8033/zipkin/async/service3/test3"; builder3.setUrl(url3); Request request3 = builder3.build(); clientRequestInterceptor(request3); Future<Response> response3 = asyncHttpClient.executeRequest(request3); clientResponseInterceptor(response3.get()); /*****************************serivce4*******************************/ RequestBuilder builder4 = new RequestBuilder(); String url4 = "http://localhost:8034/zipkin/async/service4/test4"; builder4.setUrl(url4); Request request4 = builder4.build(); clientRequestInterceptor(request4); Future<Response> response4 = asyncHttpClient.executeRequest(request4); clientResponseInterceptor(response4.get()); return response3.get().getResponseBody() + "=====" + response4.get().getResponseBody(); } catch (Exception e) { e.printStackTrace(); return ""; } } private void clientRequestInterceptor(Request request) { brave.clientRequestInterceptor().handle(new HttpClientRequestAdapter(new HttpClientRequest() { @Override public URI getUri() { return URI.create(request.getUrl()); } @Override public String getHttpMethod() { return request.getMethod(); } @Override public void addHeader(String headerKey, String headerValue) { request.getHeaders().add(headerKey, headerValue); } }, new DefaultSpanNameProvider())); } private void clientResponseInterceptor(Response response) { brave.clientResponseInterceptor().handle(new HttpClientResponseAdapter(new HttpResponse() { public int getHttpStatusCode() { return response.getStatusCode(); } })); } }
3、service3
3.1、pom.xml
<!-- zipkin brave --> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-core</artifactId> <version>3.9.0</version> </dependency> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-spancollector-http</artifactId> <version>3.9.0</version> </dependency> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-web-servlet-filter</artifactId> <version>3.9.0</version> </dependency>
3.2、ZipkinConfig
package com.xxx.service3.zipkin.brave.async; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.github.kristofa.brave.Brave; import com.github.kristofa.brave.EmptySpanCollectorMetricsHandler; import com.github.kristofa.brave.Sampler; import com.github.kristofa.brave.SpanCollector; import com.github.kristofa.brave.http.DefaultSpanNameProvider; import com.github.kristofa.brave.http.HttpSpanCollector; import com.github.kristofa.brave.servlet.BraveServletFilter; @Configuration public class ZipkinConfig { @Bean public SpanCollector spanCollector() { HttpSpanCollector.Config spanConfig = HttpSpanCollector.Config.builder() .compressionEnabled(false)//默认false,span在transport之前是否会被gzipped。 .connectTimeout(5000)//5s,默认10s .flushInterval(1)//1s .readTimeout(6000)//5s,默认60s .build(); return HttpSpanCollector.create("http://localhost:9411", spanConfig, new EmptySpanCollectorMetricsHandler()); } @Bean public Brave brave(SpanCollector spanCollector) { Brave.Builder builder = new Brave.Builder("asyn3 - service3 - 3");//指定serviceName builder.spanCollector(spanCollector); builder.traceSampler(Sampler.create(1));//采集率 return builder.build(); } @Bean public BraveServletFilter braveServletFilter(Brave brave) { /** * 设置sr、ss拦截器 */ return new BraveServletFilter(brave.serverRequestInterceptor(), brave.serverResponseInterceptor(), new DefaultSpanNameProvider()); } }
说明:指定了serviceName:"asyn3 - service3 - 3"
3.3、ZipkinAsyncController
package com.xxx.service3.zipkin.brave.async; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @Api("zipkin brave async api") @RestController @RequestMapping("/zipkin/async/service3") public class ZipkinAsyncController { @ApiOperation("trace第3步") @RequestMapping(value = "/test3", method = RequestMethod.GET) public String myboot3() { try { return "async - service3"; } catch (Exception e) { e.printStackTrace(); return ""; } } }
4、service4
4.1、pom.xml
<!-- zipkin brave --> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-core</artifactId> <version>3.9.0</version> </dependency> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-spancollector-http</artifactId> <version>3.9.0</version> </dependency> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-web-servlet-filter</artifactId> <version>3.9.0</version> </dependency>
4.2、ZipkinConfig
package com.xxx.service4.zipkin.brave.async; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.github.kristofa.brave.Brave; import com.github.kristofa.brave.EmptySpanCollectorMetricsHandler; import com.github.kristofa.brave.Sampler; import com.github.kristofa.brave.SpanCollector; import com.github.kristofa.brave.http.DefaultSpanNameProvider; import com.github.kristofa.brave.http.HttpSpanCollector; import com.github.kristofa.brave.servlet.BraveServletFilter; @Configuration public class ZipkinConfig { @Bean public SpanCollector spanCollector() { HttpSpanCollector.Config spanConfig = HttpSpanCollector.Config.builder() .compressionEnabled(false)//默认false,span在transport之前是否会被gzipped。 .connectTimeout(5000)//5s,默认10s .flushInterval(1)//1s .readTimeout(6000)//5s,默认60s .build(); return HttpSpanCollector.create("http://localhost:9411", spanConfig, new EmptySpanCollectorMetricsHandler()); } @Bean public Brave brave(SpanCollector spanCollector) { Brave.Builder builder = new Brave.Builder("asyn4 - service4 - 4");//指定serviceName builder.spanCollector(spanCollector); builder.traceSampler(Sampler.create(1));//采集率 return builder.build(); } @Bean public BraveServletFilter braveServletFilter(Brave brave) { /** * 设置sr、ss拦截器 */ return new BraveServletFilter(brave.serverRequestInterceptor(), brave.serverResponseInterceptor(), new DefaultSpanNameProvider()); } }
说明:指定了serviceName:"asyn4 - service4 - 4"
4.3、ZipkinAsyncController
package com.xxx.service4.zipkin.brave.async; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @Api("zipkin brave async api") @RestController @RequestMapping("/zipkin/async/service4") public class ZipkinAsyncController { @ApiOperation("trace第4步") @RequestMapping(value = "/test4", method = RequestMethod.GET) public String myboot3() { try { return "async - service4"; } catch (Exception e) { e.printStackTrace(); return ""; } } }
二、测试结果
1、依赖关系图:
2、span时间消耗图
3、详情图
点击第4个span,查看详情: