可是市面上的产品实在太多了,基本上每个成规模的公司都实现了自己的一套小九九。它们互不兼容,各种集成困难,尤其对于异构跨语言的系统,实现调用链几乎是一个噩梦。在这种状态下, OpenTracing
协议横空出世。
OpenTracing
只是一种协议,是一种标准化。没有它,你的应用程序照样会玩的很好,只不过失去了和其他组件交流的能力。
每一次技术迭代都是对过去技术的抽象和升华。 OpenTracing
同样抽象出调用链必须的数据模型,只需要按照其标准,一个golang语言的程序和java语言的跨平台调用链就可以很容易的实现。
官网: http://opentracing.io/
支持 OpenTracing
的开源产品可以在这里找到 : http://opentracing.io/documentation/pages/supported-tracers.html
典型的如 SpringCloud
集成的 Zipkin
。
我们要着重推荐的,是另一款叫做 Jaeger
(丫哥)的产品。 Jaeger
是 Uber
开发的一款调用链服务端产品,开发语言为 golang
,能够兼容接收 OpenTracing
格式的数据。根据其 发展历史 ,可以说是 Zipkin
的升级版。另外,其基于 udp
(也可以 http
)的传输协议,更加定位了其高效、迅速的特点(lol,可能有那么一小点不可靠)
原创文章,转载注明出处 (http://sayhiai.com)
下载可以在github上下载二进制文件。
https://github.com/jaegertracing/jaeger/releases/
jaeger的安装特别的简单。下载其二进制版本,仅有几个执行文件和配置文件(golang编译类型的功劳)。
1.架构介绍
2.添加好pom依赖
com.squareup.okhttp3
okhttp
3.8.1
io.jaegertracing
jaeger-core
0.27.0
io.opentracing.contrib
opentracing-web-servlet-filter
0.2.2
3. 添加jaeger 配置
@Configuration
public class JaegerConfig implements WebMvcConfigurer {
public static Tracer tracer;
@Autowired
private JaegerInterceptor interceptor;@Value("${io.opentracing.trace.host}")
private String AGENT_HOST;@Value("${io.opentracing.trace.port}")
private Integer AGENT_PORT;public static OkHttpClient client = new OkHttpClient();
@Bean
public void init() {
tracer = new Tracer.Builder("***-management")
.withReporter(new RemoteReporter.Builder().withSender(new UdpSender(AGENT_HOST, AGENT_PORT, 0)).build())
.withSampler(new ConstSampler(true)).withScopeManager(new AutoFinishScopeManager()).build();
}@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(interceptor).addPathPatterns("/**");
}
4.配置一个拦截器,每次拦截请求
@Component
public class JaegerInterceptor extends HandlerInterceptorAdapter {@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
Tracer.SpanBuilder spanBuilder = tracer.buildSpan(request.getRequestURI()).withTag(Tags.SPAN_KIND.getKey(),
Tags.SPAN_KIND_SERVER);
String path = request.getServletPath();
String rootPath = path.substring(0, 7);
StringBuilder sb = new StringBuilder(rootPath);
path = path.replace(rootPath, "");
String regEx = "[^0-9]";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(path);
String indexOf = m.replaceAll("").trim();
if (StringUtils.isNotBlank(indexOf) && indexOf.length() > 1) {
indexOf = indexOf.substring(0, 1);
path = path.substring(0, path.indexOf(indexOf));
}
sb.append(path);
HttpHeaders httpHeaders = new HttpHeaders();
Enumeratione = request.getHeaderNames();
while (e.hasMoreElements()) {
String headerName = e.nextElement();// 透明称
EnumerationheaderValues = request.getHeaders(headerName);
while (headerValues.hasMoreElements()) {
httpHeaders.add(headerName, headerValues.nextElement());
}
}
SpanContext extract = tracer.extract(HTTP_HEADERS,new TextMapExtractAdapter(httpHeaders.toSingleValueMap()));
spanBuilder = spanBuilder.asChildOf(extract);
tracer.inject(spanBuilder.start().context(),Format.Builtin.HTTP_HEADERS, new HttpHeadersCarrier(httpHeaders));
spanBuilder.startActive(true);
return true;
}@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
tracer.scopeManager().active().close();
}
效果图:
参考资料
Jaeger on Aliyun Log Service - https://github.com/aliyun/jaeger
OpenTracing 中文文档 - https://wu-sheng.gitbooks.io/opentracing-io/content/
Jaeger - http://jaeger.readthedocs.io/en/latest/getting_started/
OpenTracing tutorial - https://github.com/yurishkuro/opentracing-tutorial
http://peter.bourgon.org/blog/2017/02/21/metrics-tracing-and-logging.html
jaeger GitHub demo