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

前言

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

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

应用

1 增加依赖


    org.springframework.cloud
    spring-cloud-starter-sleuth
    2.0.1.RELEASE

2 配置logback

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



    
    
    
    
        https://api.puhuifinance.com/log-server/log
        @project.artifactId@
        @config.branch@
        
            ERROR
        
        
            
            %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的含义:

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

3. 日志查询

Java面试题框架篇spring sleuth分布式日志查询_第1张图片

  • 每个请求都会生成一个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);
    }
}

 

你可能感兴趣的:(面试题,架构设计,java常见知识)