如何获取dubbo上注册的referencebean

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何获取dubbo上注册的referencebean相关的知识,希望对你有一定的参考价值。

SimpleRegistryService本身也是作为一个dubbo服务暴露。
<dubbo:protocolport="9090" />
<dubbo:service interface="com.alibaba.dubbo.registry.RegistryService"ref="registryService" registry="N/A" ondisconnect="disconnect"callbacks="1000">
<dubbo:methodname="subscribe"><dubbo:argument index="1" callback="true"/></dubbo:method>
<dubbo:methodname="unsubscribe"><dubbo:argument index="1" callback="false"/></dubbo:method>
</dubbo:service>
<bean id="registryService"class="com.alibaba.dubbo.registry.simple.SimpleRegistryService" />
上面是暴露注册中心的dubbo服务配置,
定义了注册中心服务的端口号
发布RegistryService服务, registry属性是”N/A”代表不能获取注册中心,注册中心服务的发布也是一个普通的dubbo服务的发布,如果没有配置这个属性它也会寻找注册中心,去通过注册中心发布,因为自己本身就是注册中心,直接对外发布服务,外部通过ip:port直接使用。
服务发布定义了回调接口, 这里定义了subscribe的第二个入参类暴露的回调服务供注册中心回调,用来当注册的服务状态变更时反向推送到客户端。
Dubbo协议的注册中心的暴露以及调用过程过程跟普通的dubbo服务的其实是一样的,可能跟绝大多数服务的不同的是在SimpleRegistryService在被接收订阅请求subscribe的时候,同时会refer引用调用方暴露的NotifyListener服务,当有注册数据变更时自动推送
生产者发布服务
Dubbo协议向注册中心发布服务:当服务提供方,向dubbo协议的注册中心发布服务的时候,是如何获取,创建注册中心的,如何注册以及订阅服务的,下面我们来分析其流程。
看如下配置发布服务:
<dubbo:registry protocol=”dubbo” address="127.0.0.1:9090" />
<beanid="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>
<dubbo:serviceinterface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>
1. 指定了哪种的注册中心,是基于dubbo协议的,指定了注册中心的地址以及端口号
2. 发布DemoService服务,服务的实现为DemoServiceImpl
每个<dubbo:service/>在spring内部都会生成一个ServiceBean实例,ServiceBean的实例化过程中调用export方法来暴露服务
1. 通过loadRegistries获取注册中心registryUrls
registry://127.0.0.1:9090/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&dubbo=2.5.4-SNAPSHOT&owner=william&pid=7084®istry=dubbo×tamp=1415711791506
用统一数据模型URL表示:
protocol=registry表示一个注册中心url
注册中心地址127.0.0.1:9090
调用注册中心的服务RegistryService
注册中心协议是registry=dubbo
。。。。。。
2. 构建发布服务的URL
dubbo://192.168.0.102:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.5.4-SNAPSHOT&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=7084&side=provider×tamp=1415712331601
发布协议protocol =dubbo
服务提供者的地址为192.168.0.102:20880
发布的服务为com.alibaba.dubbo.demo.DemoService
。。。。。。
3. 遍历registryUrls向注册中心注册服务
给每个registryUrl添加属性key为export,value为上面的发布服务url得到如下registryUrl
registry://127.0.0.1:9098/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&dubbo=2.5.4-SNAPSHOT&export=dubbo%3A%2F%2F192.168.0.102%3A20880%2Fcom.alibaba.dubbo.demo.DemoService%3Fanyhost%3Dtrue%26application%3Ddemo-provider%26dubbo%3D2.5.4-SNAPSHOT%26generic%3Dfalse%26interface%3Dcom.alibaba.dubbo.demo.DemoService%26loadbalance%3Droundrobin%26methods%3DsayHello%26owner%3Dwilliam%26pid%3D7084%26side%3Dprovider%26timestamp%3D1415712331601&owner=william&pid=7084®istry=dubbo×tamp=1415711791506
4. 由发布的服务实例,服务接口以及registryUrl为参数,通过代理工厂proxyFactory获取Invoker对象,Invoker对象是dubbo的核心模型,其他对象都向它靠拢或者转换成它。
5. 通过Protocol对象暴露服务protocol.export(invoker)
通过DubboProtocol暴露服务的监听(不是此节内容)
通过RegistryProtocol将服务地址发布到注册中心,并订阅此服务
RegistryProtocol.export(Invoker)暴露服务
1. 调DubboProtocol暴露服务的监听
2. 获取注册中心getRegistry(Invoker)
URL转换, 由Invoker获取的url是registryURL它的协议属性用来选择何种的Protocol实例如RegistryProtocol, DubboProtocol或者RedisProtocol等等。 这里要通过URL去选择何种注册中心,所以根据registry=dubbo属性,重新设置url的协议属性得registryUrl
dubbo: //127.0.0.1:9098/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&dubbo=2.5.4-SNAPSHOT& export=dubbo%3A%2F%2F192.168.0.102%3A20880%2Fcom.alibaba.dubbo.demo.DemoService%3Fanyhost%3Dtrue%26application%3Ddemo-provider%26dubbo%3D2.5.4-SNAPSHOT%26generic%3Dfalse%26interface%3Dcom.alibaba.dubbo.demo.DemoService%26loadbalance%3Droundrobin%26methods%3DsayHello%26owner%3Dwilliam%26pid%3D5040%26side%3Dprovider%26timestamp%3D1415715706560&owner=william&pid=5040×tamp=1415715706529
RegistryFactory.getRegistry(url) 通过工厂类创建注册中心,RegistryFactory通过dubbo的spi机制获取对应的工厂类, 这里的是基于dubbo协议的注册中心,所以是DubboRegistryFactory
3. 获取发布url 就是registryUrl的export参数的值
registryProviderUrl=dubbo://10.33.37.7:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.5.4-SNAPSHOT&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=6976&side=provider×tamp=1415846958825
4. DubboRegistry.register(registryProviderUrl)
通过注册器向注册中心注册服务
这里注意registryProviderUrl的并没有设置category属性, 在注册中心UrlUtils.ismatch(conuumerUrl, providerUrl)比较的时候,providerUrl的category属性取默认值providers,
这点消费者订阅的时候会指定订阅的url的category=providers,去判断有没有注册的提供者。
5. 构建订阅服务overrideProviderUrl,我们是发布服务
provider:/ /10.33.37.7:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&category=configurators&check=false&dubbo=2.5.4-SNAPSHOT&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=6432&side=provider×tamp=1415847417663
6. 构建OverrideListener它实现与NotifyLisener,当注册中心的订阅的url发生变化时回调重新export
7. registry.subscribe(overrideProviderUrl, OverrideListener), 注册器向注册中心订阅overrideProviderUrl,同时将Override Listener暴露为回调服务,当注册中心的overrideProviderUrl数据发生变化时回调,
注册器DubboRegistry的registry,subscribe, unRegistry, unSubscribe都类似, 是一个dubbo的远程服务调用
DubboRegistryFactory创建注册中心过程
1. 根据传入registryUrl重新构建
移除EXPORT_KEY REFER_KEY
添加订阅回调参数
dubbo://127.0.0.1:9098/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&callbacks=10000&connect.timeout=10000&dubbo=2.5.4-SNAPSHOT& interface=com.alibaba.dubbo.registry.RegistryService&lazy=true&methods=register,subscribe,unregister,unsubscribe,lookup&owner=william&pid=8492&reconnect=false&sticky=true&subscribe.1.callback=true&timeout=10000×tamp=1415783872554&unsubscribe.1.callback=false
2. 根据url 注册服务接口构建注册目录对象RegistryDircectory,实现了NotiyfLisener,这里NotiyfLisener实现主要是根据urls去refer引用远程服务RegistryService得到对应的Invoker,当urls变化时重新refer;目录服务可以列出所有可以执行的Invoker
3. 利用cluster的join方法,将Dirctory的多个Invoker对象伪装成一个Invoker对象, 这里默认集群策略得到FailoverClusterInvoker
4. FailoverClusterInvoker利用ProxyFactory获取到RegistryService服务的代理对象
5. 由RegistryService服务的代理对象和FailoverClusterInvoker构建dubbo协议的注册中心注册器DubboRegistry
6. RegistryDircectory设置注册器DubboRegistry,设置dubbo的协议
7. 调用 RegistryDircectory的notify(urls)方法
主要是根据registryUrls, 引用各个注册中心的RegistryService服务实现,将引用的服务按key=menthodName/value=invoker缓存起来, 目录服务Directory.list(Invocation)会列出所调用方法的所有Invoker , 一个Invoker代表对一个注册中心的调用实体。
8. 订阅注册中心服务, 服务的提供者调注册中心的服务RegistryService属于消费方, 所以订阅服务的url的协议是consumer
consumer: //192.168.0.102/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&callbacks=10000&connect.timeout=10000&dubbo=2.5.4-SNAPSHOT&interface=com.alibaba.dubbo.registry.RegistryService&lazy=true&methods=register,subscribe,unregister,unsubscribe,lookup&owner=william&pid=6960&reconnect=false&sticky=true &subscribe.1.callback=true&timeout=10000×tamp=1415800789364& unsubscribe.1.callback=false
订阅的目的在于在注册中心的数据发送变化的时候反向推送给订阅方
directory.subscribe(url)最终调用注册中心的RegsryService远程服务, 它是一个普通的dubbo远程调用。要说跟绝大多数dubbo远程调用的区别:url的参数subscribe.1.callback=true 它的意思是RegistryService的subscribe方法的第二个参数NotifyListener暴露为回调服务; url的参数 unsubscribe.1.callback=false 的意思是RegistryService的 unsubscribe 方法的第二个参数NotifyListener暴露的回调服务销毁。
这里dubbo协议的注册中心调注册中心的服务采用的默认集群调用策略是FailOver,选择一台注册中心,只有当失败的时候才重试其他服务器,注册中心实现也比较简单不具备集群功能, 如果想要初步的集群功能可以选用BroadcastCluster它至少向每个注册中心遍历调用注册一遍
参考技术A 开源的dubbo已支持4种组件作为注册中心,我们部门使用推荐的zookeeper做为注册中心,由于就瓶颈来说不会出现在注册中心,风险较低,未做特别的研究或比较。
zookeeper,推荐集群中部署奇数个节点,由于zookeeper挂掉一半的机器集群就不可用,所以部署4台和3台的集群都是在挂掉2台后集群不可用
redis
multicast,广播受到网络结构的影响,一般本地不想搭注册中心的话使用这种调用
dubbo简易注册中心
对于zookeeper客户端,dubbo在2.2.0之后默认使用zkclient,2.3.0之后提供可选配置Curator,提到这个点的原因主要是因为zkclient发现一些问题:①服务器在修改服务器时间后zkClient会抛出日志错误之类的异常然后容器(我们使用resin)挂掉了,也不能确定就是zkClient的问题,接入dubbo之前无该问题②dubbo使用zkclient不传入连接zookeeper等待超时时间,使用默认的Integer.MAX_VALUE,这样在zookeeper连不上的情况下不报错也无法启动;目前我们准备寻找其他解决方案,比如使用curator试下,还没正式投入。

