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. http_proxy_module 模块(proxy_pass 指令)

    1. proxy_pass 指令介绍 该指令属于 http_proxy_module, http_proxy_module 模块可以将请求转发到另一台服务器. 在 nginx 反向代理是,会通过 lo ...

  2. Java 类 ThreadLocal 本地线程变量

    前言:工作中将要使用ThreadLocal,先学习总结一波.有不对的地方欢迎评论指出. 定义 ThreadLocal并不是一个Thread,而是Thread的局部变量.这些变量不同于它们的普通对应物, ...

  3. jQuery bind()与delegate()的区别

    笔试题: bind()与delegate()的区别主要有三点: 1 绑定目标 .bind直接绑在目标元素上 .delegate绑在父元素上 2  监听个数 .bind监听个数多——每个目标元素都需要添 ...

  4. JavaWeb学习总结(三):Servlet开发(一)

    一.Servlet简介 Servlet是sun公司提供的一门用于开发动态web资源的技术. Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向 ...

  5. PHP new StdClass() 创建空对象

    PHP可以用 $object = new StdClass(); 创建一个没有成员方法和属性的空对象.很多时候,程序员们会将一些参数配置项之类的信息放在数组中使用,但是数组操作起来并不是很方便,很多时 ...

  6. D3.js 入门教程

    最近需要用到d3, 记录下d3的教程 网上搜了几个关于d3的教程 D3.js 入门教程      http://wiki.jikexueyuan.com/project/d3wiki/author.h ...

  7. 搭建hustoj

    环境:centos6.5 + LAMP环境 LAMP环境的搭建可以参考下面这篇文章 http://www.cnblogs.com/yoke/p/7257184.html 搭建完LAMP环境之后可以按照 ...

  8. 如何解决MSSQL中文数据乱码问题

    今天遇到了在数据库中直接写SQL语句,语句中包含中文,但是数据库的表里是包含“?” 的乱码. 我程序代码中,调试时得到的SQL不是乱码,在控制台中也不是乱码.但是在数据库中却出现了乱码. 当用MSSQ ...

  9. Azure 中部署WordPress的方法

    一.Azure 中创建WordPress虚拟机(1).登陆Azure:打开Azure 官网,点击右侧上方的登陆Azure门户,输入Azure帐号与密码,点击 登陆 . (2).创建Wordpress虚 ...

  10. 关于CATransform3D矩阵变换的简单解析

    关于CATransform3D矩阵变换的简单解析 效果图: 我能能够用上的CATransform3D其实很简单,并不复杂. CATransform3D有着4种东西我们可以设置. 1. 透视效果(由m3 ...