Dubbo實戰介紹2
註冊中心
dubbo支援多註冊中心,不僅支援多種形式的註冊中心,還支援向多個註冊中心註冊。目前dubbo支援的註冊中心有如下四種
Multicast註冊中心
該註冊中心不需要啟動任何中心節點,只要廣播地址一樣,就可以互相發現。組播受網路結果影響,只適合小規模的應用或開發階段使用。
ZooKeeper 註冊中心
是一個樹形的目錄服務,為分散式應用提供一致性服務,還支援變更推送功能,推薦生產環境使用
Redis註冊中心
基於redis實現的註冊中心,使用key/value結構儲存服務的url地址和過期時間,同時使用redis的publish/subscribe事件通知資料變更。
Simple註冊中心
它本身就是一個dubbo服務,可以減少第三方的依賴,是整體通訊方式一致。
由於dubbo建議使用zk作為註冊中心,所以本文主要介紹zk註冊中心。
我們在服務提供者、消費者的配置檔案使用了<dubbo:registry/>標籤後指定zk的地址後,就可以使用zk註冊中心了配置如下,兩種方式
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>
dubbo目前支援zkclient和curator兩種zk的客戶端實現,預設是zkclient,如果想要使用curator,則可以定製client="curator"
<dubbo:registry address="zookeeper://127.0.0.1:2181" client="curator"/>
還可以使用group屬性將同一個zk分成多組註冊中心,程式碼如下
<dubbo:registry id="shanghairegistry" address="zookeeper://127.0.0.1:2181" group="shanghai"/>
<dubbo:registry id="beijingregistry" address="zookeeper://127.0.0.1:2181" group="beijing"/>
前面說的都是單機配置,那麼zk的叢集配置方式呢?兩種方式如下
<dubbo:registry address="zookeeper://127.0.0.1:2181?backup=127.0.0.2:2181,127.0.0.3:2181" />
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181,127.0.0.2:2181,127.0.0.3:2181" />
除了可以向zk的叢集模式註冊中心註冊,還可以向多個註冊中心註冊
<dubbo:registry id= "shanghairegistry" address="zookeeper://127.0.0.1:2181"/>
<dubbo:registry id= "beijingregistry" address="zookeeper://127.0.0.1:2182"/>
<dubbo:service interface="com.yang.test.api.TestService" ref="testServcie" registry="shanghairegistry,beijingregistry"/>
服務暴露
在通過註冊中心註冊後,是如何提供服務給消費者使用的呢?這就需要<dubbo:service/>標籤進行服務暴露了,用法如下
<dubbo:service interface="com.yang.test.api.TestService" ref="testServcie"/>
其中,interface屬性提供服務的介面,ref屬性是該介面的具體實現類的引用。
如果服務需要預熱的時間,比如初始化快取,等待相關資源就位等,可以使用delay屬性進行服務延遲暴露,用法如下
<dubbo:service interface="com.yang.test.api.TestService" ref="testServcie" delay="5000"/> //或者設定-1,表示延遲到spring初始化完成後暴露服務
如果一個服務的併發量過大,超出了伺服器的承載能力,可以使用executes屬性控制併發。
<dubbo:service interface="com.yang.test.api.TestService" ref="testServcie" executes="10"/>//併發執行(或佔用的執行緒池的執行緒數)不能超過10個
除了限制介面,還可以具體到介面內的某一個方法,程式碼如下
<dubbo:service interface="com.yang.test.api.TestService" ref="testServcie">
<dubbo:method name="sayHello" executes="10"/>
</dubbo:service>
以上是從提供者實現的併發控制,客戶端同樣可以實現控制併發,即通過active屬性限制程式碼如下
<dubbo:service interface="com.yang.test.api.TestService" ref="testServcie" actives="10" />//限制每個客戶端的併發執行(佔線程的請求數)不超過10個
同服務提供者一樣,也可以限制到具體的方法
<dubbo:service interface="com.yang.test.api.TestService" ref="testServcie">
<dubbo:method name="sayHello" actives="10"/>
<!--不建議在客戶端控制併發,應由服務提供者來控制-->
</dubbo:service>
如果執行緒超過了給定的值,就會報異常。
為了保障服務的 穩定性,除了限制併發執行緒,還可以限制服務端的連結數量。
<dubbo:protocol name="dubbo" port="20880" accepts="10"/>
<dubbo:provider protocol="dubbo" accepts="10"/>
同樣,也可以限制客戶端的使用連線數量
<dubbo:service interface="com.yang.test.api.TestService" ref="testServcie" connections="10"/>
<dubbo:reference id="testService" interface="com.yang.test.api.TestService" connections="10"/>
如果<dubbo:service/> <dubbo:reference/> 都配置了connections,則<dubbo:reference/>優先,由於服務提供者更瞭解自身的承載能力,建議服務提供者控制連線數。
在服務報暴露過程中,除了控制併發,控制連線數,服務隔離也是一項重要的措施,dubbo提供了分組隔離,即前面的group屬性分組。
引用服務
在服務提供者暴露了服務後,消費者就可以使用如下方式引用服務了。
<dubbo:reference id="testService" interface="com.yang.test.api.TestService"/>
在預設情況下使用同步方式遠端呼叫的,如果想使用非同步方式,則可以設定async屬性為true,並使用Future獲取返回值,程式碼如下
<dubbo:reference id="testService" interface="com.yang.test.api.TestService">
<dubbo:method name="sayHello" async="true"/>
</dubbo:reference>
然後在程式碼中通過以下方式非同步呼叫
@RestController
@RequestMapping("/")
public class TestController {
@Autowired
private TestService testService;
@RequestMapping("test")
public String hello() throws Exception{
testService.sayHello("Hello springboot-dubbo!");
//拿到future引用
Future<String> future = RpcContext.getContext().getFuture();
//如果已返回,則直接拿到返回值,否則執行緒等待(wait),直到拿到返回值,執行緒才會被喚醒(notify)
String result = future.get();
return result;
}
}
在非同步呼叫中還可以設定是否需要等待發送和返回值,設定如下
sent = "true" ,等待訊息發出,訊息傳送失敗丟擲異常。
sent = "false" 不等待訊息發出,將訊息放入I/O佇列,即可返回。
return = "false" 只是想非同步,完全忽略返回值 以減少Future物件的建立和管理
<dubbo:reference id="testService" interface="com.yang.test.api.TestService">
<dubbo:method name="sayHello" async="true" sent="true"/>
</dubbo:reference>
<dubbo:reference id="testService" interface="com.yang.test.api.TestService">
<dubbo:method name="sayHello" async="true" sent="false"/>
</dubbo:reference>
<dubbo:reference id="testService" interface="com.yang.test.api.TestService">
<dubbo:method name="sayHello" async="true" return="false"/>
</dubbo:reference>
Dubbo中的非同步呼叫時基於N/O的非阻塞機制實現的,客戶端不需要開始多執行緒即可實現,相對執行緒開銷小。
Dubbo回撥
Dubbo遠端呼叫過程中如果出現了異常或著需要回調,則可以使用dubbo的事件通知機制,主要一下三總
oninvoke(原引數1,原引數2。。。) 為在發起遠端呼叫之前觸發的事件
onreturn(返回值,原引數1,原引數2。。。) 為在遠端呼叫之後的回撥事件
onthrow(Throwable ex原引數1,原引數2。。。,) 為出現異常時候觸發的事件,可以在該事件實現服務降級。
在消費者實現事件通知時候,先定義一個INotify,並實現相關業務。
public interface INotify {
void onreturn(String resStr,String inSter);
void onthrow(Throwable ex,String resStr,String inSter);
void oninvoke(String resStr,String inSter);
}
實現介面
public class notiryImpl implements INotify{
@Override
public void onreturn(String resStr, String inSter) {
System.out.println("after");
}
@Override
public void onthrow(Throwable ex, String resStr, String inSter) {
System.out.println("yichang");
}
@Override
public void oninvoke(String resStr, String inSter) {
System.out.println("before");
}
}
然後就是在配置檔案中配置
<dubbo:reference id="testService" interface="com.yang.test.api.TestService">
<dubbo:method name="sayHello" async="true" onreturn="notify.onreturn" onthrow="notify.onthrow"/>
</dubbo:reference>
Dubbo快取
dubbo為了加速熱門資料的訪問速度,提供了宣告式快取,可以在消費方配置cache屬性開始快取功能.
<dubbo:reference id="testService" interface="com.yang.test.api.TestService" cache="lru" />
快取型別:
lru 基於最近最少使用原則刪除多餘的快取,保持最熱的資料被快取
Threadlocal:當前的執行緒快取 jache :如jsr107繼承,可以橋接各種快取實現。