Dubbo源码之消费者端代理调用

由上一篇博客我们知道,消费者端调用服务,实际上是调用代理的invoke方法,内部是调用传入的handler的invoke()方法。

这里是调用了InvokerInvocationHandler的invoke()方法,我们来看下具体逻辑。

    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();
    }

这里invoker拦截了一些Object的方法,toString,hashCode,equals等方法,其他服务的方法调用invoker.invoke,传入的参数是根据参数跟方法构造的RpcInvocation。

这里,默认调用的是FailoverClusterInvoker的父类AbstractClusterInvoker的invoke方法

    public Result invoke(final Invocation invocation) throws RpcException {

        checkWhetherDestroyed();

        LoadBalance loadbalance;
        
        List<Invoker<T>> invokers = list(invocation);
        if (invokers != null && invokers.size() > 0) {
            loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(invokers.get(0).getUrl()
                    .getMethodParameter(invocation.getMethodName(),Constants.LOADBALANCE_KEY, Constants.DEFAULT_LOADBALANCE));
        } else {
            loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(Constants.DEFAULT_LOADBALANCE);
        }
        RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
        return doInvoke(invocation, invokers, loadbalance);
    }

先通过list()方法,根据传入的invocation(仅仅封装了服务名称,参数等数据)根据调用的服务信息找到相应的具体的服务调用地址集合invokers。

    protected  List<Invoker<T>> list(Invocation invocation) throws RpcException {
    	List<Invoker<T>> invokers = directory.list(invocation);
    	return invokers;
    }

我们看list具体逻辑,在AbstractDirectory中

    public List<Invoker<T>> list(Invocation invocation) throws RpcException {
        if (destroyed){
            throw new RpcException("Directory already destroyed .url: "+ getUrl());
        }
        List<Invoker<T>> invokers = doList(invocation);
        List<Router> localRouters = this.routers; // local reference
        if (localRouters != null && localRouters.size() > 0) {
            for (Router router: localRouters){
                try {
                    if (router.getUrl() == null || router.getUrl().getParameter(Constants.RUNTIME_KEY
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 回答:Dubbo调用流程主要包括:服务提供方、服务消费方和注册中心三部分组成。其中,服务提供方向注册中心注册服务,服务消费方通过注册中心发现服务并向服务提供方发起调用;服务提供方收到调用请求后,通过调用服务提供者实现服务,并将结果返回给服务消费方。可以参考以下源码解读:http://www.sohu.com/a/242295322_465833。 ### 回答2: Dubbo调用流程分为三个阶段:服务导出、服务引用和远程调用。下面我将结合源码解读这三个阶段的具体流程。 首先是服务导出阶段。当服务提供者启动时,Dubbo会解析@Service注解,生成ServiceBean对象。然后,Dubbo调用Protocol的export方法,将ServiceBean暴露成一个Invoker对象,该对象持有ServiceBean的引用和一系列的过滤器链。接着,Dubbo会通过Exporter对象,将Invoker注册到注册中心。最后,Dubbo会根据配置选择合适的Server实现,启动Server并监听服务口。 接下来是服务引用阶段。当服务消费者启动时,Dubbo会解析@Reference注解,生成ReferenceBean对象。然后,Dubbo调用ReferenceConfig的get方法,根据配置从注册中心获取服务提供者的Invoker对象。接着,Dubbo会通过Protocol的refer方法,将Invoker封装成一个代理对象,并返回给业务逻辑,实现远程调用。 最后是远程调用阶段。当业务代码调用代理对象的方法时,Dubbo会通过Invocation对象封装方法调用的相关信息。然后,Dubbo会根据服务的URL信息选择合适的InvocationHandler,发起远程调用。在InvocationHandler中,Dubbo会对请求进行编码、协议适配和消息传输,最终将请求发送给服务提供者。服务提供者接收到请求后,会根据请求内容执行相应的服务逻辑,并返回结果。最后,Dubbo会将结果进行解码、协议适配和消息传输,将结果返回给服务消费者。 通过源码解读可以看出,Dubbo调用流程主要包括服务导出、服务引用和远程调用三个阶段,并且每个阶段都有一系列的类和方法来协调和处理相应的任务。这样的设计使得Dubbo具备了高度的扩展性和灵活性,能够支持不同的协议和中间件,并提供了一系列的配置选项,满足不同场景下的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值