Dubbo服务发现、引用过程Hollis关注共 2792字,需浏览 6分钟 ·2021-09-18 10:42 前言这篇我们要说的服务引用,服务引用是有两种情况的,也可以看做是两种时机,第一个是在Spring容器调用ReferenceBean的afterPropertiesSet方法时引用服务,第二个就是在ReferenceBean对应的服务被注入到其他类中时引用。这两个引用服务的时机区别在于,第一个是饿汉式的,第二个是懒汉式的是不是一说饿汉和懒汉,大家顺便回忆了一波单例模式默认情况下,Dubbo使用懒汉式引用服务。如果需要使用饿汉式,可通过配置 <dubbo:reference> 的 init 属性开启。服务引入的三种方式:第一种是引用本地 (JVM) 服务,上篇在服务暴露里面也说过了每个服务都会通过走injvm协议然后走本地的暴露,因为存在一个服务端和消费端是同一台机器上的情况,这样就直接走本地调用了,不需要走远程调用了,节省网络开销第二是通过直连方式引用远程服务,这种在线上基本不会采用这种形式的,一般都是平时我们自己测试用,直接写死服务端的地址来调用第三是通过注册中心引用远程服务,Consumer 通过注册中心得知 Provider 的相关信息,然后进行服务的引入不管是哪种引用方式,最后都会得到一个 Invoker 实例。如果有多个注册中心,多个服务提供者,这个时候会得到一组 Invoker 实例,此时需要通过集群管理类 Cluster 将多个 Invoker 合并成一个实例。合并后的 Invoker 实例已经具备调用本地或远程服务的能力了但是呢,开发者秉承不对用户业务代码侵入的原则,所以此时框架还需要通过代理工厂类ProxyFactory为服务接口生成代理类,并让代理类去调用Invoker逻辑,避免了Dubbo框架代码对业务代码的侵入服务发现dubbo的服务发现,就是通过从注册中心订阅服务提供者,并且组装成URL,然后通过URL创建出invoker来实现的服务的引入和服务的暴露一样,也是通过 spring 自定义标签机制解析生成对应的 Bean,Provider Service 对应解析的是 ServiceBean 而 Consumer Reference 对应的是 ReferenceBeandubbo 的服务发现,是通过从注册中心订阅服务提供者组装成 URL,然后通过 URL 创建出 Invoker 来实现的。这里是入口,进去看ReferenceBeancreateLazyProxy中我们会看到DubboReferenceLazyInitTargetSource这一目标资源,点进来new的地方,里面的protected的方法createObject调用了getCallProxy,而这个方法最终调用的是referenceConfig.get()点进来,我们进入的是ReferenceConfig类的方法,而非ReferenceBean的,这是因为ReferenceConfig是作为ReferenceBean的内部的属性出现的Init()方法内部主要就是通过Map设置各种参数,我们看init其中的一个方法叫做createProxy,我们根据名字也可以知道大概意思就是创建代理对象,点进去看看如果是走本地的话,那么直接构建个本地协议的 URL 然后进行服务的引入,即 refprotocol.refer,这个方法之后会做分析,本地的引入就不深入了,就是去之前服务暴露的 exporterMap 拿到服务如果不是本地,那肯定是远程了,接下来就是判断是点对点直连 provider 还是通过注册中心拿到 provider 信息再连接 provider 了,我们分析一下配置了 url 的情况,如果配置了 url 那么不是直连的地址,就是注册中心的地址这其实就是整个流程了,简述一下就是先检查配置,通过配置构建一个 map ,然后利用 map 来构建 URL ,再通过 URL 上的协议利用自适应扩展机制调用对应的 protocol.refer 得到相应的 invoker 我给大家总结个流程图,这样大家看着更加清晰服务引用Dubbo 的服务引用,实际上是为引用的接口创建一个 Proxy,这个 Proxy 的功能就是去执行 refprotocol.refer(interfaceClass, url) 创建出来的 Invoker。当服务提供者有多个时,就创建一个 ClusterInvoker。Cluster 是一个 SPI 扩展点,默认使用com.alibaba.dubbo.rpc.cluster.support.FailoverCluster所以,Consumer 端服务调用的逻辑被封装在 refprotocol.refer(interfaceClass, url) 创建出来的 Invoker 上主要就是获取注册中心实例,然后调用 doRefer 进行真正的 refer。这里会向注册中心注册自身的信息,生成一个Invoker,底层生成用于远程调用的invoker,然后通过cluster包装一下再得到ClusterInvoker,因此一个服务可能有多个提供者,然后最后注册相应的监听器拿到了Provider的信息之后就可以通过监听触发 Protocol# refer 了,具体调用哪个 protocol 还是得看 URL的协议的,我们看下这个内部DubboProtocol的refer而这个connect最终返回 HeaderExchangeClient里面封装的是 NettyClient,然后最终得到的invoker就是对这个client的封装,最终将返回一个Proxy的代理对象回顾其实整个流程看代码啥的,一开始可能会遇到很多新名词,但是细细一想其实不难,静下心来好好分析,就都很简单了其实就是通过各种配置参数和协议组装成相应的URL,然后通过自动适配去对相应的实现类进行相应的服务的引入和后续的调用如果是写死的地址就直接连接,是注册中心就向注册中心注册信息,然后订阅注册中心的相关信息,得到服务提供者的IP端口号等信息,通过netty进行连接,底层会通过directory和cluster进行底层多个服务的屏蔽和负载均衡的处理,得到代理对象Invoker,再通过动态代理封装得到代理类,总之就是不侵入业务代码,能用代理解决的就用代理不侵入代码的最好办法就是加代理,遇事不决加层代理有道无术,术可成;有术无道,止于术欢迎大家关注Java之道公众号好文章,我在看❤️ 浏览 88点赞 评论 收藏 分享 手机扫一扫分享分享 举报 评论图片表情视频评价全部评论推荐 Dubbo服务发现、引用过程大鱼仙人0dubbo 2.7应用级服务发现踩坑小记捉虫大师0微服务通信之feign的注册、发现过程java12340Dubbo 服务拥堵,怎么办??Java技术栈0Dubbo之服务暴露源码共读0diaophpphp dubbo 微服务框架diaophpphp dubbo 微服务框架0SkyDNS服务发现系统SkyDNS是一个相对新的项目它采用Go语言编写,使用了RAFT用于一致性,并提供了HTTP和DNS两种客户端API.它与Etcd和Spotify的DNS模型有点类似,事实上它采用了和Etcd,go-Discoverd服务发现系统Discoverd是一个简单又强大的服务发现系统,目前基于Etcd,但是也可以使用ZooKeeper或者其它的分布式一致性存储系统。类似Consul和Etcd这样的项目只是提供基础的服务发现功能,但是Discoverd服务发现系统Discoverd是一个简单又强大的服务发现系统,目前基于Etcd,但是也可以使用ZooKeeperdiaophpphp dubbo 微服务框架diaophp 是使用原生PHP语法、极简内核、内置异步任务、定时器、全自动配置的php/java双向RPC调用的phpdubbo微服务框架。diaophp不定义命名空间,不依赖composer包管理点赞 评论 收藏 分享 手机扫一扫分享分享 举报