Dubbo源码分析 (四)之服务调用原理

本文深入分析了Dubbo服务消费的过程,从获取接口代理类开始,经由MockClusterInvoker调用、FailoverClusterInvoker的路由与负载均衡,到执行服务提供者Invoker,再到信息交换层的请求封装与发送,最后详述了数据的解码与响应处理,揭示了Dubbo RPC调用的全貌。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

目录

服务消费过程

1:获取对应接口服务的代理类

2:委托接口代理类查找可执行的Invoker(服务提供者)

1)调用接口方法

2)proxy0.要执行的方法 //代理执行,

3)代理执行this.handler.invoke(this, methods[0], arrayOfObject); 

4)MockClusterInvoker.invoke(new RpcInvocation(method, args)).recreate();

5)容错集群执行 FailoverClusterInvoker.invoke 处理隐式传参,目录查找所有服务提供则,以及获取对应的负载均衡算法

6)容错集群执行 FailoverClusterInvoker.doInvoke 进行路由Router过滤,和负载均衡算法选出一个Invoker(服务提供者)

3:执行服务提供者Invoker

1)执行Filter 链

2)执行DubboInvoker.invoke->DubboInvoker.doInvoke 获取与服务提供者建立的连接客户端,随后将请求委派客户端发送

4:currentClient.request(inv, timeout).get()  请求进入信息交换层Exchange,封装Request

5:请求Request 进入Transport层,进行传输层数据发送 (NettyClient.send)

6:request 委托socket发送完毕后,返回DefaultFuture,调用其get方法,阻塞当前消费线程

7:接受服务提供者返回数据,消费线程被唤醒


服务消费过程

1:获取对应接口服务的代理类

如:proxy0 implements ClassGenerator.DC, EchoService, DemoService 见下文

2:委托接口代理类查找可执行的Invoker(服务提供者)

过程如:

1)调用接口方法

如:demoService.sayHello

2)proxy0.要执行的方法 //代理执行,

见图1

3)代理执行this.handler.invoke(this, methods[0], arrayOfObject); 

//InvokerInvocationHandler.invoke 见图2

4)MockClusterInvoker.invoke(new RpcInvocation(method, args)).recreate();

//见图3

     图1:              

package com.alibaba.dubbo.common.bytecode;
import com.alibaba.dubbo.demo.DemoService;
import com.alibaba.dubbo.rpc.service.EchoService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
 
//通过JavassistProxyFactory 为接口生成的代理类如下:
public class proxy0
  implements ClassGenerator.DC, EchoService, DemoService 
{
  public static Method[] methods;
  private InvocationHandler handler;
  //为 InvokerInvocationHandler 包装了MockClusterInvoker(其具备集群容错,目录查找,路由功能的Invoker)
  
  public String sayHello(String paramString)
  {
    Object[] arrayOfObject = new Object[1];
    arrayOfObject[0] = paramString;
    Object localObject = this.handler.invoke(this, methods[0], arrayOfObject);
    return (String)localObject;
  }
  
  public Object $echo(Object paramObject)
  {
    Object[] arrayOfObject = new Object[1];
    arrayOfObject[0] = paramObject;
    Object localObject = this.handler.invoke(this, methods[1], arrayOfObject);
    return (Object)localObject;
  }
  
  public proxy0() {}
  
  public proxy0(InvocationHandler paramInvocationHandler)
  {
    this.handler = paramInvocationHandler;
  }
}
 
所以无论是基于JDK还是Javassit 生成的消费接口的动态代理类,在进行方法调用的时候
都是直接执行到InvokerInvocationHandler 中的invoke方法,然后通过Invoker方法在执行MockClusterInvoker中的invoke方法
 
public class InvokerInvocationHandler implements InvocationHandler {
    private final Invoker<?> 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]);
        }
        return invoker.invoke(new RpcInvocation(method, args)).recreate();//接口代理类的方法执行,最后会执行到此处
		//new RpcInvocation(method, args) 封装需要执行的接口类方法信息和方法参数,
		//通过一系类的处理后,将方法调用信息和参数传递给服务提供者(后续具体过程讲解)。
    }
 
}

图2:

图3:

5)容错集群执行 FailoverClusterInvoker.invoke 处理隐式传参,目录查找所有服务提供则,以及获取对应的负载均衡算法

    public Result invoke(final Invocation invocation) throws RpcException {
        checkWhetherDestroyed();
        LoadBalance loadbalance = null;

        // binding attachments into invocation.
        Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();//获取隐式传参
        if (contextAttachments != null && contextAttachments.size() != 0) {
            ((RpcInvocation) invocation).addAttachments(context
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值