Dubbo之服务消费
Dubbo的服务消费主要包括两个部分。第一大步是ReferenceConfig类的init方法调用Protocol的refer方法生成Invoker实例,这是服务消息的关键。第二大步是把Invoker通过动态代理转换成实现用户接口的动态代理引用。这里的Invoker承载了网络连接、服务调用和重试等功能。
服务暴露起点
在消费者的配置文件中存在这个代码:
<!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
<dubbo:reference id="demoService" interface="org.apache.dubbo.demo.DemoService" />
它会生成一个ReferenceBean,实现了FactoryBean接口,继承了ReferenceConfig,所以ReferenceBean作为dubbo中能够生产对象的工厂Bean,而我们要引用服务,也就要有一个该服务的对象。
public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean,
ApplicationContextAware, InitializingBean, DisposableBean {
服务引用被触发有两个时机:
- Spring容器调用ReferenceBean的afterPropertiesSet方法时引用服务(饿汉式)
- 在ReferenceBean对应的服务被注入到其他类中时引用(懒汉式)
默认情况下,Dubbo使用懒汉式引用服务。如果需要使用饿汉式,可通过配置dubbo:reference的init属性开启。
因为ReferenceBean实现了FactoryBean接口的getObject()方法,所以在加载bean的时候,会调用ReferenceBean的getObject()方法。
ReferenceBean.getObject() ---> ReferenceConfig.get() --> ReferenceConfig.init()
在init()方法中主要有这几步:
(1) 检测本地存根和mock合法性
(2) 添加协议版本、发布版本、时间戳、application、module、consumer、protocol等所有信息到map中。
(3) 单独处理方法配置,设置重试次数配置以及设置该方法对异步配置信息。
(4) 添加消费者ip地址到map
(5)创建代理对象,调用ReferenceConfig.createProxy()方法。
(6) 生成ConsumerMpdel存入到ApplicationModel中。
之后介绍ReferenceConfig.createProxy()方法。主要有下面几步:
- 如果是本地调用,则直接使用InjvmProtocol的refer方法生成Invoker实例。
- 如果不是本地调用,但是选择直连的方式进行调用,则分割配置的多个url。如果协议是配置registry,则表明用户想使用指定的注册中心,配置url后将url保存到urls里面,否则就合并url,并且保存到urls。
- 如果是通过注册中心来进行调用,则先校验所有的注册中心,然后假加载注册中心的url,遍历每个url,加入监控中心url配置,最后把每个url保存到urls。
- 如果urls的个数是1,是单注册中心,直接引用RegistryProtocol的refer构建Invoker实例;如果urls的数量大于1,说明是多注册中心,则对每个url都生成Invoker,利用
cluster.join()方法将多个Invoker进行合并成一个Invoker。 - 最后调用
proxyFactory.getProxy(invoker)方法。
然后介绍RegistryProtocol.refer(Class<T> type, URL url)方法生成invoker。
如果是注册中心服务,则直接返回注册中心服务的invoker;如果不是,则先处理组配置,根据组配置来决定Cluster的实现方式,如果有多个组,则使用MergeableCluster,然后调用doRefer(Cluster, Registry, Class, URL)方法。
然后介绍doRefer()方法。
(1) 创建一个RegistryDirectory实例,设置注册中心、协议等信息
(2) 生成服务消费者链接。
(3) 注册消费信息到注册中心。
(4) 订阅该服务下的providers、configurators、routers等节点下的数据。完成订阅后,RegistryDirectory会受到这几个节点下的子节点信息。
(5) 由于一个服务可能部署在多台服务器上,这样就会在providers产生多个节点,这个时候就需要Cluster将多个服务节点合并成一个,并生成一个Invoker.
在RegistryDirectory实现了NotifyListener接口,服务变更会触发这个类回调notify方法,用于重新引用服务。当发起订阅请求时会进行一次数据拉取操作,同时触发RegistryDirectory.nofity()方法。这是会执行toInvokers()方法进行Invoker转换。
(1) 根据消费者protocol配置过滤不匹配的协议。
(2) 合并provider端配置数据,比如服务端IP和port等。
(3) 忽略重复推送的服务列表
(4) 使用具体协议创建远程连接,new InvokerDelegate<T>(protocol.refer(serviceType, url), url, providerUrl)。
具体的Invoker创建是在DubboProtocol.refer()中实现。Dubbo协议在返回DubboInvoker对象之前会初始化客户端连接对象。
调用DubboProtocol.initClient()方法 -> Exchangers.connect()方法,根据SPI机制加载HeaderExchangeClent,调用connect()方法。然后调用Transporter类的connect()方法,默认是NettyTransporter类。
public class DubboInvoker<T> extends AbstractInvoker<T> {
private final ExchangeClient[] clients;
private final AtomicPositiveInteger index = new AtomicPositiveInteger();
private final String version;
private final ReentrantLock destroyLock = new ReentrantLock();
private final Set<Invoker<?>> invokers;
public abstract class AbstractInvoker<T> implements Invoker<T> {
protected final Logger logger = LoggerFactory.getLogger(getClass());
private final Class<T> type;
private final URL url;
private final Map<String, Object> attachment;
private volatile boolean available = true;
private AtomicBoolean destroyed = new AtomicBoolean(false);
Dubbo之服务消费的更多相关文章
- Dubbo之服务消费原理
前言 上篇文章<Dubbo之服务暴露>分析 Dubbo 服务是如何暴露的,本文接着分析 Dubbo 服务的消费流程.主要从以下几个方面进行分析:注册中心的暴露:通过注册中心进行服务消费通知 ...
- 使用dubbo分布式服务框架发布服务及消费服务
什么是DUBBO DUBBO是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案. 准备工作 安装zookeeper ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服 ...
- dubbo注册服务和消费服务---入门篇
本文介绍如何用dubbo+zk来实现一个注册服务 + 消费服务的入门小demo 需要环境:zk服务器 两个maven项目,一个负责提供服务,一个负责消费服务. dubbo-service 服务端 po ...
- Dubbo学习笔记10:Dubbo服务消费方启动流程源码分析
同理我们看下服务消费端启动流程时序图: 在<Dubbo整体架构分析>一文中,我们提到服务消费方需要使用ReferenceConfig API来消费服务,具体是调用代码(1)get()方法来 ...
- Dubbo学习笔记4:服务消费端泛化调用与异步调用
本文借用dubbo.learn的Dubbo API方式来解释原理. 服务消费端泛化调用 前面我们讲解到,基于Spring和基于Dubbo API方式搭建简单的分布式系统时,服务消费端引入了一个SDK二 ...
- Spring Cloud Alibaba(四)实现Dubbo服务消费
本项目演示如何使用 Spring Cloud Alibaba 完成 Dubbo 的RPC调用. Spring Cloud与Dubbo Spring Cloud是一套完整的微服务架构方案 Dubbo是国 ...
- dubbo入门之服务消费
今天,我们来看看dubbo消费的执行过程 首先,我们都知道dubbo是一个基于netty实现的RPC框架,底层通信是使用netty来实现的.在学习dubbo的时候,或许我们都会有下面的这些疑惑: 1. ...
- 源码分析Dubbo服务消费端启动流程
通过前面文章详解,我们知道Dubbo服务消费者标签dubbo:reference最终会在Spring容器中创建一个对应的ReferenceBean实例,而ReferenceBean实现了Spring生 ...
- Dubbo分布式服务框架入门
参考http://blog.csdn.net/u013142781/article/details/50387583 一.Dubbo概念介绍 1.1.Dubbo是什么? Dubbo是一个分布式服务框架 ...
随机推荐
- C语言三(2)
多重 if...else....else 结构 语法: if(条件1) { 语句1; } else if(条件2) { 语句2; } else if(条件3) { 语句3; } else { 语句N; ...
- HTML连载70-相片墙、盒子阴影和文字阴影
一. 制作一个相片墙 二. <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...
- 「Spark」Spark SQL Thrift Server运行方式
Spark SQL可以使用JDBC/ODBC或命令行接口充当分布式查询引擎.这种模式,用户或者应用程序可以直接与Spark SQL交互,以运行SQL查询,无需编写任何代码. Spark SQL提供两种 ...
- 邓士鹏【MySql大全】
禁止使用系统关键字: typename 1.计算两个日期的时间差函数 SELECT TIMESTAMPDIFF(MONTH,'2009-10-01','2009-09-01'); interval可是 ...
- mybatis 自学笔记
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.本页作为自学整理资料,信息来源网络,侵权速联,但大部份经过自己测试.使用说明:本人测试用编辑软件eclipse_st ...
- Vue中使用NProgress实现进度条
简介 NProgress是页面跳转或者发生异步请求是浏览器顶部的进度条 GitHub地址:https://github.com/rstacruz/nprogress 在线演示地址:http://ric ...
- 【干货】Python基础——列表
1.列表的创建 列表是多个.有序.可重复的元素集合,数据包装在“[]”里,列表中的元素可以是任何类型,甚至可以是一个列表.创建列表有两种方法: A 对于规模比较小的列表可以直接定义和赋值,列表可以嵌套 ...
- c# 异步编程 使用回调函数例子
环境VS2010, 在项目属性中输出类型选择控制台应用程序 运行结果 using System;using System.Collections.Generic;using System.Compon ...
- 保存为pickle
保存为pickle import pickle # 保存模型 with open('model.pickle', 'wb') as f: pickle.dump(model, f) # 读取模型 wi ...
- Windows显示默认桌面图标(计算机,用户的文件,网络,控制面板,回收站)
1.按Win+R 2.复制以下命令 rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,0 3.点击运行,根据需求勾选相应图标即可