分布式追踪OpenTracing与 Jaeger 实现

分布式追踪OpenTracing与 Jaeger 实现

OpenTracing

可是市面上的产品实在太多了,基本上每个成规模的公司都实现了自己的一套小九九。它们互不兼容,各种集成困难,尤其对于异构跨语言的系统,实现调用链几乎是一个噩梦。在这种状态下, 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)

jaeger

下载可以在github上下载二进制文件。

https://github.com/jaegertracing/jaeger/releases/

jaeger的安装特别的简单。下载其二进制版本,仅有几个执行文件和配置文件(golang编译类型的功劳)。

1.架构介绍

SpringCloud + Opentracing + jaeger调用链解决方案

2.添加好pom依赖

<dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>3.8.1</version>
        </dependency>
        <dependency>
            <groupId>io.jaegertracing</groupId>
            <artifactId>jaeger-core</artifactId>
            <version>0.27.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.opentracing.contrib/opentracing-web-servlet-filter -->
        <dependency>
            <groupId>io.opentracing.contrib</groupId>
            <artifactId>opentracing-web-servlet-filter</artifactId>
            <version>0.2.2</version>
        </dependency>

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();
        Enumeration<String> e = request.getHeaderNames();
        while (e.hasMoreElements()) {
            String headerName = e.nextElement();// 透明称
            Enumeration<String> headerValues = 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

猜你喜欢

转载自blog.csdn.net/m0_37598953/article/details/88760603