Export发布服务流程

Dubbo协议向注册中心发布服务:当服务提供方,向dubbo协议的注册中心发布服务的时候,是如何获取,创建注册中心的,如何注册以及订阅服务的,下面我们来分析其流程。

看如下配置发布服务:

<!-- 指定了哪种的注册中心,是基于zookeeper协议的,指定了注册中心的地址以及端口号 -->
<dubbo:registry protocol="zookeeper" client="zkclient" address="localhost:2181" group="dubbo"/>
<bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>
<!-- 发布DemoService服务,服务的实现为DemoServiceImpl -->
<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>

每个<dubbo:service/>在Spring内部都会生成一个ServiceBean实例,ServiceBean的实例化过程中调用export方法来暴露服务

1. 通过loadRegistries获取注册中心registryUrls

registry://localhost:2181/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&client=zkclient&dubbo=2.6.1&group=dubbo&logger=slf4j&pid=8012&registry=zookeeper&timestamp=1532198612419

用统一数据模型URL表示:

  • protocol=registry      表示一个注册中心URL
  • 注册中心地址      localhost:2181
  • 调用注册中心的服务     RegistryService
  • 注册中心协议        registry=zookeeper
  • 。。。。。。

2. 构建发布服务的URL

dubbo://192.168.56.1:20882/org.apache.dubbo.demo.DemoService?anyhost=true&application=demo-provider&buffer=8192&dispatcher=all&dubbo=2.6.1&executes=3&generic=false&interface=org.apache.dubbo.demo.DemoService&iothreads=2&loadbalance=leastactive&logger=slf4j&methods=sayHello&pid=8012&queues=300&retries=0&side=provider&threadpool=fixed&threads=10&timeout=300&timestamp=1532198751165
  • 发布协议      protocol =dubbo
  • 服务提供者的地址  192.168.56.1:20882
  • 发布的服务    com.alibaba.dubbo.demo.DemoService
  • 。。。。。。

3. 遍历registryUrls向注册中心注册服务

给每个registryUrl添加属性key为export,value为上面的发布服务url得到如下registryUrl

registry://localhost:2181/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&client=zkclient&dubbo=2.6.1&group=dubbo&logger=slf4j&pid=8012&registry=zookeeper&timestamp=1532198612419&export=dubbo%3a%2f%2f192.168.56.1%3a20882%2forg.apache.dubbo.demo.DemoService%3fanyhost%3dtrue%26application%3ddemo-provider%26buffer%3d8192%26dispatcher%3dall%26dubbo%3d2.6.1%26executes%3d3%26generic%3dfalse%26interface%3dorg.apache.dubbo.demo.DemoService%26iothreads%3d2%26loadbalance%3dleastactive%26logger%3dslf4j%26methods%3dsayHello%26pid%3d8012%26queues%3d300%26retries%3d0%26side%3dprovider%26threadpool%3dfixed%26threads%3d10%26timeout%3d300%26timestamp%3d1532198751165

4. 由发布的服务实例,服务接口以及registryUrl为参数,通过代理工厂proxyFactory获取Invoker对象,Invoker对象是dubbo的核心模型,其他对象都向它靠拢或者转换成它。

5. 通过Protocol对象暴露服务protocol.export(invoker)

  • 通过DubboProtocol暴露服务的监听;
  • 通过RegistryProtocol将服务地址发布到注册中心,并订阅此服务。

以上逻辑,在ServiceConfig类中的doExportUrlsFor1Protocol实现:

        String scope = url.getParameter(Constants.SCOPE_KEY);
