Zipkin 是一款开源的分布式实时数据追踪系统(Distributed Tracking System),基于 Google Dapper 的论文设计而来,由 Twitter 公司开发贡献。其主要功能是聚集来自各个异构系统的实时监控数据,用来追踪微服务架构下的系统延时问题。
Brave 是用来装备 Java 程序的类库,提供了面向 Standard Servlet、Spring MVC、Http Client、JAX RS、Jersey、Resteasy 和 MySQL 等接口的装备能力,可以通过编写简单的配置和代码,让基于这些框架构建的应用可以向 Zipkin 报告数据。同时 Brave 也提供了非常简单且标准化的接口,在以上封装无法满足要求的时候可以方便扩展与定制(下篇会讲)。
有关zipkin与Brave的详细介绍:http://www.tuicool.com/articles/f2qAZnZ
客户端发起请求到接收到服务端回应,先后经过四个阶段:客户端/消费者发起请求(cs)、服务端/生产者接收到请求(sr)、服务端/生产者发送应答(ss)和客户端/消费者接收到应答(cr)。Brave为Spring提供的Servlet拦截器(ServletHandlerInterceptor)及Rest(BraveClientHttpRequestInterceptor)模板的拦截器,向zipkin报告监控数据,其中,BraveClientHttpRequestInterceptor负责cs与cr的处理,ServletHandlerInterceptor负责sr与ss的处理。
好,开始实验这两个拦截器的使用,目标是发布两个服务a和b,在a中调用b服务,记录调用的跟踪信息。
git项目地址:https://github.com/blacklau/brave-webmvc-example (forked from openzipkin/brave-webmvc-example ,请忽略README.md说明)
1、pom.xml
4.0.0
io.zipkin.brave
brave-webmvc-example
1.0-SNAPSHOT
war
brave-webmvc-examplea
Example using Brave to trace RPCs from Spring Web MVC
https://github.com/openzipkin/brave-webmvc-example
UTF-8
4.3.3.RELEASE
8.1.20.v20160902
3.16.0
0.6.9
junit
junit
4.10
test
io.zipkin.brave
brave-core-spring
${brave.version}
io.zipkin.reporter
zipkin-sender-okhttp3
${zipkin-reporter.version}
io.zipkin.reporter
zipkin-sender-libthrift
${zipkin-reporter.version}
io.zipkin.reporter
zipkin-sender-kafka08
${zipkin-reporter.version}
io.zipkin.brave
brave-spring-web-servlet-interceptor
${brave.version}
io.zipkin.brave
brave-spring-resttemplate-interceptors
${brave.version}
org.springframework
spring-core
${spring.version}
org.springframework
spring-context
${spring.version}
org.springframework
spring-beans
${spring.version}
org.springframework
spring-web
${spring.version}
org.springframework
spring-webmvc
${spring.version}
org.eclipse.jetty
jetty-server
${jetty.version}
test
org.eclipse.jetty
jetty-webapp
${jetty.version}
test
log4j
log4j
1.2.17
org.slf4j
slf4j-log4j12
1.7.21
org.slf4j
jcl-over-slf4j
1.7.21
true
org.apache.maven.plugins
maven-compiler-plugin
2.5.1
1.6
true
true
org.apache.maven.plugins
maven-failsafe-plugin
2.19.1
integration-test
integration-test
verify
verify
org.apache.maven.plugins
maven-war-plugin
3.0.0
${basedir}/src/main/webapp
true
**/index.html
${basedir}/src/main/webapp/WEB-INF
true
WEB-INF
**/web.xml
WEB-INF/lib/servlet-api-*.jar
2、Brave的初始化及添加拦截器
package brave.webmvc;
import com.github.kristofa.brave.Brave;
import com.github.kristofa.brave.LoggingReporter;
import com.github.kristofa.brave.http.DefaultSpanNameProvider;
import com.github.kristofa.brave.http.SpanNameProvider;
import com.github.kristofa.brave.spring.BraveClientHttpRequestInterceptor;
import com.github.kristofa.brave.spring.ServletHandlerInterceptor;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import zipkin.Span;
import zipkin.reporter.Reporter;
import zipkin.reporter.Sender;
import zipkin.reporter.okhttp3.OkHttpSender;
/**
* This adds tracing configuration to any web mvc controllers or rest template clients. This should
* be configured last.
*/
@Configuration
// import as the interceptors are annotation with javax.inject and not automatically wired
@Import({BraveClientHttpRequestInterceptor.class, ServletHandlerInterceptor.class})
public class WebTracingConfiguration extends WebMvcConfigurerAdapter {
/** 发送器配置 */
@Bean Sender sender() {
return OkHttpSender.create("http://127.0.0.1:9411/api/v1/spans");
//return LibthriftSender.create("127.0.0.1");
// return KafkaSender.create("127.0.0.1:9092");
}
/** 用什么方式显示span信息 */
@Bean Reporter reporter() {
//取消注释,日志打印span信息
//return new LoggingReporter();
return AsyncReporter.builder(sender()).build();
}
@Bean Brave brave() {
return new Brave.Builder("brave-webmvc-example").reporter(reporter()).build();
}
// span命名提供者,默认为http方法.
@Bean SpanNameProvider spanNameProvider() {
return new DefaultSpanNameProvider();
}
@Autowired
private ServletHandlerInterceptor serverInterceptor;
@Autowired
private BraveClientHttpRequestInterceptor clientInterceptor;
@Autowired
private RestTemplate restTemplate;
// 添加rest template拦截器
@PostConstruct
public void init() {
List interceptors =
new ArrayList(restTemplate.getInterceptors());
interceptors.add(clientInterceptor);
restTemplate.setInterceptors(interceptors);
}
// 添加Severlet拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(serverInterceptor);
}
}
3、springmvc的controller,发布a和b两个服务
package brave.webmvc;
import java.util.Random;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@RestController
@EnableWebMvc
@Configuration
public class ExampleController {
@Bean RestTemplate template() {
return new RestTemplate();
}
@Autowired RestTemplate template;
@RequestMapping("/a")
public String a() throws InterruptedException {
Random random = new Random();
Thread.sleep(random.nextInt(1000));
return template.getForObject("http://localhost:8080/brave-webmvc-example/b", String.class);
}
@RequestMapping("/b")
public String b() throws InterruptedException {
Random random = new Random();
Thread.sleep(random.nextInt(1000));
return "b";
}
}
4、web.xml配置
brave webmvc example
dispatcher
org.springframework.web.servlet.DispatcherServlet
contextClass
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
contextConfigLocation
brave.webmvc.ExampleController
brave.webmvc.WebTracingConfiguration
1
dispatcher
/*
5、下载zipkin并运行
下载地址: https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=LATEST&c=exec
运行: java -jar zipkin.jar
6、git上下载项目,maven打war包(打包时,请跳过测试,否则报错)部署到tomcat或在开发环境中运行
访问a服务: http://localhost:8080/brave-webmvc-example/a
打开:http://localhost:9411,查看调用链跟踪信息及耗时
发现Brave提供的拦截器使用的Span的名称是默认的http的请求方法,好像没多大意义,且没有记录请求参数,若调用链中出现bug,不方便bug重现与问题排查,下一篇讲使用Brave的扩展与定制,重写span名称的获取与添加请求参数到跟踪信息中