
1先问几个小问题,
1 dubbo 动态代理的目的 是什么?
代理的目的:举个例子,我被老板雇佣,本质上来去完成某一项工作。其实人就是要完成那份工作的代理。从表面上duboo客户端能执行调用某个接口的方法,其实是通过网络传输告诉服务端。我要调用哪些方法,传递给你哪些参数。你帮我执行完。然后把结果给我就行了。这就是dubbo动态代理要完成的功能。只不过框架层面抽象了这个层次,具体功能由框架来实现。dubbo动态代理有两种方案,1个是javaasisit 一个是jdk提供的。可选。为什么出现javaasisit,是基于性能的考虑。生成字节码的速度要比jdk的快。
2服务暴露解决什么问题?
服务暴露就是告诉客户端。我能提供什么服务,对应的ip是什么,端口是什么。你需要让我为你服务,你只需要按一定的协议调用就行。
搞清楚以上两个问题,就基本上了解了服务暴露的流程。
主要流程
1 通过netty暴露服务,
2 像注册中心注册,表明我提供什么服务
3订阅 Configurations 监听属性变更时间。
下面主要解析如何通过netty 发布服务,最终的目的达到
创建NettyServer对象并通过doOpen()方法创建Netty Server对象。
doOpen()方法内部创建ServerBootstrap对象并实现bind启动服务监听
HeaderExchangeServer对象的参数通过Transportersbind()生成的Server对象。
String string = uRL2getParameter("server", uRL2getParameter("transporter","netty"));
默认是netty
创建NettyServer对象并通过doOpen()方法创建Netty Server对象。
doOpen()方法内部创建ServerBootstrap对象并实现bind启动服务监听。
1、InvokerInvocationHandler jdk动态代理
5、RegistryDirector返回Invokers
Router分为:Script 脚本路由、Condition 条件路由
6、通过MockInvokersSelector的route方法(getNormalInvokers)拿到能正常执行的invokers
8、当回到AbstractClusterInvoker后,执行(默认FailoverClusterInvoker,根据配置的是,Failfast Cluster(快速失败) , Failsafe Cluster(失败安全) , Failback Cluster(失败自动恢复) , Forking Cluster(并行调用多个服务器,只要一个成功即返回) , Broadcast Cluster(广播调用所有提供者,逐个调用,任意一台报错则报错))doInvoker方法
9、FailoverClusterInvoker调用AbstractClusterInvoker的select方法
10、执行doSelect方法
11、调用AbstractLoadbalance的select方法
12、根据配置的负载均衡策略调用对应的(如RoundRobinLoadBalance)类的doSelect方法
13、返回invokersget()方法
14、调用FailoverClusterInvoker的invoke方法
均继承自抽象类AbstractDirectory
Directory 获取 invoker 是从 methodInvokerMap 中获取的,主要都是读 *** 作,那它的写 *** 作是在什么时候写的呢就是在回调方法 notify 的时候 *** 作的,也就是注册中心有变化,则更新 methodInvokerMap 和 urlInvokerMap 的值
根据dubbo-admin配置的路由规则来过滤相关的invoker,当我们对路由规则点击启用,就会触发 RegistryDirectory 类的 notify 方法。
notify方法调用refreshInvoker方法。
route方法的实现类为ConditionRoute 根据条件进行过滤
1、调用mathThen方法
2、调用matchCondition方法
3、调用isMatch判断
4、调用isMatchGlobPattern方法
集群模块是服务提供者和服务消费者的中间层,为服务消费者屏蔽了服务提供者的情况,这样服务消费者就可以专心处理远程调用相关事宜。比如发请求,接受服务提供者返回的数据等。这就是Dubbo Cluster集群的作用。
通过cluster来指定集群容错方式
其实就是应对出错情况采取的策略
用于有状态服务,尽可能让客户端总是向同一提供者发起调用,除非提供者挂了,再连另一台,自动开启延迟链接,以减少长接数
启动时服务提供者将当前进程启动时间注册到ZK;服务消费者发现该节点后计算服务启动时间(相对当前时间),在默认预热时间的前20%时间内,该节点权重始终固定为2,这样客户端的负载均衡器只会分发极少的请求至节点。
在预热时间之后的80%时间内,该节点权重将随着时间的推移而线性增长;待预热时间到期后,权重自动恢复为默认值100;负载均衡器的内核是一个标准的WLC算法模块,即加权最少连接算法;
如果某个节点Hang住或宕机,其权重会迅速自动调节降低,避免持续性影响;当节点下线时,服务端提前触发权重调节,重载默认权重至1并发布到注册中心,服务消费者将迅速感知到该事件;
服务提供者优雅下线步骤(注意这套逻辑仅在服务端执行)在okhtmdown=true对应的controller中加入下列逻辑,注意要判断down是否为true,因为正常来说false表示启动验证而不是关机
服务者消费者配置
dubbo服务支持参数动态调整,例如动态调整权重,但dubbo实现方式较为特殊,并不是常规思路。
ServiceConfig类拿到对外提供服务的实际类ref,然后通过ProxyFactory类的getInvoker方法使用ref生成一个AbstractProxyInvoker实例,到这一步就完成具体服务到Invoker的转换(javassistProxyFacory、JdkProxyFactory),接着要做Invoker转换到Export的过程
服务发布:本地暴露、远程暴露
为什么会有 本地暴露 和 远程暴露 呢不从场景考虑讨论技术的没有意义是在dubbo中我们一个服务可能既是 Provider ,又是 Consumer ,因此就存在他自己调用自己服务的情况,如果再通过网络去访问,那自然是舍近求远,因此他是有 本地暴露 服务的这个设计从这里我们就知道这个两者的区别
1、spring启动,解析配置文件
2、创建dubbo标签解析器
3、解析dubbo标签
4、ServiceBean解析
5、容器创建完成,触发ContextRefrestEvent
6、export暴露服务
7、duExportUrls
8、doExportUrlsFor1Protocol
9、getInvoker
10、protocolexport
11、开启服务器 openServer()如nettyServer
12、注册服务到注册中心 registerProvider
Filter 在服务暴露前,做拦截器初始化,在加载所有拦截器时会过滤支队provider生效的数据。
可以。zookeeper的信息会缓存到本地作为一个缓存文件,并且转换成 properties 对象方便使用。建立线程池,定时检测并连接注册中心,失败了就重连。
注册服务到zk其实就是在zk上创建临时节点,当节点下线或者down掉时,即会删除临时节点,从而使服务从可用列表中剔除。
持久节点
临时节点
1、export的时候进行zk订阅
2、设置监听回调的地址,回调给FailbackRegistry的notify
3、创建持久节点
4、设置对该节点的监听
5、更新新的服务信息,服务启动和节点更新回调,都会调用到这里
6、更新缓存文件
7、对比新旧信息是否有变化,有则重新暴露服务
高并发大业务量情况下,暂时屏蔽边缘业务
MockClusterInvoker
SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。SPI 机制在第三方框架中也有所应用,比如 Dubbo 就是通过 SPI 机制加载所有的组件。不过,Dubbo 并未使用 Java 原生的 SPI 机制,而是对其进行了增强,使其能够更好的满足需求。在 Dubbo 中,SPI 是一个非常重要的模块。基于 SPI,我们可以很容易的对 Dubbo 进行拓展。如果大家想要学习 Dubbo 的源码,SPI 机制务必弄懂。接下来,我们先来了解一下 Java SPI 与 Dubbo SPI 的用法,然后再来分析 Dubbo SPI 的源码。
最近一直在看dubbo的源码部分。在阅读的时候,需要有一个入手点,才能一点一点的进行下去。自己在研究的时候,发现思绪比较乱,于是就以 芋道源码 为基础,一点一点的啃食。芋道源码是直接从dubbo的配置和一些核心的API开始讲起,是从dubbo已经启动的过程作为开始节点,而这些核心 API 与 Spring 的之间的关系被省略了,这些东西对我来说属于前置的知识点,所以花了比较长的时间又从 Dubbo 的核心 API 倒着往前看。
在阅读 Dubbo 时,发现前置知识越来越多,如:Spring 的 refresh 中的一些核心点,Spring 中 bean 的生命周期,BeanFactory 与 FactoryBean 的区别等。所以这些前置知识花了特别多的时间去补。所幸,虽然补前置知识虽然时间长,但是性价比还是可以的。Dubbo 是依赖于Spring 的上下文环境的框架,其他依赖于 Spring 的框架也是相同的道理。Spring 的一些对外的扩展点,读过之后也会心中有数。
1、本篇主要是描述了 Dubbo 在 Spring 创建上下文的时候,是如何从创建,到能完整提供一个RPC调用能力的一些相关点。
2、由于源码比较多,直接贴断点也太过臃肿,所以仅仅贴一些关键点来概括整个流程。
3、本文是依赖于前面的 dubbo 项目进行断点分析,项目结构可以参照这里。项目中 dubbo 的配置方式是 xml 文件,所以本篇主要说 xml 配置方式。其他方式道理相同,并不是问题的关键点。
4、项目启动的是 dubbo-user 服务,所以 UserService 为 dubbo:service,OrderService 为 dubbo:reference。
下图为Spring 启动时是如何加载 Dubbo 的,其中省略了大量过程,只保留了一些关键节点,省略的部分可以略微脑补一下。
整个流程的入口是 Spring 的 refresh 方法。每个方法都有比较深的调用栈。与 Dubbo 有关的入口是 refresh 中的 invokeBeanFactoryPostProcessors 方法
这个方法是执行 beanFactory 的一些后处理 *** 作,其核心流程为在Spring容器中找出实现了BeanFactoryPostProcessor接口的processor并执行。Spring容器会委托给PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法执行。
ConfigurationClassPostProcessor 是比较核心的类,在这里我们关注一下这个类。它的作用是对项目中配置的类进行处理。具体处理可以分为几步:
在加载类信息时,spring 会去用各种方式扫到注册的 bean 信息。我们在 spring 中注册的 bean,逃不出这个方法的扫描方式。 核心方法是:
扫描之后,会将扫描到的 bean 注册到 beanDefinitionMap 中
首先是此处 orgspringframeworkbeansfactoryxmlDefaultBeanDefinitionDocumentReader#parseBeanDefinitions,可以看出方法会以配置文件根节点起,遍历所有子节点。
其次是这里 orgspringframeworkbeansfactoryxmlBeanDefinitionParserDelegate#parseCustomElement(orgw3cdomElement, orgspringframeworkbeansfactoryconfigBeanDefinition), 此方法会通过解析出来的节点,获取对应的 Spring 的 namespaceUri ,进而获取对应的配置文件处理器。
此处 ele 参数实际值为 <dubbo:service />,namespaceUri 为 >
SimpleRegistryService本身也是作为一个dubbo服务暴露。
<dubbo:protocolport="9090" />
<dubbo:service interface="comalibabadubboregistryRegistryService"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="comalibabadubboregistrysimpleSimpleRegistryService" />
上面是暴露注册中心的dubbo服务配置,
定义了注册中心服务的端口号
发布RegistryService服务, registry属性是”N/A”代表不能获取注册中心,注册中心服务的发布也是一个普通的dubbo服务的发布,如果没有配置这个属性它也会寻找注册中心,去通过注册中心发布,因为自己本身就是注册中心,直接对外发布服务,外部通过ip:port直接使用。
服务发布定义了回调接口, 这里定义了subscribe的第二个入参类暴露的回调服务供注册中心回调,用来当注册的服务状态变更时反向推送到客户端。
Dubbo协议的注册中心的暴露以及调用过程过程跟普通的dubbo服务的其实是一样的,可能跟绝大多数服务的不同的是在SimpleRegistryService在被接收订阅请求subscribe的时候,同时会refer引用调用方暴露的NotifyListener服务,当有注册数据变更时自动推送
生产者发布服务
Dubbo协议向注册中心发布服务:当服务提供方,向dubbo协议的注册中心发布服务的时候,是如何获取,创建注册中心的,如何注册以及订阅服务的,下面我们来分析其流程。
看如下配置发布服务:
<dubbo:registry protocol=”dubbo” address="127001:9090" />
<beanid="demoService" class="comalibabadubbodemoproviderDemoServiceImpl"/>
<dubbo:serviceinterface="comalibabadubbodemoDemoService" ref="demoService"/>
1 指定了哪种的注册中心,是基于dubbo协议的,指定了注册中心的地址以及端口号
2 发布DemoService服务,服务的实现为DemoServiceImpl
每个<dubbo:service/>在spring内部都会生成一个ServiceBean实例,ServiceBean的实例化过程中调用export方法来暴露服务
1 通过loadRegistries获取注册中心registryUrls
registry://127001:9090/comalibabadubboregistryRegistryServiceapplication=demo-provider&dubbo=254-SNAPSHOT&owner=william&pid=7084®istry=dubbo×tamp=1415711791506
用统一数据模型URL表示:
protocol=registry表示一个注册中心url
注册中心地址127001:9090
调用注册中心的服务RegistryService
注册中心协议是registry=dubbo
。。。。。。
2 构建发布服务的URL
dubbo://1921680102:20880/comalibabadubbodemoDemoServiceanyhost=true&application=demo-provider&dubbo=254-SNAPSHOT&generic=false&interface=comalibabadubbodemoDemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=7084&side=provider×tamp=1415712331601
发布协议protocol =dubbo
服务提供者的地址为1921680102:20880
发布的服务为comalibabadubbodemoDemoService
。。。。。。
3 遍历registryUrls向注册中心注册服务
给每个registryUrl添加属性key为export,value为上面的发布服务url得到如下registryUrl
registry://127001:9098/comalibabadubboregistryRegistryServiceapplication=demo-provider&dubbo=254-SNAPSHOT&export=dubbo%3A%2F%2F1921680102%3A20880%2FcomalibabadubbodemoDemoService%3Fanyhost%3Dtrue%26application%3Ddemo-provider%26dubbo%3D254-SNAPSHOT%26generic%3Dfalse%26interface%3DcomalibabadubbodemoDemoService%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对象暴露服务protocolexport(invoker)
通过DubboProtocol暴露服务的监听(不是此节内容)
通过RegistryProtocol将服务地址发布到注册中心,并订阅此服务
RegistryProtocolexport(Invoker)暴露服务
1 调DubboProtocol暴露服务的监听
2 获取注册中心getRegistry(Invoker)
URL转换, 由Invoker获取的url是registryURL它的协议属性用来选择何种的Protocol实例如RegistryProtocol, DubboProtocol或者RedisProtocol等等。 这里要通过URL去选择何种注册中心,所以根据registry=dubbo属性,重新设置url的协议属性得registryUrl
dubbo: //127001:9098/comalibabadubboregistryRegistryServiceapplication=demo-provider&dubbo=254-SNAPSHOT& export=dubbo%3A%2F%2F1921680102%3A20880%2FcomalibabadubbodemoDemoService%3Fanyhost%3Dtrue%26application%3Ddemo-provider%26dubbo%3D254-SNAPSHOT%26generic%3Dfalse%26interface%3DcomalibabadubbodemoDemoService%26loadbalance%3Droundrobin%26methods%3DsayHello%26owner%3Dwilliam%26pid%3D5040%26side%3Dprovider%26timestamp%3D1415715706560&owner=william&pid=5040×tamp=1415715706529
RegistryFactorygetRegistry(url) 通过工厂类创建注册中心,RegistryFactory通过dubbo的spi机制获取对应的工厂类, 这里的是基于dubbo协议的注册中心,所以是DubboRegistryFactory
3 获取发布url 就是registryUrl的export参数的值
registryProviderUrl=dubbo://1033377:20880/comalibabadubbodemoDemoServiceanyhost=true&application=demo-provider&dubbo=254-SNAPSHOT&generic=false&interface=comalibabadubbodemoDemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=6976&side=provider×tamp=1415846958825
4 DubboRegistryregister(registryProviderUrl)
通过注册器向注册中心注册服务
这里注意registryProviderUrl的并没有设置category属性, 在注册中心UrlUtilsismatch(conuumerUrl, providerUrl)比较的时候,providerUrl的category属性取默认值providers,
这点消费者订阅的时候会指定订阅的url的category=providers,去判断有没有注册的提供者。
5 构建订阅服务overrideProviderUrl,我们是发布服务
provider:/ /1033377:20880/comalibabadubbodemoDemoServiceanyhost=true&application=demo-provider&category=configurators&check=false&dubbo=254-SNAPSHOT&generic=false&interface=comalibabadubbodemoDemoService&loadbalance=roundrobin&methods=sayHello&owner=william&pid=6432&side=provider×tamp=1415847417663
6 构建OverrideListener它实现与NotifyLisener,当注册中心的订阅的url发生变化时回调重新export
7 registrysubscribe(overrideProviderUrl, OverrideListener), 注册器向注册中心订阅overrideProviderUrl,同时将Override Listener暴露为回调服务,当注册中心的overrideProviderUrl数据发生变化时回调,
注册器DubboRegistry的registry,subscribe, unRegistry, unSubscribe都类似, 是一个dubbo的远程服务调用
DubboRegistryFactory创建注册中心过程
1 根据传入registryUrl重新构建
移除EXPORT_KEY REFER_KEY
添加订阅回调参数
dubbo://127001:9098/comalibabadubboregistryRegistryServiceapplication=demo-provider&callbacks=10000&connecttimeout=10000&dubbo=254-SNAPSHOT& interface=comalibabadubboregistryRegistryService&lazy=true&methods=register,subscribe,unregister,unsubscribe,lookup&owner=william&pid=8492&reconnect=false&sticky=true&subscribe1callback=true&timeout=10000×tamp=1415783872554&unsubscribe1callback=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缓存起来, 目录服务Directorylist(Invocation)会列出所调用方法的所有Invoker , 一个Invoker代表对一个注册中心的调用实体。
8 订阅注册中心服务, 服务的提供者调注册中心的服务RegistryService属于消费方, 所以订阅服务的url的协议是consumer
consumer: //1921680102/comalibabadubboregistryRegistryServiceapplication=demo-provider&callbacks=10000&connecttimeout=10000&dubbo=254-SNAPSHOT&interface=comalibabadubboregistryRegistryService&lazy=true&methods=register,subscribe,unregister,unsubscribe,lookup&owner=william&pid=6960&reconnect=false&sticky=true &subscribe1callback=true&timeout=10000×tamp=1415800789364& unsubscribe1callback=false
订阅的目的在于在注册中心的数据发送变化的时候反向推送给订阅方
directorysubscribe(url)最终调用注册中心的RegsryService远程服务, 它是一个普通的dubbo远程调用。要说跟绝大多数dubbo远程调用的区别:url的参数subscribe1callback=true 它的意思是RegistryService的subscribe方法的第二个参数NotifyListener暴露为回调服务; url的参数 unsubscribe1callback=false 的意思是RegistryService的 unsubscribe 方法的第二个参数NotifyListener暴露的回调服务销毁。
这里dubbo协议的注册中心调注册中心的服务采用的默认集群调用策略是FailOver,选择一台注册中心,只有当失败的时候才重试其他服务器,注册中心实现也比较简单不具备集群功能, 如果想要初步的集群功能可以选用BroadcastCluster它至少向每个注册中心遍历调用注册一遍
从时序图上不难看出,服务提供端对请求的处理先通过处理器责任链一层一层处理,然后找到需要调用的服务实现类的代理Invoker进行调用,再将响应发送到调用方。
调用NettyServer#handler处理请求
Dubbo默认的底层网络通信使用的是Netty,NettyServer使用两级线程池,EventLoopGroup(boss),主要用来接收客户端连接请求,并把完成TCP三次握手的连接分发给EventLoopGroup(worker)处理,根据请求的消息是被I/O线程处理还是被业务线程池处理,Dubbo提供了几种线程模型,AllDispatcher是默认线程模型,AllChannelHandler是对应的处理器
AllDispatcher:将所有消息(请求,响应,心跳,连接事件,断开事件)都派发到业务线程池
ChannelEventRunnable处理消息的线程
对消息进行解码,解码后交由后续处理器处理
对消息进行分发处理
处理消息,并返回响应
从inv中获取 path 、version、group,从channel中获取调用的端口,组装serviceKey ,找到缓存在exporterMap的DubboExporter,进而获取服务实现类代理对象Invoker
调用代理类,处理请求,根据返回类型组装相应的Result,如果是开启了异步上下文或者返回值为CompletableFuture类型,则返回AsyncRpcResult,
否则返回同步返回结果RpcResult
至此,Dubbo提供端请求处理流程就分析完了。总结一下:
答案是肯定可以的,我将从下面几点进行说明:
1dubbo 的调用流程
2Dubbo整体设计
3从源码上说明注册中心挂了还是可以继续通信的
Dubbo 调用流程
架构图
流程说明:
1Provider(提供者)绑定指定端口并启动服务
2提供者连接注册中心,并发本机IP、端口、应用信息和提供服务信息发送至注册中心存储
3Consumer(消费者),连接注册中心 ,并发送应用信息、所求服务信息至注册中心
4注册中心根据 消费 者所求服务信息匹配对应的提供者列表发送至Consumer 应用缓存。
5Consumer 在发起远程调用时基于缓存的消费者列表择其一发起调用。
6Provider 状态变更会实时通知注册中心、在由注册中心实时推送至Consumer
这么设计的意义:
Dubbo 整体设计其协作流程如下:
从源码上说明注册中心挂了还是可以继续通信的
首先要把消费者注册到Zookeeper注册中心
然后使用RegistryDirectory 监听一下几个目录(会自动触发一次去获取这些目录上的当前数据)
当前所引入的服务的动态配置目录:/dubbo/config/dubbo/orgapachedubbodemoDemoService:111:g1configurators
比如监控providers 目录:
当有服务提供者注册,zookeeper会自动推动给订阅的消费者,然后转换为invoker存储到缓存中
我们在看调用时的代码:
我们看到 FailoverClusterInvoker 的doInvoke方法
Invoker invoker = select(loadbalance, invocation, copyInvokers, invoked);
此方法根据负载均衡器去缓存中获取一个invoker,
上面的 copyInvokers 就是上面我们缓存进去的 List
invokers = routerChainroute(getConsumerUrl(), invocation);
总结
在我们系统启动时,已经缓存了注册中心上的所有服务,后续的注册中心挂了只会影响到后续则注册,不会影响调用!
Dubbo分布式的RPC,微服务框架,
包括三个关键功能:基于接口的远程调用,容错与负载均衡,服务自动注册与发现。
Dubbo使得调用远程服务就像调用本地java服务一样简单。
参考Dubbo官方文档:包括实现细节,远程调用细节,服务提供者暴露服务。
主要流程。
1、provider向注册中心去注册
2、consumer从注册中心订阅服务,注册中心会通知consumer注册好的服务
3、consumer调用provider
4、consumer和provider都异步的通知监控中心
基于zk作为注册中心:
提供者在启动时,向注册中心zk 注册自己提供的服务。
消费者在启动时,向注册中心zk 订阅自己所需的服务。
所以是可以的,消费者在启动时,消费者会从zk拉取注册的生产者的地址接口等数据,缓存在本地。每次调用时,按照本地存储的地址进行调用,消费者本地有一个生产者的列表,他会按照列表继续工作,倒是无法从注册中心去同步最新的服务列表,短期的注册中心挂掉是不要紧的,但一定要尽快修复,挂掉是不要紧的,但前提是你没有增加新的服务,如果你要调用新的服务,则是不能办到的
Dubbo是Alibaba开源的分布式服务框架,它按照分层的方式来架构,使用这种方式可以使各层解耦。
Dubbo在调用远程的服务的时候再本地有一个接口,就想调用本地方法一样去调用,底层实现好参数传输和远程服务运行结果传回之后的返回。
Dubbo的特点:
(1)它主要使用高效的网络框架和序列化框架,让分布式服务之间调用效率更高。
(2)采用注册中心管理众多的服务接口地址,当你想调用服务的时候只需要跟注册中心询问即可,不像使用WebService一样每个服务都得记录好接口调用方式。
(3)监控中心时实现服务方和调用方之间运行状态的监控,还能控制服务的优先级、权限、权重、上下线等,让整个庞大的分布式服务系统的维护和治理比较方便。
(4)高可用,如果有服务挂了,注册中心就会从服务列表去掉该节点,客户端会像注册中心请求另一台可用的服务节点重新调用。同时注册中心也能实现高可用(ZooKeeper)。
(5)负载均衡,采用软负载均衡算法实现对多个相同服务的节点的请求负载均衡。
Dubbo需要四大基本组件:Rigistry,Monitor,Provider,Consumer。
1、监控中心的配置文件-dubboproperties文件
(1)容器,监控中心是在jetty和spring环境下运行,依赖于注册中心,日志系统是log4j
dubbocontainer = log4j,spring,registry,jetty
(2)监控服务的名称,监控系统对整个Dubbo服务系统来说也是一个服务
dubboapplicationname = simple-monitor
(3)服务的所有者,这是Dubbbo的服务的功能,可以指定服务的负责人
dubboapplicationowner = coselding
(4)注册中心的地址,配置后监控中心就能通过注册中心获取当前可用的服务列表及其状态,在页面向你汇报Dubbo中的服务运行情况。
dubboregistraddress = multicast://{ip}:{port} //广播
dubboregistraddress = zookeeper://{ip}:{port} //zookeper
dubboregistraddress = redis://{ip}:{port} //redis
dubboregistraddress = dubbo://{ip}:{port} //dubbo
(5)dubbo协议端口号
dubboprotocolport = 7070
(6)jetty工作端口号
dubbojettyport = 8082
(7)工作目录,用于存放监控中心的数据
dubbojettydirectory = ${userhome}/monitor
(8)监控中心报表存放目录
dubbochartsdirectory=${dubbojettydirectory}/charts
(9)监控中心数据资料目录
dubbostatisticsdirectory=${userhome}/monitor/statistics
(10)监控中心日志文件路径
dubbolog4jfile=logs/dubbo-monitor-simplelog
(11)监控中心日志记录级别
dubbolog4jlevel=WARN
2、Dubbo提供负载均衡方式
(1)Random,随机,按权重配置随机概率,调用量越大分布越均匀,默认方式。
(2)RounRobin,轮询,按权重设置轮询比例,如果存在比较慢的机器容易在这台机器上请求阻塞较多。
(3)LeastActive,最少活跃调用数,不支持权重,只能根据自动识别的活跃数分配,不能灵活调配。
(4)ConsistenHash,一致性hash,对相同参数的请求路由到一个服务提供者上,如果有类似灰度发布需求可采用。
3、Dubbo过滤器
Dubbo初始化过程加载ClassPath下的META-INF/dubbo/internal/,META-INF/dubbo/,META-INF/services/三个路径下的comalibabadubborpcFilter文件。文件内容:
Name = FullClassName,这些类必须实现Filter接口。
自定义Filter类:
配置文件在配置过滤器,consumerxml中:
Dubbo对过滤器的加载过程:
先加载三个路径下的comalibabadubborpcFilter文件里面的键值对,key为过滤器名称,value为过滤器的类的全限定名(这个类必须实现Dubbo中的Filter接口)。
自定义的类中@Active注解是过滤器设定的全局基本属性。
Spring在加载consumerxml文件时,通过 <dubbo:consumer filter="xxx" id = "xxx" retrries = "0">这个配置指定消费者端要加载的过滤器,通过filter属性指定过滤器名称。
@Activate注解-自动激活,group属性是表示匹配了对应的角色才被加载,value表示表明过滤条件,不写则表示所有条件都会被加载,写了则只有dubbo URL中包含该参数名且参数值不为空才被加载,这个参数会以dubbo协议的一个参数K-V对传到Provider。
4、Dubbo的Provider配置
5、Dubbo的Consumer配置
1、Dubbo是什么?
Dubbo是阿里巴巴开源的基于Java的高性能RPC分布式框架。
2、为什么使用Dubbo?
很多公司都在使用,经过很多线上的考验,内部使用了Netty,Zookeeper,保证了高性能可用性。
使用Dubbo可以将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,可以提高业务复用灵活性扩展,使前端应用能快速的响应对边的市场需求。分布式架构可以承受更大规模的并发流量。
Dubbo的服务治理图:
3、Dubbo和Spring Cloud的区别
两个没有关联,但是非要说区别,有如下几点:
(1)通信方式不同,Dubbo使用RPC通信,Spring Cloud使用>
以上就是关于dubbo服务暴露原理全部的内容,包括:dubbo服务暴露原理、Dubbo——服务调用、服务暴露、服务引用过程、Dubbo(一)——Dubbo 集成于 Spring 的原理等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)