// don't export when none is configured
// 配置为none不暴露
if (!Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) { // export to local if the config is not remote (export to remote only when config is remote)
// 配置不是remote的情况下做本地暴露 (配置为remote,则表示只暴露远程服务)
if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) {
exportLocal(url);
}
// export to remote if the config is not local (export to local only when config is local)
// 如果配置不是local则暴露为远程服务.(配置为local,则表示只暴露远程服务)
if (!Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope)) {
if (logger.isInfoEnabled()) {
logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
}
if (registryURLs != null && !registryURLs.isEmpty()) {
for (URL registryURL : registryURLs) {
url = url.addParameterIfAbsent("dynamic", registryURL.getParameter("dynamic"));
URL monitorUrl = loadMonitor(registryURL);
if (monitorUrl != null) {
url = url.addParameterAndEncoded(Constants.MONITOR_KEY, monitorUrl.toFullString());
}
if (logger.isInfoEnabled()) {
logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);
}
Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));
DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this); Exporter<?> exporter = protocol.export(wrapperInvoker);
exporters.add(exporter);
}
} else {
Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this); Exporter<?> exporter = protocol.export(wrapperInvoker);
exporters.add(exporter);
}
}
}
this.urls.add(url);

RegistryProtocol.export(Invoker)暴露服务

META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol 文件中配置如下:

registry=com.alibaba.dubbo.registry.integration.RegistryProtocol

因为上一步中url为registry://开头,因此使用的是RegistryProtocol类。

    public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {
//export invoker
final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker); URL registryUrl = getRegistryUrl(originInvoker); //registry provider
final Registry registry = getRegistry(originInvoker);
final URL registedProviderUrl = getRegistedProviderUrl(originInvoker); //to judge to delay publish whether or not
boolean register = registedProviderUrl.getParameter("register", true); ProviderConsumerRegTable.registerProvider(originInvoker, registryUrl, registedProviderUrl); if (register) {
register(registryUrl, registedProviderUrl);
ProviderConsumerRegTable.getProviderWrapper(originInvoker).setReg(true);
} // Subscribe the override data
// 订阅override数据
// FIXME When the provider subscribes, it will affect the scene : a certain JVM exposes the service and call the same service. Because the subscribed is cached key with the name of the service, it causes the subscription information to cover.
// FIXME 提供者订阅时,会影响同一JVM即暴露服务,又引用同一服务的的场景,因为subscribed以服务名为缓存的key,导致订阅信息覆盖。
final URL overrideSubscribeUrl = getSubscribedOverrideUrl(registedProviderUrl);
final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl, originInvoker);
overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener);
registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);
//Ensure that a new exporter instance is returned every time export
// 保证每次export都返回一个新的exporter实例
return new DestroyableExporter<T>(exporter, originInvoker, overrideSubscribeUrl, registedProviderUrl);
}

以上函数中,doLocalExport(originInvoker)就是调用正常的protocol的export过程,进行暴露。

这里我们针对demo的例子,在debug过程中记录如下信息:

registedProviderUrl

dubbo://192.168.56.1:20882/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&pid=6324&side=provider&timestamp=1428237661384

overrideSubscribeUrl

provider://192.168.56.1:20882/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&pid=6324&side=provider&timestamp=1428237661384

注册时应该是将registedProviderUrl传递到注册中心,注册中心记录相应信息。这里我们可以理解为,消费者访问注册中心时,根据消费者需要获得的服务去读取服务提供者(url)。 而订阅时,则是根据overrideSubscribeUrl地址和overrideSubscribeListener监听。overrideSubscribeListener监听的作用是当提供者的url改变时,重新export。

