dubbo分布式日志跟踪

dubbo分布式日志追踪:

需要修改两个地方,一个是consumer端的 InvokerInvocationHandler.java,红色是修改的地方

public class InvokerInvocationHandler implements InvocationHandler {

    private final Invoker<?> invoker;

    public InvokerInvocationHandler(Invoker<?> handler) {
        this.invoker = handler;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        Class<?>[] parameterTypes = method.getParameterTypes();
        if (method.getDeclaringClass() == Object.class) {
            return method.invoke(invoker, args);
        }
        if ("toString".equals(methodName) && parameterTypes.length == 0) {
            return invoker.toString();
        }
        if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
            return invoker.hashCode();
        }
        if ("equals".equals(methodName) && parameterTypes.length == 1) {
            return invoker.equals(args[0]);
        }

        RpcInvocation invocation;
        if (RpcUtils.hasGeneratedFuture(method)) {
            Class<?> clazz = method.getDeclaringClass();
            String syncMethodName = methodName.substring(0, methodName.length() - Constants.ASYNC_SUFFIX.length());
            Method syncMethod = clazz.getMethod(syncMethodName, method.getParameterTypes());
            invocation = new RpcInvocation(syncMethod, args);
            invocation.setAttachment(Constants.FUTURE_GENERATED_KEY, "true");
            invocation.setAttachment(Constants.ASYNC_KEY, "true");
        } else {
            invocation = new RpcInvocation(method, args);
            if (RpcUtils.hasFutureReturnType(method)) {
                invocation.setAttachment(Constants.FUTURE_RETURNTYPE_KEY, "true");
                invocation.setAttachment(Constants.ASYNC_KEY, "true");
            }
        }
        // 这里将cosumer 端的traceId放入RpcInvocation
        invocation.setAttachment("traceId", TraceIdUtil.getTraceId());
        return invoker.invoke(invocation).recreate();
    }
}

Provider端 DubboProtocol.java ,红色是修改的地方

private ExchangeHandler requestHandler = new ExchangeHandlerAdapter() {

    @Override
    public CompletableFuture<Object> reply(ExchangeChannel channel, Object message) throws RemotingException {
        if (message instanceof Invocation) {
            Invocation inv = (Invocation) message;
            Invoker<?> invoker = getInvoker(channel, inv);
            // need to consider backward-compatibility if it's a callback
            if (Boolean.TRUE.toString().equals(inv.getAttachments().get(IS_CALLBACK_SERVICE_INVOKE))) {
                String methodsStr = invoker.getUrl().getParameters().get("methods");
                boolean hasMethod = false;
                if (methodsStr == null || !methodsStr.contains(",")) {
                    hasMethod = inv.getMethodName().equals(methodsStr);
                } else {
                    String[] methods = methodsStr.split(",");
                    for (String method : methods) {
                        if (inv.getMethodName().equals(method)) {
                            hasMethod = true;
                            break;
                        }
                    }
                }
                if (!hasMethod) {
                    logger.warn(new IllegalStateException("The methodName " + inv.getMethodName()
                            + " not found in callback service interface ,invoke will be ignored."
                            + " please update the api interface. url is:"
                            + invoker.getUrl()) + " ,invocation is :" + inv);
                    return null;
                }
            }
            RpcContext rpcContext = RpcContext.getContext();
            boolean supportServerAsync = invoker.getUrl().getMethodParameter(inv.getMethodName(), Constants.ASYNC_KEY, false);
            if (supportServerAsync) {
                CompletableFuture<Object> future = new CompletableFuture<>();
                rpcContext.setAsyncContext(new AsyncContextImpl(future));
            }
            rpcContext.setRemoteAddress(channel.getRemoteAddress());
            // 这里将收到的consumer端的traceId放入provider端的thread local
            TraceIdUtil.setTraceId(inv.getAttachment("traceId"));
            Result result = invoker.invoke(inv);

            if (result instanceof AsyncRpcResult) {
                return ((AsyncRpcResult) result).getResultFuture().thenApply(r -> (Object) r);
            } else {
                return CompletableFuture.completedFuture(result);
            }
        }
        throw new RemotingException(channel, "Unsupported request: "
                + (message == null ? null : (message.getClass().getName() + ": " + message))
                + ", channel: consumer: " + channel.getRemoteAddress() + " --> provider: " + channel.getLocalAddress());
    }

自定义一个TraceIdUtil.java

/**
 * Created by abin on 2018/7/31.
 */
public class TraceIdUtil {
    private static final ThreadLocal<String> TRACE_ID = new ThreadLocal<String>();

    public static String getTraceId() {
        return TRACE_ID.get();
    }

    public static void setTraceId(String traceId) {
        TRACE_ID.set(traceId);
    }

}

dubbo客户端consumer代码和配置如下:

dubbo-consumer.xml:

 <dubbo:consumer filter="logSessionFilter" timeout="9000"/>

/resource/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter里面添加

logSessionFilter=com.abin.lee.dubbo.rpc.consumer.filter.RpcLogSessionFilter
RpcLogSessionFilter.java内容为:
public class RpcLogSessionFilter implements Filter {

    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        String sessionId = UUID.randomUUID().toString();
        String traceId = RpcContext.getContext().getAttachment("traceId");
        if (StringUtils.isNotBlank(traceId)) {
            System.out.println("accept traceId=" + traceId);
        } else {
            traceId = sessionId ;
            System.out.println("create traceId=" + traceId);
        }
        RpcContext.getContext().setAttachment("traceId", traceId);
        System.out.println("transfer traceId=" + traceId);
        return invoker.invoke(invocation);
    }

    public static void main(String[] args) {
        System.out.println(UUID.randomUUID().toString());
    }
}
DubboClientServer.java
package com.abin.lee.dubbo.rpc.consumer;

