使用Zipkin和Brave實現http服務調用的跟蹤,Brave 是用來裝備Java程序的類庫,提供了面向標准Servlet、Spring MVC、Http Client、JAX RS、Jersey、Resteasy 和 MySQL 等接口的裝備能力,可以通過編寫簡單的配置和代碼,讓基於這些框架構建的應用可以向 Zipkin 報告數據。同時 Brave 也提供了非常簡單且標准化的接口,在以上封裝無法滿足要求的時候可以方便擴展與定制。
提供四個工程,分別對應四個服務分別是:zipkin1,zipkin2,zipkin3,zipkin4;zipkin1通過httpclient調用zipkin2,然后zipkin2通過httpclient調用zipkin3和zipkin4,形成一個調用鏈;四個服務都是基於spring-boot來實現,對應的端口分別是8081,8082,8083,8084;
1.公共maven依賴庫
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <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> <dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-apache-http-interceptors</artifactId> <version>3.9.0</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> </dependencies>
2.核心類ZipkinBean提供需要使用的Bean
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.github.kristofa.brave.Brave; import com.github.kristofa.brave.Brave.Builder; 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.http.HttpSpanCollector.Config; import com.github.kristofa.brave.httpclient.BraveHttpRequestInterceptor; import com.github.kristofa.brave.httpclient.BraveHttpResponseInterceptor; import com.github.kristofa.brave.servlet.BraveServletFilter; @Configuration public class ZipkinBean { /** * 配置收集器 * * @return */ @Bean public SpanCollector spanCollector() { Config config = HttpSpanCollector.Config.builder().compressionEnabled(false).connectTimeout(5000) .flushInterval(1).readTimeout(6000).build(); return HttpSpanCollector.create("http://192.168.237.128:9411", config, new EmptySpanCollectorMetricsHandler()); } /** * Brave各工具類的封裝 * * @param spanCollector * @return */ @Bean public Brave brave(SpanCollector spanCollector) { Builder builder = new Builder("service1");// 指定serviceName builder.spanCollector(spanCollector); builder.traceSampler(Sampler.create(1));// 采集率 return builder.build(); } /** * 攔截器,需要serverRequestInterceptor,serverResponseInterceptor 分別完成sr和ss操作 * * @param brave * @return */ @Bean public BraveServletFilter braveServletFilter(Brave brave) { return new BraveServletFilter(brave.serverRequestInterceptor(), brave.serverResponseInterceptor(), new DefaultSpanNameProvider()); } /** * httpClient客戶端,需要clientRequestInterceptor,clientResponseInterceptor分別完成cs和cr操作 * * @param brave * @return */ @Bean public CloseableHttpClient httpClient(Brave brave) { CloseableHttpClient httpclient = HttpClients.custom() .addInterceptorFirst(new BraveHttpRequestInterceptor(brave.clientRequestInterceptor(), new DefaultSpanNameProvider())) .addInterceptorFirst(new BraveHttpResponseInterceptor(brave.clientResponseInterceptor())).build(); return httpclient; } }
3.核心類ZipkinController對外接口
@RestController public class ZipkinController { @Autowired private CloseableHttpClient httpClient; @GetMapping("/service1") public String service() throws Exception { Thread.sleep(100); HttpGet get = new HttpGet("http://localhost:8082/service2"); CloseableHttpResponse response = httpClient.execute(get); return EntityUtils.toString(response.getEntity(), "utf-8"); } }
分別啟動四個服務,然后瀏覽器訪問:http://localhost:8081/service1,正常調用結果返回:
service3 service4
可以觀察zipkin web ui,查看服務的調用鏈: