dubbo源码分析第十二篇一dubbo远程调用第二小节一消费端rpc层发送消息核心源码解析

文章目录

  • 流程图示
  • 源码分析
    • InvokerInvocationHandler.invoke
    • MockClusterInvoker.invoke容错降级
    • AbstractClusterInvoker.invoke 获取负载均衡实现以及服务端集合
    • FailoverClusterInvoker.invoke 支持重试的clusterInvoker
    • CallbackRegistrationInvoker监听过滤
    • AsyncToSyncInvoker.invoke异步转同步
    • dubboInvoker.doinvoke调用remote层远程通信
  • 总结

流程图示

dubbo源码分析第十二篇一dubbo远程调用第二小节一消费端rpc层发送消息核心源码解析_第1张图片

源码分析

InvokerInvocationHandler.invoke

  • 代理入口,对方法的调用,代理拦截后调用invoker.invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    ...... 删除equals hashcode等方法调用 
    调用MockClusterInvoker 构建调用会话
    return invoker.invoke(new RpcInvocation(method, args)).recreate();
}

MockClusterInvoker.invoke容错降级

  • 配置force则直接降级
  • 配置fail则失败降级
  • 无配置正常调用服务端
public Result invoke(Invocation invocation) throws RpcException {
    Result result = null;
    获取容错降级配置
    String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), MOCK_KEY, Boolean.FALSE.toString()).trim();
    if (value.length() == 0 || "false".equalsIgnoreCase(value)) {
        step-1: 无配置直接调用
        result = this.invoker.invoke(invocation);
    } else if (value.startsWith("force")) {
        step-2: 强制降级直接走降级逻辑 一般配置于dubbo面板
        result = doMockInvoke(invocation, null);
    } else {
       step-3: 容错直接调用 异常走降级逻辑
        try {
            result = this.invoker.invoke(invocation);
            区分rpc业务异常与远程调用异常
            if(result.getException() != null && result.getException() instanceof RpcException){
                RpcException rpcException= (RpcException)result.getException();
                if(rpcException.isBiz()){
                    throw  rpcException;
                }else {
                    result = doMockInvoke(invocation, rpcException);
                }
            }

        } catch (RpcException e) {
            if (e.isBiz()) {
                throw e;
            }
            result = doMockInvoke(invocation, e);
        }
    }
    return result;
}

AbstractClusterInvoker.invoke 获取负载均衡实现以及服务端集合

  • 通过directory获取服务端所有注册的提供者
  • 通过url获取负载均衡实现
  • 执行doinvoke
public Result invoke(final Invocation invocation) throws RpcException {
    checkWhetherDestroyed();
    添加上下文附件到远程会话对象上
    Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();
    if (contextAttachments != null && contextAttachments.size() != 0) {
        ((RpcInvocation) invocation).addAttachments(contextAttachments);
    }
    通过directory获取服务端所有注册的提供者
    List<Invoker<T>> invokers = list(invocation);
    通过url获取负载均衡实现
    LoadBalance loadbalance = initLoadBalance(invokers, invocation);
    RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
    return doInvoke(invocation, invokers, loadbalance);
}

FailoverClusterInvoker.invoke 支持重试的clusterInvoker

  • 循环重试
  • 通过负载均衡选择Invoker
  • 执行Invoker调用
 public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
    List<Invoker<T>> copyInvokers = invokers;
    checkInvokers(copyInvokers, invocation);
    String methodName = RpcUtils.getMethodName(invocation);
    int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1;
    if (len <= 0) {
        len = 1;
    }
    
    RpcException le = null;
    List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyInvokers.size()); // invoked invokers.
    Set<String> providers = new HashSet<String>(len);
    len表示重试次数
    for (int i = 0; i < len; i++) {
        ...... 删除部分代码
        负载均衡选择
        Invoker<T> invoker = select(loadbalance, invocation, copyInvokers, invoked);
        invoked.add(invoker);
        RpcContext.getContext().setInvokers((List) invoked);
        try {
            Result result = invoker.invoke(invocation);
            return result;
        } catch (RpcException e) {
            ...... 删除部分代码
            throw e;
        } 
    }
    ...... 删除部分代码
}

CallbackRegistrationInvoker监听过滤

  • 过滤器链执行 最后执行下一个Invoker
  • ListenableFilter能够对asyncResult进行监听[这里代码删除]
  @Override
        public Result invoke(Invocation invocation) throws RpcException {
            过滤器链执行 最后执行dubboInvoker
            Result asyncResult = filterInvoker.invoke(invocation);
            ...... 删除具有监听功能的过滤器
            return asyncResult;
        }

AsyncToSyncInvoker.invoke异步转同步

  • 一般默认是同步模式
  • 通过future机制实现异步

public Result invoke(Invocation invocation) throws RpcException {
    asyncResult是一个future
    Result asyncResult = invoker.invoke(invocation);
    如果同步则无限等待获取结果
  
    if (InvokeMode.SYNC == ((RpcInvocation) invocation).getInvokeMode()) {
        asyncResult.get(Integer.MAX_VALUE, TimeUnit.MILLISECONDS);
    }
    ...... 删除异常代码
    如果异步直接返回future
    return asyncResult;
}

dubboInvoker.doinvoke调用remote层远程通信

  • 调用通信层进行远程通信
  • 返回future对象,上层Invoker通过get阻塞
protected Result doInvoke(final Invocation invocation) throws Throwable {
    RpcInvocation inv = (RpcInvocation) invocation;
    final String methodName = RpcUtils.getMethodName(invocation);
    接口名+端口号
    inv.setAttachment(PATH_KEY, getUrl().getPath());
    inv.setAttachment(VERSION_KEY, version);
    获取ExchangeClient
    ...... 删除client的选择 一般默认就一个共享连接
    ...... 删除部分代码
    boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
    int timeout = getUrl().getMethodPositiveParameter(methodName, TIMEOUT_KEY, DEFAULT_TIMEOUT);
    区分单边,比如心跳包等
    if (isOneway) {
        boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
        currentClient.send(inv, isSent);
        return AsyncRpcResult.newDefaultAsyncResult(invocation);
    } else {
        核心
        AsyncRpcResult asyncRpcResult = new AsyncRpcResult(inv);
        进行请求
        CompletableFuture<Object> responseFuture = currentClient.request(inv, timeout);
        asyncRpcResult.subscribeTo(responseFuture);
        FutureContext.getContext().setCompatibleFuture(responseFuture);
        返回请求future对象,responseFuture并没有真正请求完毕,在异步转同步Invoker处阻塞
        return asyncRpcResult;
    }
   
}

总结

  • 除去FailoverClusterInvoker还有多种容错策略
  • 整个容错核心在于 ***ClusterInvoker
  • 整个负载均衡核心在于loadbalance.select
  • directory.list出了列举服务提供者集合,还处理了router路由过滤[tag,script,condition等]

你可能感兴趣的:(dubbo源码分析,rpc,java,网络协议,dubbo)