Dubbo -- 系统学习 笔记 -- 示例 -- 直连提供者

Dubbo -- 系统学习 笔记 -- 目录

示例

  想完整的运行起来,请参见:快速启动,这里只列出各种场景的配置方式

直连提供者

在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,
点对点直联方式,将以服务接口为单位,忽略注册中心的提供者列表,
A接口配置点对点,不影响B接口从注册中心获取列表。

(1) 如果是线上需求需要点对点,可在<dubbo:reference>中配置url指向提供者,将绕过注册中心,多个地址用分号隔开,配置如下:(1.0.6及以上版本支持)

<dubbo:reference id="xxxService" interface="com.alibaba.xxx.XxxService" url="dubbo://localhost:20890" />

(2) 在JVM启动参数中加入-D参数映射服务地址,如:
(key为服务名,value为服务提供者url,此配置优先级最高,1.0.15及以上版本支持)

java -Dcom.alibaba.xxx.XxxService=dubbo://localhost:20890

  注意
    为了避免复杂化线上环境,不要在线上使用这个功能,只应在测试阶段使用。

(3) 如果服务比较多,也可以用文件映射,如:
(用-Ddubbo.resolve.file指定映射文件路径,此配置优先级高于<dubbo:reference>中的配置,1.0.15及以上版本支持)
(2.0以上版本自动加载${user.home}/dubbo-resolve.properties文件,不需要配置)

java -Ddubbo.resolve.file=xxx.properties

然后在映射文件xxx.properties中加入:
(key为服务名,value为服务提供者url)

com.alibaba.xxx.XxxService=dubbo://localhost:20890

注意
为了避免复杂化线上环境,不要在线上使用这个功能,只应在测试阶段使用。

 

啦啦啦

以上是关于如何获取dubbo上注册的referencebean的主要内容,如果未能解决你的问题,请参考以下文章

dubbo如何获取某服务的所有节点的服务

Dubbo实践(十四)生产者发布服务

Dubbo + ZooKeeper丨如何解决线上故障排查链路长的难题

dubbo为啥用到了zookeeper

Dubbo在安全机制方面是如何解决的

Dubbo——Registry服务注册