`

zipkin链路监控跟踪

 
阅读更多
zipkin链路跟踪:
多服务之间调用,服务与服务之间监控,原理是在发送和接收请求时由brave异步传输(HTTP, Kafka和Scribe)给zipkin传输记录,zipkin把记录整理存储起来(可以内存,DB,es等)。
同时zipkin有自己的ui可以展示给我们使用,调查日志。
另外zipkin也可以使用brave-mysql类库跟踪业务DB,增加MySQLStatementInterceptorManagementBean方法实例 ,原理是在jdbc时进行拦截把记录放到zipkin。

OkHttpClient调用发起http请求。在每次发起请求时则需要通过brave记录Span信息,并异步传递给zipkin
作为被调用方(服务端)也同样需要完成以上操作。

zipkin链路跟踪mysql:
maven引用brave-mysql类库,增加MySQLStatementInterceptorManagementBean实例 ,原理是在jdbc时进行拦截把记录放到zipkin。

cs:Client Send,客户端发起请求;
sr:Server Receive,服务器接受请求,开始处理;
ss:Server Send,服务器完成处理,给客户端应答;
cr:Client Receive,客户端接受应答从服务器;



zipkin参考:
zipkin入门和brave源码:
https://blog.csdn.net/john1337/article/details/71127056/
https://blog.csdn.net/apei830/article/details/78722180
brave-mysql:
https://www.cnblogs.com/java-zhao/p/5858138.html
https://www.h3399.cn/201805/576621.html

google dapper







package com.pingan.haofang.qypms.common.configuration.zipkin;

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.mysql.MySQLStatementInterceptorManagementBean;
import com.github.kristofa.brave.okhttp.BraveOkHttpRequestResponseInterceptor;
import com.github.kristofa.brave.servlet.BraveServletFilter;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Author: huaxiuming
 * @Description: [此处填写类的描述信息]
 * @Date: Created in 15:22 2019-3-4
 * @Modified By:
 */
@Configuration
public class SqlSpanConfig {

    @Autowired
    private ZipkinProperties properties;

//    @Bean
//    HttpResponseInjectingTraceFilter responseInjectingTraceFilter(Brave brave) {
//        return new HttpResponseInjectingTraceFilter(brave.localTracer());
//    }

    @Bean
    public SpanCollector spanCollector() {
        HttpSpanCollector.Config config = HttpSpanCollector.Config.builder().connectTimeout(properties.getConnectTimeout()).readTimeout(properties.getReadTimeout())
                .compressionEnabled(properties.isCompressionEnabled()).flushInterval(properties.getFlushInterval()).build();
        return HttpSpanCollector.create(properties.getUrl(), config, new EmptySpanCollectorMetricsHandler());
    }

    @Bean
    public Brave brave(SpanCollector spanCollector){
        Brave.Builder builder = new Brave.Builder(properties.getServiceName());  //指定state
        builder.spanCollector(spanCollector);
        builder.traceSampler(Sampler.ALWAYS_SAMPLE);
        Brave brave = builder.build();
        return brave;
    }

    @Bean
    public BraveServletFilter braveServletFilter(Brave brave){
        BraveServletFilter filter = new BraveServletFilter(brave.serverRequestInterceptor(),brave.serverResponseInterceptor(),new DefaultSpanNameProvider());
        return filter;
    }

    @Bean
    public OkHttpClient okHttpClient(Brave brave){
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(new BraveOkHttpRequestResponseInterceptor(brave.clientRequestInterceptor(), brave.clientResponseInterceptor(), new DefaultSpanNameProvider()))
                .build();
        return client;
    }

    @Bean
    public MySQLStatementInterceptorManagementBean mySQLStatementInterceptorManagementBean(Brave brave) {
        return new MySQLStatementInterceptorManagementBean(brave.clientTracer());
    }

}


package com.pingan.haofang.qypms.common.configuration.zipkin;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.web.filter.GenericFilterBean;

import com.alibaba.fastjson.JSONObject;


/**
* @Author: huaxiuming
* @Description: [此处填写类的描述信息]
* @Date: Created in 15:21 2019-3-4
* @Modified By:
*/
public class HttpResponseInjectingTraceFilter extends GenericFilterBean {

    private static final Logger logger = LoggerFactory
            .getLogger(HttpResponseInjectingTraceFilter.class);

    private final Tracer tracer;

    public HttpResponseInjectingTraceFilter(Tracer tracer) {
        this.tracer = tracer;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain filterChain) throws IOException, ServletException {
        Span currentSpan = this.tracer.getCurrentSpan();
        HttpServletRequest httpRequest = (HttpServletRequest) request;

        // 添加头部信息
        Map<String, String> headerMap = new HashMap<String, String>();
        Enumeration<String> enume = httpRequest.getHeaderNames();
        while (enume.hasMoreElements()) {
            String key = enume.nextElement();
            String value = httpRequest.getHeader(key);
            headerMap.put(key, value);
        }
        if (headerMap.size() > 0) {
            currentSpan.tag("http.head", JSONObject.toJSONString(headerMap));
        }


        //方法名
        String method = httpRequest.getMethod();
        currentSpan.tag("request.method", method);

        RequestWrapper wrapperRequest = new RequestWrapper(httpRequest);// 转换成代理类
        ResponseWrapper wrapperResponse = new ResponseWrapper(
                (HttpServletResponse) response);// 转换成代理类
        // 拦截返回
        filterChain.doFilter(wrapperRequest, wrapperResponse);

        // 添加参数信息
        String params = this.getRequestParameter(wrapperRequest);
        currentSpan.tag("http.params", params);

        // 添加返回值信息
        byte[] content = wrapperResponse.getContent();// 获取返回值
        // 判断是否有值
        if (content.length > 0) {
            try {
                String result = new String(content, "UTF-8");
                currentSpan.tag("http.result", result);
            } catch (Exception e) {
                logger.error("添加返回值信息异常", e);
            }
        }

        // 把返回值输出到客户端
        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
        } catch (Exception e) {
        } finally {
            try {
                if (out != null) {
                    out.write(content);
                    out.flush();
                    out.close();
                }
            } catch (IOException e) {
            }
        }
    }

    /**
     * 方法功能说明: 获取请求参数包括form表单和json参数
     */
    public String getRequestParameter(RequestWrapper wrapperRequest) {
        if (null == wrapperRequest) {
            return null;
        }
        String params = null;
        String method = wrapperRequest.getMethod();
        if (StringUtils.isNotBlank(method) && "GET".equals(method.toUpperCase())) {
            // 获取请求体中的字符串(get)
            params = wrapperRequest.getQueryString();
            try {
                if (StringUtils.isNotBlank(params)) {
                    params = URLDecoder.decode(params, "UTF-8");
                }
            } catch (UnsupportedEncodingException e) {
                // Logger.error("获取到的请求参数解码错误 : {}", e.getMessage());
            }
            return params;
        } else {
            return wrapperRequest.getBodyString(wrapperRequest);
        }
    }

}

package com.pingan.haofang.qypms.common.configuration.zipkin;

import org.springframework.cloud.sleuth.Tracer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Author: huaxiuming
 * @Description: [此处填写类的描述信息]
 * @Date: Created in 15:22 2019-3-4
 * @Modified By:
 */
@Configuration
public class HttpSpanConfig {

    @Bean
    HttpResponseInjectingTraceFilter responseInjectingTraceFilter(Tracer tracer) {
        return new HttpResponseInjectingTraceFilter(tracer);
    }

}



package com.pingan.haofang.qypms.common.configuration.zipkin;

import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanTextMap;
import org.springframework.cloud.sleuth.instrument.web.ZipkinHttpSpanInjector;


/**
 * @Author: huaxiuming
 * @Description: [此处填写类的描述信息]
 * @Date: Created in 15:20 2019-3-4
 * @Modified By:
 */
public class CustomHttpServletResponseSpanInjector extends ZipkinHttpSpanInjector {

    @Override
    public void inject(Span span, SpanTextMap carrier) {
        super.inject(span, carrier);
        carrier.put(Span.TRACE_ID_NAME, span.traceIdString());
        carrier.put(Span.SPAN_ID_NAME, Span.idToHex(span.getSpanId()));
    }

}


package com.pingan.haofang.qypms.common.configuration.zipkin;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Enumeration;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.lang3.StringUtils;
import org.springframework.util.StreamUtils;

/**
 * @Author: huaxiuming
 * @Description: [请求输出代理类]
 * @Date: Created in 15:23 2019-3-4
 * @Modified By:
 */
public class RequestWrapper extends HttpServletRequestWrapper {

    private final byte[] body;

    public RequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        String sessionStream = getBodyString(request);
        body = sessionStream.getBytes(Charset.forName("UTF-8"));
    }

    /**
     * 获取请求Body
     *
     * @param request
     * @return
     */
    public String getBodyString(final ServletRequest request) {
        String contentType = request.getContentType();
        String bodyString = "";

        if (StringUtils.isNotBlank(contentType) &&
                (contentType.contains("multipart/form-data") ||
                        contentType.contains("x-www-form-urlencoded"))) {

            Enumeration<String> pars = request.getParameterNames();

            while (pars.hasMoreElements()) {

                String n = pars.nextElement();

                bodyString += n + "=" + request.getParameter(n) + "&";

            }

            bodyString = bodyString.endsWith("&") ? bodyString.substring(0, bodyString.length() - 1) : bodyString;

            return bodyString;

        }

        try {
            byte[] byteArray = StreamUtils.copyToByteArray(request.getInputStream());
            bodyString = new String(byteArray, "UTF-8");
        } catch (IOException e) {
        }

        return bodyString;
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {

        final ByteArrayInputStream bais = new ByteArrayInputStream(body);

        return new ServletInputStream() {

            @Override
            public int read() throws IOException {
                return bais.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {
            }
        };
    }

}

分享到:
评论

相关推荐

    ASP.NET Core整合Zipkin链路跟踪的实现方法

    ASP.NET Core整合Zipkin链路跟踪的实现方法 在现代微服务架构中,链路跟踪是监控和诊断系统性能的关键工具。Zipkin是一款由Twitter开源的分布式跟踪系统,旨在帮助开发者收集和分析实时监控数据,以发现服务间的...

    统一监控平台方案(日志监控、方法监控、调用链路监控)

    该统一监控平台主要关注于**日志监控**、**方法监控**、**调用链路监控**三大核心领域,并结合先进的大数据技术如Flume、Kafka、Spark和Elasticsearch,以确保高效、准确的数据采集与分析能力。此外,还计划集成自研...

    SpringBoot集成Zipkin实现分布式全链路监控

    SpringBoot集成Zipkin实现分布式全链路监控 在本文中,我们将详细介绍如何使用SpringBoot集成Zipkin实现分布式全链路监控。Zipkin是一种分布式跟踪系统,能够帮助我们收集服务体系结构中的延迟问题所需的计时数据,...

    构建微服务体系下的全链路监控体系

    构建微服务体系下的全链路监控体系是一个在分布式系统架构中越来越受到重视的领域,尤其是在以微服务为基础的体系结构中。微服务架构由于其解耦、灵活性和可扩展性等优点被广泛采纳,同时也带来了管理和监控上的挑战...

    spring-cloud 整合zipkin实现链路追踪 Demo

    在分布式系统中,链路追踪是一项关键的技术,它允许开发者追踪请求在整个系统中...通过这个 Demo,你可以深入了解 Spring Cloud Zipkin 的工作原理,并在实际项目中实现链路追踪,提高微服务架构的可监控性和可维护性。

    微服务springcloud之zipkin使用demo(链路追踪)

    zipkin为分布式链路调用监控系统,聚合各业务系统调用延迟数据,达到链路调用监控跟踪。 zipkin主要涉及四个组件 collector storage search web UI 1.Collector接收各service传输的数据 2.Cassandra作为Storage的一...

    Vert.x,应用监控 - 全链路跟踪,基于Zipkin

    Vert.x,应用监控 - 全链路跟踪,基于Zipkin

    统一监控平台方案(日志监控、方法监控、调用链路监控).pdf

    该方案涵盖了日志监控、方法监控、调用链路监控、JVM 监控、中间件监控、数据库监控、硬件监控等多个方面。 一、背景 随着公司软件系统和硬件的增多,需要一个统一的监控系统进行全盘监控和管理。当前的服务通常由...

    dubbo 链路跟踪

    链路跟踪,也称为分布式追踪,是用于监控微服务架构中的请求流的一种技术。在Dubbo中,它可以帮助我们跟踪请求从客户端发起,经过多个服务的传递,最后到达服务器端的整个过程,这对于优化服务性能、排查故障有着...

    统一监控平台方案(日志监控、方法监控、调用链路监控).rar

    再者,调用链路监控,也被称为分布式跟踪,是现代云原生环境中不可或缺的一部分。它能记录每一次请求在整个系统中的传播路径,包括每个服务的调用顺序、响应时间、异常情况等。调用链路监控为故障排查提供了全景视图...

    zipkin&Sleuth链路追踪.zip

    【标题】"zipkin&Sleuth链路追踪.zip" 提供了有关分布式系统监控和链路追踪的重要工具,其中涉及到 Zipkin 和 Sleuth 这两个关键组件。Zipkin 是一个流行的开源系统,用于收集和可视化服务间的调用时间数据,以帮助...

    zipkin 分布式调用链跟踪

    分布式调用链跟踪是一种用于监控和调试分布式系统中各个服务之间调用关系的技术。随着微服务架构和服务网格技术的流行,分布式系统的规模和复杂性日益增加,调用链跟踪技术逐渐成为保证系统稳定性和性能的关键工具。...

    全链路监控的起源解决方案.docx

    全链路监控是一种针对复杂分布式系统的技术方案,旨在确保服务的高效、稳定运行。它源自于Application Performance Management(APM),其核心思想是在应用程序服务的各个节点间传递一个标识,以便跟踪和关联不同...

    SpringCloud微服务、链路跟踪、分布式配置、分布式网关

    2. **分布式链路跟踪**:Zipkin是SpringCloud用于分布式系统追踪的工具,它可以收集并展示服务之间的调用链路,帮助开发者理解请求在系统中的传播过程,快速定位性能瓶颈或故障点。通过Zipkin,我们可以收集服务调用...

    目前市面的全链路监控系统基本都是参考Google的Dapper来做的,本专题主要通过六个章节的代码实战.zip

    全链路监控系统是现代软件开发中不可或缺的一部分,它能够帮助开发者实时了解应用程序的运行状况,定位并解决性能瓶颈和故障。Google的Dapper作为这一领域的先驱,为许多后来的全链路监控系统提供了设计灵感和技术...

    zipkin分布式服务链接监控服务端

    Zipkin分布式服务链路监控服务端是用于追踪微服务架构中请求在各服务间传递的延迟数据的重要工具。它的核心目标是收集并展示服务间的调用关系,帮助开发者理解和优化系统的性能瓶颈。Zipkin最初由Twitter开发,后来...

    zipkin-server-2.12.9-exec.jar

    在SpringCloud生态中,Zipkin是实现链路追踪的重要组件,通过它可以直观地查看服务之间的调用关系和请求耗时,从而提升系统的可监控性和可维护性。 标题中的"zipkin-server-2.12.9-exec.jar"是Zipkin Server的一个...

    微服务调用链路追踪详解教程Zipkin.docx

    总之,服务调用链路追踪和Zipkin的结合使用,为微服务架构带来了强大的监控能力,使得问题排查和性能优化更为高效。通过Sleuth的自动日志注入和Zipkin的数据收集与展示,我们可以清晰地看到请求在分布式系统中的流转...

    微服务架构之分布式请求链路跟踪1

    Spring Cloud Sleuth 结合 Zipkin 提供了一个强大且易于使用的分布式请求链路跟踪解决方案。通过它,开发者可以有效地监控微服务架构中的服务交互,定位性能瓶颈,优化系统性能,提升用户体验。在实际的微服务开发和...

    Servlet项目集成zipkin

    Zipkin的设计灵感来源于Google的Dapper,它提供了收集和可视化服务之间调用链路的能力。Zipkin的核心组件包括:收集器(Collector)、存储(Storage)、查询服务(Query Service)和Web UI。通过在服务中插入合适的...

Global site tag (gtag.js) - Google Analytics