• 从消费者到提供者的调用栈


    consumer:

    在NettyChannel.send中加断点,显示调用栈

    helloService.sayFuck();

    provider:

    在方法实现里面,加断点得到调用栈

    如以上2图,从consumer到provider的步骤一目了然。

    consumer对应NettyClient,provider对应NettyServer。

    之前对dubbo method的重试次数有点疑惑,在图1的consumer调用栈中,FailoverClusterInvoker<T>.doInvokede方法中有具体处理逻辑,也就是说重试是从consumer发起的。

    ProtocolFilterWrapper的buildInvokerChain方法生成filter链:provider和consumer的filter是不同的

    public interface Invoker<T> extends Node {
        //我们主要关心这个方法
        Result invoke(Invocation invocation) throws RpcException;
    }
    
    //ProtocolFilterWrapper类
    private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
            //dubbo最终会调用的invoker,或者说是我们的业务servlce的代理
        Invoker<T> last = invoker;
        List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
        if (filters.size() > 0) {
            for (int i = filters.size() - 1; i >= 0; i --) {
                final Filter filter = filters.get(i);
                final Invoker<T> next = last;
                //通过创建匿名内部类对象,生成filter链
                //虽然这只是一个匿名内部类对象,这个类有3个属性需要关注:
                //final Invoker<T> invoker 算是业务对象的代理吧
                //final Filter filter 该invoker的filter,filter中有dubbo框架逻辑
                //final Invoker<T> next 把各个匿名invoker链起来
                last = new Invoker<T>() {
                    //省略掉其他代码
                    public Result invoke(Invocation invocation) throws RpcException {
                        //各filter实现dubbo框架的逻辑    
                        return filter.invoke(next, invocation);
                    }
                };
            }
        }
        return last;
    }
    
    /**
    假定有两个匿名Invoker对象,invoker1和invoker2,invoker1的filter是TimeoutFilter,next是invoker2,
    invoker2的filter是ExceptionFilter,next就是业务service代理了。 *
    */ //TimeoutFilter类 @Activate(group = Constants.PROVIDER) public class TimeoutFilter implements Filter { private static final Logger logger = LoggerFactory.getLogger(TimeoutFilter.class); //对应调用语句filter.invoke(next, invocation) public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { long start = System.currentTimeMillis(); //执行next的调用 Result result = invoker.invoke(invocation); long elapsed = System.currentTimeMillis() - start; //可以看出,timeoutFilter只是打印超时日志,并没其他动作 if (invoker.getUrl() != null && elapsed > invoker.getUrl().getMethodParameter(invocation.getMethodName(), "timeout", Integer.MAX_VALUE)) { if (logger.isWarnEnabled()) { logger.warn("invoke time out. method: " + invocation.getMethodName() + "arguments: " + Arrays.toString(invocation.getArguments()) + " , url is " + invoker.getUrl() + ", invoke elapsed " + elapsed + " ms."); } } return result; } } //ExceptionFilter类 @Activate(group = Constants.PROVIDER) public class ExceptionFilter implements Filter { private final Logger logger; public ExceptionFilter() { this(LoggerFactory.getLogger(ExceptionFilter.class)); } public ExceptionFilter(Logger logger) { this.logger = logger; } //当调用这个filter时,参数invoker已经是业务service的代理了 public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { try { Result result = invoker.invoke(invocation); if (result.hasException() && GenericService.class != invoker.getInterface()) { try { Throwable exception = result.getException(); // 如果是checked异常,直接抛出 if (! (exception instanceof RuntimeException) && (exception instanceof Exception)) { return result; } // 在方法签名上有声明,直接抛出 try { Method method = invoker.getInterface().getMethod(invocation.getMethodName(), invocation.getParameterTypes()); Class<?>[] exceptionClassses = method.getExceptionTypes(); for (Class<?> exceptionClass : exceptionClassses) { if (exception.getClass().equals(exceptionClass)) { return result; } } } catch (NoSuchMethodException e) { return result; } // 未在方法签名上定义的异常,在服务器端打印ERROR日志 logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", exception: " + exception.getClass().getName() + ": " + exception.getMessage(), exception); // 异常类和接口类在同一jar包里,直接抛出 String serviceFile = ReflectUtils.getCodeBase(invoker.getInterface()); String exceptionFile = ReflectUtils.getCodeBase(exception.getClass()); if (serviceFile == null || exceptionFile == null || serviceFile.equals(exceptionFile)){ return result; } // 是JDK自带的异常,直接抛出 String className = exception.getClass().getName(); if (className.startsWith("java.") || className.startsWith("javax.")) { return result; } // 是Dubbo本身的异常,直接抛出 if (exception instanceof RpcException) { return result; } // 否则,包装成RuntimeException抛给客户端 return new RpcResult(new RuntimeException(StringUtils.toString(exception))); } catch (Throwable e) { logger.warn("Fail to ExceptionFilter when called by " + RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e); return result; } } return result; } catch (RuntimeException e) { logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e); throw e; } } }

     附上一张provider buildFilterChain的变量图:

  • 相关阅读:
    win32 tcp文件传输客户端
    Android窗口管理服务WindowManagerService对输入法窗口(Input Method Window)的管理分析
    和菜鸟一起深入学习国嵌实验之vim常用命令
    和菜鸟一起深入学习国嵌实验之linux常用命令
    和菜鸟一起深入学习国嵌实验之文件编程
    和菜鸟一起深入学习国嵌实验之gcc分步编译&&gdb调试
    和菜鸟一起深入学习国嵌实验之简单Makefile
    获得创建表脚本
    oralce中获得创建脚本
    所有数据库连接字符串
  • 原文地址:https://www.cnblogs.com/allenwas3/p/7569898.html
Copyright © 2020-2023  润新知