Full Link Log Tracking Based on Spring Boot + Dubbo (II)

Time:2019-9-2

I. Summary

Next to the last article, after completing the analysis, we need to implement it concretely.

service-aImplementing Dubbo services.

service-bImplementing web services and callingservice-aImplemented services.

II. Realization

2.1 Log Collection and Storage

This example directly uses Aliyun Log Service to store and retrieve data.Aliyun Log Logback AppenderLog collection and upload.

In fact, Ali implemented a Logback Appender himself. Of course, we can also implement it ourselves, such as uploading it to self-built ELK.

TraceId Generation, Delivery and Destruction in Project 2.2

2.2.1 TraceId Generation and Destruction

2.2.1.1 Client request etc. (external)

External class requests are triggered using interceptors.

When the request comes in, it generatestraceIdAnd writeorg.slf4j.MDC

After the request is completed, thetraceIdfromorg.slf4j.MDCRemove from.

package com.example.dubboserviceb.interceptor;

import com.example.dubboserviceb.constants.Constants;
import org.slf4j.MDC;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

/**
 * @author lpe234
 * @since 2019/5/25 14:43
 */
public class TraceIdInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // generate traceId
        String traceId = UUID.randomUUID().toString().replace("-", "");

        // put traceId
        MDC.put(Constants.TRACE_ID, traceId);

        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 {

        // clear traceId
        MDC.remove(Constants.TRACE_ID);
    }
}

2.2.1.2 Timing Tasks and Other Triggers (Internal)

(Brief…)

2.2.1 traceId delivery

2.2.1.1 WEB Class Delivery

Simple interface return class, addtraceIdFields.

package com.example.dubboserviceb.utils;

import lombok.Data;

/**
 * @author lpe234
 * @since 2019/5/25 14:55
 */
@Data
public class RestResponse<T> {
    private Integer code;
    private String msg;
    private T data;
    private String traceId;

    public RestResponse() {
    }

    public RestResponse(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public static <T> RestResponse<T> ok(T data) {
        return new RestResponse<>(200, "ok", data);
    }

    public static <T> RestResponse<T> error(T data) {
        return new RestResponse<>(400, "error", data);
    }
}

Before the request response results are generated, get the currentorg.slf4j.MDCMediumtraceIdSet toRestResponseMedium.

package com.example.dubboserviceb.advice;

import com.example.dubboserviceb.constants.Constants;
import com.example.dubboserviceb.utils.RestResponse;
import org.slf4j.MDC;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * @author lpe234
 * @since 2019/5/25 15:03
 */
@ControllerAdvice
public class ResponseModifyAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {

        // put traceId to response
        ((RestResponse) o).setTraceId(MDC.get(Constants.TRACE_ID));

        return o;
    }
}

Finally, the interface response data is as follows:

{
  "code": 200,
  "msg": "ok",
  "data": "Hello apple",
  "traceId": "6c25de3422374d51be58555ae9c380e8"
}

2.2.1.2 Dubbo class delivery

traceIdStorage usageorg.apache.dubbo.rpc.RpcContext(Internal useInternalThreadLocalImplementation).

With the help of Dubbo’s filters,traceIdRead, write, and clean between Dubbo services.

package com.example.dubboservicea.filter;

import com.example.dubboservicea.constants.Constants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.slf4j.MDC;

/**
 * @author lpe234
 * @since 2019/5/25 15:24
 */
@Activate(group = {org.apache.dubbo.common.Constants.PROVIDER, org.apache.dubbo.common.Constants.CONSUMER})
public class DubboTraceIdFilter implements Filter {

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {

        RpcContext rpcContext = RpcContext.getContext();

        // before
        if (rpcContext.isProviderSide()) {
            // get traceId from dubbo consumer,and set traceId to MDC
            String traceId = rpcContext.getAttachment(Constants.TRACE_ID);
            MDC.put(Constants.TRACE_ID, traceId);
        }

        Result result = invoker.invoke(invocation);

        // after
        if (rpcContext.isProviderSide()) {
            // clear traceId from MDC
            MDC.remove(Constants.TRACE_ID);
        }

        return result;
    }

    @Override
    public Result onResponse(Result result, Invoker<?> invoker, Invocation invocation) {
        return result;
    }
}

In addition, the need forresources/META-INF/dubbo/Under the folder, createcom.alibaba.dubbo.rpc.FilterText file. The contents are as follows:dubboTraceIdFilter=com.example.dubboservicea.filter.DubboTraceIdFilter

Then, Dubbo filters are configured in the spring-boot configuration file

#dubbo
dubbo:
  scan:
    base-packages: com.example.dubboservicea.provider, com.example.dubboservicea.reference
  protocol:
    name: dubbo
    port: 12101
  registry:
    address: zookeeper://118.190.204.150:20084
  provider:
    filter: dubboTraceIdFilter
  consumer:
    filter: dubboTraceIdFilter

III. RESULTS

3.1 HTTP request result return

Full Link Log Tracking Based on Spring Boot + Dubbo (II)

3.2 Log Service Query

Full Link Log Tracking Based on Spring Boot + Dubbo (II)