理解 Dubbo 服务引用
為什么80%的碼農都做不了架構師?>>> ??
?
dubbo 服務引用過程
????? ? dubbo 的使用過程中消費者端會依賴服務端提供的 api 包(接口 jar 包) , 這些 api 包中只含有服務的 Interface 的 class 文件 , 在進行服務調用的時候使用 Interface 的一個引用,就可以進行遠程的調用了,因為 dubbo 在客戶端動態(tài)的生成了一個該 Interface 類型的代理類。在這個代理類中封裝了遠程服務調用的組件。獲取這個 Interface 類型的代理對象的實例通過 spring IOC 容器 ,自動注入的方式或者通過 getBean 的方式。服務引用的入口代碼:
com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler com.alibaba.dubbo.config.spring.schema.DubboBeanDefinitionParser com.alibaba.dubbo.config.spring.ReferenceBeanReferenceBean 實現(xiàn)了 spring 的 FactoryBean 接口 , 該接口有一個 T getObject() 函數(shù) ,dubbo 服務引用的開端就是在實現(xiàn)的這個 getObject() 函數(shù)中。當對任意服務 Interface 進行自動注入或者 getBean 獲取時,就會觸發(fā)服務的引用過程。? ??
? ? ? ? ? ? ? ?
????? ? 服務引用分為和服務提供者在同一個 JVM 實例中和在不同的 JVM?引用,和服務提供者在同一 JVM 實例中引用不會打開網絡連接,同一 JVM 實例內調用不需要經過網絡傳輸過程。在和服務提供者不同的 JVM 實例內引用時就必須打開網絡連接,否則無法調用遠程服務。
????? ? 和服務提供者在不同 JVM 實例中引用,首先消費者要去注冊中心進行注冊, 接下來訂閱所引用的服務。當服務提供者接收到消費者的訂閱消息后會去注冊中心查找已經注冊的所有服務 , 然后匹配哪一個服務是當前消費者正在訂閱的服務 , 如果匹配成功了就會通過注冊中心通知消費者找到了消費者訂閱的服務,消費者接收到注冊中心發(fā)送的匹配服務成功消息后 , 會調用消費者注冊的訂閱通知監(jiān)聽 (NotifyListener),?NotifyListener 中的 notify 會被調用 。 dubbo 提供了一個?RegistryDirectory 實現(xiàn)了?NotifyListener 接口 , 在?notify 函數(shù)中去刷新 Invoker (refreshInvoker) 。這時候會去創(chuàng)建一個新的 Invoker , 創(chuàng)建的這個 Invoker 還是和之前博客中討論過的創(chuàng)建 Invoker 的過程一樣, Invoker 會被 Filter 、 Listener 包裝。在創(chuàng)建這個 Invoker 的過程中也會打開網絡連接。
???????????????????
? ? ? ? 這里使用的注冊中心是 multicast 。?zookeeper , redis 注冊中心的具體實現(xiàn)方式不同。如果在消費者服務引用的過程中,服務提供者沒有正常啟動的話,是不會去進行打開網絡連接操作的,如果在消費者連接提供者的過程中提供者掛掉了拋出異常 RemotingException? 。
?
打開網絡連接
????? ? 消費者在引用服務的過程中如果和提供者不在同一 JVM 實例內,需要去打開網絡連接,來和服務提供者進行網絡通信。打開網絡連接的過程和服務端在網絡中暴露服務的順序一致 Transporter , Exchanger ,?ExchangeClient 可選的實現(xiàn)有 NettyClient (默認) , MinaClient , GrizzlyClient 。消費者建立客戶端打開網絡連接之后要和所訂閱的服務端建立連接。Interface 引用 , Invoker? ,?ExchangeClient? , Provider 之間的關系大致是這樣:
????????????
????? ? 每一個服務引用都可能對應多個 Invoker , 每一個 Invoker 指向了一個 Provider ,消費者內部會開啟多個客戶端與提供者開啟的一個服務端進行通信。當使用服務引用調用服務時,就可以在多個 Invoker 之間進行負載均衡。如果每個 Invoker 只有一個 Client,這樣稱為共享連接。每一個服務引用也可以使用多個網絡連接,在 <dubbo:reference connections="3" /> 進行配置 , 默認使用共享網絡連接。
?
創(chuàng)建服務存根接口的代理對象
????? ? 通過 ProxyFactory 擴展點 getProxy 來獲取一個代理對象的實例 ,dubbo 默認使用的是 JavassistProxyFactory 擴展 , 動態(tài)的生成一個代理類和這個代理類的實例對象 。我的 Interface 代碼 :
package net.j4love.dubbo.quickstart.provider;public interface DemoService {String echoWithCurrentTime(String src); }????????生成的接口代理類代碼 :
package com.alibaba.dubbo.common.bytecode;public class com.alibaba.dubbo.common.bytecode.proxy0 implements interface net.j4love.dubbo.quickstart.provider.DemoService ,interface com.alibaba.dubbo.rpc.service.EchoService {// 存儲的是所有實現(xiàn)的接口中的 methodpublic static java.lang.reflect.Method[] methods;private java.lang.reflect.InvocationHandler handler;public proxy0(java.lang.reflect.InvocationHandler $1) {handler=$1;}public java.lang.String echoWithCurrentTime(java.lang.String $1) {Object[] args = new Object[1];args[0] = ($w)$1;Object ret = handler.invoke(this, methods[0], args);return (java.lang.String)ret;}public java.lang.Object $echo(java.lang.Object $1) {Object[] args = new Object[1];args[0] = ($w)$1;Object ret = handler.invoke(this, methods[1], args);return (java.lang.Object)ret;} }?????? ? 生成的 com.alibaba.dubbo.common.bytecode.Proxy 的實現(xiàn)類代碼 :
public class com.alibaba.dubbo.common.bytecode.Proxy0 extends com.alibaba.dubbo.common.bytecode.Proxy {public Proxy0() {}public Object newInstance(java.lang.reflect.InvocationHandler h) {return new com.alibaba.dubbo.common.bytecode.proxy0($1);} }????? ? 數(shù)字 0 是自增生成的 , 從 0 開始自增。
?
回聲測試
????? ? 所有的動態(tài)生成的引用接口代理類都實現(xiàn)了 com.alibaba.dubbo.rpc.service.EchoService 這個接口,獲取到的引用可以強制轉換成?EchoService? 調用 $echo 函數(shù)來測試服務是否可用。
?
泛化調用
????? ? 泛化調用是用?interface com.alibaba.dubbo.rpc.service.GenericService 接口來替代自定義的服務接口,通過? $invoke 函數(shù)來調用遠程服務 , 這種方式適用于消費者端本地沒有服務提供者端的接口 jar 包時,但是卻知道接口的全名稱 , 接口全名稱是必須知道的因為要靠這個名稱去注冊中心尋找是否有注冊的服務提供者。泛化調用只需要進行配置就可使用 ?, generic 設置為 true:
<dubbo:reference id="demoService"version="1.0.0"generic="true"interface="net.j4love.dubbo.quickstart.provider.DemoService" />?
?
?
?
轉載于:https://my.oschina.net/j4love/blog/1817698
總結
以上是生活随笔為你收集整理的理解 Dubbo 服务引用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 进程管理常用命令
- 下一篇: 数据绑定(三)为Binding指定绑定源