Dubbo实践(十四)生产者发布服务的更多相关文章

  1. JAVA之旅(三十四)——自定义服务端,URLConnection,正则表达式特点,匹配,切割,替换,获取,网页爬虫

    JAVA之旅(三十四)--自定义服务端,URLConnection,正则表达式特点,匹配,切割,替换,获取,网页爬虫 我们接着来说网络编程,TCP 一.自定义服务端 我们直接写一个服务端,让本机去连接 ...

  2. Gradle 1.12用户指南翻译——第六十四章. 发布到Ivy(新)

    其他章节的翻译请参见:http://blog.csdn.net/column/details/gradle-translation.html翻译项目请关注Github上的地址:https://gith ...

  3. 第四十四章 微服务CICD(6)- gitlab + jenkins + docker + k8s

    总体流程: 在开发机开发代码后提交到gitlab 之后通过webhook插件触发jenkins进行构建,jenkins将代码打成docker镜像,push到docker-registry 之后将在k8 ...

  4. Kubernetes学习之路(十四)之服务发现Service

    一.Service的概念 运行在Pod中的应用是向客户端提供服务的守护进程,比如,nginx.tomcat.etcd等等,它们都是受控于控制器的资源对象,存在生命周期,我们知道Pod资源对象在自愿或非 ...

  5. Dubbo实践(四)设计模式

    Dubbo框架在初始化和通信过程中使用了多种设计模式,可灵活控制类加载.权限控制等功能. 工厂模式 Provider在export服务时,会调用ServiceConfig的export方法.Servi ...

  6. 三十四、www服务apache进阶

    9.虚拟主机:部署多个站点,每个站点希望用不同的站点域名和站点目录,或者是不同的端口和不同的IP,则需要虚拟主机,简单理解就是一个http服务要配置多个站点,就要虚拟主机. apache虚拟主机分为三 ...

  7. Linux系统学习 十四、VSFTP服务—配置文件解析、客户端使用

    3.配置文件解析 默认配置选项: 一般情况下不允许匿名用户登录 全局配置选项:(手工添加) listen_address=192.168.4.1             #设置监听地址 listen_ ...

  8. 使用dubbo分布式服务框架发布服务及消费服务

    什么是DUBBO DUBBO是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案. 准备工作 安装zookeeper ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服 ...

  9. 十分钟搭建微服务框架(SpringBoot +Dubbo+Docker+Jenkins源码)

    本文将以原理+实战的方式,首先对“微服务”相关的概念进行知识点扫盲,然后开始手把手教你搭建这一整套的微服务系统. 这套微服务框架能干啥? 这套系统搭建完之后,那可就厉害了: 微服务架构 你的整个应用程 ...

随机推荐

  1. hdu 1159(DP+字符串最长公共序列)

    http://blog.csdn.net/a_eagle/article/details/7213236 公共序列可以用一个二维数组dp[i][j]保存每个点时的最大数字,本质就是一个双向比较. dp ...

  2. Delegate背后的秘密

    表面上看来使用delegate是一件很简单的事. 用delegate关键字定义,使用老套的new创建一个instance ,使用熟悉的方法调用写法调用,只不过不在是方法名,而是委托名. 但是在这背后C ...

  3. MySQL的约束、多表查询、子查询

    一.约束之主键约束 约束:约束是添加在列上的,用来约束列的. 1.主键约束(唯一标识):非空.唯一.被引用 当表的某一列被指定为主键后,该类就不能为空,不能有重复值出现 创建表时指定主键的两种方式: ...

  4. Effective C++ .47 traits与模板特化

    #include <iostream> #include <cstdlib> #include <string> using namespace std; temp ...

  5. Reporting Service 2005 迁移 到 2008

    1. 备份ReportServer 和ReportServerTempDB 的数据库. 2. 在Reporting Services Configuration Manager 中备份Encrypti ...

  6. 压力测试Jmeter+badboy

    压力测试Jmeter+badboy 前言:很多人都想学习压力测试,但是一开始手动写脚本着实蛋疼,所以今天我教大家的是利用badboy来录制压测脚本,然后用Jmeter来做压力测试. 流程:badboy ...

  7. Java基础之基本数据类型的包装类型

    Java的基本数据类型的包装数据类型有多种: int Integer,short Short,boolean Boolean,float Float,double Double等等. Java包装类数 ...

  8. Visual Studio 2017RC 版本相关资料

    Visual Studio 2017 RC版本说明 1.社区版 Visual Studio Community 2017 RC Visual Studio Community 2017 RC 是针对个 ...

  9. 传递给数据库 'model' 中的日志扫描操作的日志扫描号无效

    状况描述:在服务器的管理中重新启动MSSQLSERVER启动后马上又停止   通过"事件查看器" 发现 错误: ,严重度: ,状态: LSN(::)无效.该 LSN 是传递给数据库 ...

  10. [翻译] CHAnimation

    CHAnimation https://github.com/cyndibaby905/CHAnimation How it looks CHAnimation is a project used t ...