Java面试题框架篇spring sleuth分布式日志查询

前言

随着微服务数量不断增长,需要跟踪一个请求从一个微服务到下一个微服务的传播过程, Spring Cloud Sleuth 正是解决这个问题,它在日志中引入唯一ID,以保证微服务调用之间的一致性,这样你就能跟踪某个请求是如何从一个微服务传递到下一个。

  如果你有使用AOP拦截Servlet的经验,做一个基于AOP的简单服务统计和跟踪很容易。但要像Zipkin那样能够跟踪服务调用链就比较困难了。所谓调用链,就是A服务调用B服务,B服务又调用了C、D服务。这样一个链要想统计跟踪,要写不少代码。而Spring Cloud Sleuth能让你不写一行代码的情况下完成这些。

应用

1 增加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
    <version>2.0.1.RELEASE</version>
</dependency>

2 配置logback

logback众所周知可以输出到console,file和远程服务器,我们项目中定义输入到统一的服务器:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <jmxConfigurator/>
    <property name="LOG_FILE_NAME" value="@[email protected]"/>
    <include resource="com/puhui/cloud/logging/logback/puhui-logback-standardization.xml"/>
    <appender name="ERRORLOG" class="com.puhui.log.logback.HttpAppender">
        <url>https://api.puhuifinance.com/log-server/log</url>
        <localSystemName>@project.artifactId@</localSystemName>
        <env>@config.branch@</env>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <encoder charset="UTF-8">
            <!--<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{80} - %msg%n</pattern>-->
            <pattern>%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} | %clr(${LOG_LEVEL_PATTERN:-%5p}){magenta}
                |[%X{X-B3-TraceId:-}]| [%X{token}] | %clr(---){faint}| %clr([%15.15t]){faint} |
                %clr(%-40.40logger{39}){cyan} |
                %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}
            </pattern>
        </encoder>
    </appender>
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
        <appender-ref ref="ERRORLOG"/>
    </root>

    <!-- 需要配置的日志 -->
    <logger name="com.puhui" level="INFO" additivity="true"/>

</configuration>

pattern的含义:

  • 时间,加颜色clr
  • 日志级别
  • TraceId
  • 自定义输出属性token,token在filter中存入MDC即可,代码:
    MDC.put("token", "111888");
  • 分隔符----
  • thread
  • logger内容 也就是包路径,类
  • 信息,包括异常

3. 日志查询

  • 每个请求都会生成一个traceid
  • spanId在跨微服务的时候发生变化,微服务内不变化
  • 查询条件区分大小写,比如AND,不能写成and

4 问题

一开始调试的时候,在logback增加了自定义属性token,但是本地调试就是不输出,后来发现我改动的logback的appender是输出到远程服务器到,本地当然不会修改,部署到云平台后,日志系统可以正常输出,没有问题。

5 自定义key

除了traceid和spanid等四个默认属性,可以自定义属性,只要存入MDC就可以,代码如下:

写一个拦截器:

package com.puhui.goosecard.bank.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.puhui.goosecard.bank.controller.BindCardController;
import com.puhui.goosecard.common.model.bank.shyk.BindCardCheckReq;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;

/**
 * 2 * @Author: kerry
 * 3 * @Date: 2018/9/19 16:52
 * 4
 */
@Component(value = "handlerInterceptor")
public class MDCInterceptor implements HandlerInterceptor {


    private String getBody(HttpServletRequest request) {
        String wholeStr = "";
        try {
            BufferedReader br = request.getReader();
            String str = "";
            while ((str = br.readLine()) != null) {
                wholeStr += str;
            }
        } catch (Exception e) {
        }
        return wholeStr;
    }


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String body = getBody(request);
        if (((HandlerMethod) handler).getBean() instanceof BindCardController) {
            BindCardCheckReq bindCardCheckReq = JSONObject.parseObject(body, BindCardCheckReq.class);
            MDC.put("outTradeNo", bindCardCheckReq.getOutTradeNo());
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

注册拦截器:

  @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(handlerInterceptor);
    }
}

猜你喜欢

转载自blog.csdn.net/hanruikai/article/details/82777223
今日推荐