I. Summary
Next to the last article, after completing the analysis, we need to implement it concretely.
service-a
Implementing Dubbo services.
service-b
Implementing web services and callingservice-a
Implemented services.
II. Realization
2.1 Log Collection and Storage
This example directly uses Aliyun Log Service to store and retrieve data.Aliyun Log Logback Appender
Log 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 generatestraceId
And writeorg.slf4j.MDC
。
After the request is completed, thetraceId
fromorg.slf4j.MDC
Remove 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, addtraceId
Fields.
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.MDC
MediumtraceId
Set toRestResponse
Medium.
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
traceId
Storage usageorg.apache.dubbo.rpc.RpcContext
(Internal useInternalThreadLocal
Implementation).
With the help of Dubbo’s filters,traceId
Read, 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.Filter
Text 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