import com.abin.lee.dubbo.rpc.api.DubboService;
import com.abin.lee.dubbo.rpc.api.GlobalService;
import com.abin.lee.dubbo.rpc.common.util.JsonUtil;
import com.abin.lee.dubbo.rpc.enums.UserRole;
import com.abin.lee.dubbo.rpc.model.UserInfo;
import com.google.common.collect.Lists;
import org.apache.dubbo.common.TraceIdUtil;
import org.apache.dubbo.rpc.RpcContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;

/**
 * Created by abin on 2017/9/7 2017/9/7.
 * march-svr
 * com.abin.lee.march.svr.dubbo.client.view
 */
public class DubboClientServer {
    public static void main(String[] args) throws InterruptedException {
        //traceId
        main_filter();
    }

    public static void main_filter() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"classpath*:spring/dubbo-consumer.xml"});
        context.start();
        DubboService dubboService = (DubboService) context.getBean("dubboService"); // 获取bean
        String message = "";

        try {
            int randomTraceId = (int) (Math.random() * 1000);
            TraceIdUtil.setTraceId(randomTraceId+"");
            message = dubboService.build("2016-10-20");
            System.out.println("dubboService.build-- the message from server is:" + message);
            List<Integer> list = dubboService.findById(5);
            System.out.println("dubboService.findById--- the message from server is:" + JsonUtil.toJson(list));
            String traceId = RpcContext.getContext().getAttachment("traceId");
            System.out.println(" the message from server is result traceId :" + traceId);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

服务端Provider:

dubbo-provider.xml

<dubbo:provider filter="logSessionFilter"  timeout="9000"/>

/resource/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter里面添加

logSessionFilter=com.abin.lee.dubbo.rpc.provider.filter.ProviderRpcLogSessionFilter
ProviderRpcLogSessionFilter.java
import org.apache.dubbo.rpc.*;

/**
 *
 */
public class ProviderRpcLogSessionFilter implements Filter {

    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        String traceId = RpcContext.getContext().getAttachment("traceId");
        System.out.println("ProviderRpcLogSessionFilter accept traceId=" + traceId);
        //服务段处理完了,给客户端回传回去之前他自己传过来的traceId
//        RpcContext.getContext().setAttachment("traceId", traceId);
        return invoker.invoke(invocation);
    }
}
DubboServer.java
package com.abin.lee.dubbo.rpc.provider;

import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by abin on 2017/9/7 2017/9/7.
 * march-svr
 * com.abin.lee.march.svr.dubbo.server.view
 */
public class DubboServer {
    public static void main(String[] args) throws Exception {

        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"classpath*:spring/dubbo-provider.xml"});
        context.start();
        System.out.println("................................................");
        System.out.println(".......Dubbo Server is Running now!..............");
        System.out.println("................................................");
        System.in.read(); // 按任意键退出

    }
}

猜你喜欢

转载自blog.csdn.net/varyall/article/details/82557201