轉載前言:網絡上很多教程沒有描述zookeeper和dubbo到底是什么關系、分別扮演了什么角色等信息,都是說一些似是而非的話,這里終於找到一篇文章,比較生動地描述了注冊中心和微服務框架之間的關系,以及他們之間的合作分工。
下面附上我讀完之后的理解:
dubbo是一個遠程調用服務的分布式框架,可以實現遠程通訊、動態配置、地址路由等等功能。
比如在入門demo里的暴露服務,使得遠程調用的協議可以使用dobbo協議(dubbo://x.x.x.x)或者其它協議,可以配置zookeeper集群地址,實現軟負載均衡並配置均衡方式等。
在不搭配注冊中心的時候,它也是可以實現服務端和調用端的通信的,這種方式是點對點通信的,所謂“沒有中間商”。但是如果配置服務發布和調用端過多特別是集群的方式提供服務的時候,就會暴露許多的問題:增加節點需要修改配置文件、服務端機器宕機后不能被感知等。它可以通過集成注冊中心,來動態地治理服務發布和服務調用。相當於把服務注冊和發布推送的功能分攤給了(zookeeper)注冊中心。
原帖地址:https://www.javazhiyin.com/28425.html#m
介紹
微服務是最近比較火的概念,而微服務框架目前主流的有Dubbo和Spring Cloud,兩者都是為了解決微服務遇到的各種問題而產生的,即遇到的問題是一樣的,但是解決的策略卻有所不同,所以這2個框架經常拿來比較。沒用過Dubbo的小伙伴也不用擔心,其實Dubbo還是比較簡單的,看完本文你也能掌握一個大概,重要的不是代碼,而是思想。
Dubbo實現服務調用是通過RPC的方式,即客戶端和服務端共用一個接口(將接口打成一個jar包,在客戶端和服務端引入這個jar包),客戶端面向接口寫調用,服務端面向接口寫實現,中間的網絡通信交給框架去實現,想深入了解的看推薦閱讀。原文鏈接有代碼GitHub地址
使用入門
服務提供者
定義服務接口
public interface DemoService {
String sayHello(String name);
}
在服務提供方實現接口
public class DemoServiceImpl implements DemoService {
@Override
public String sayHello(String name) {
return "Hello " + name;
}
}
用 Spring 配置聲明暴露服務
provider.xml(省略了beans標簽的各種屬性)
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<!-- 當前項目在整個分布式架構里面的唯一名稱,用於計算依賴關系 -->
<dubbo:application name="helloworld-app" />
<!--dubbo這個服務所要暴露的服務地址所對應的注冊中心,N/A為不使用注冊中心-->
<dubbo:registry address="N/A"/>
<!--當前服務發布所依賴的協議;webserovice、Thrift、Hessain、http-->
<dubbo:protocol name="dubbo" port="20880"/>
<!--服務發布的配置,需要暴露的服務接口-->
<dubbo:service interface="com.st.DemoService"
ref="demoService"/>
<!--bean的定義-->
<bean id="demoService" class="com.st.DemoServiceImpl"/>
</beans>
加載 Spring 配置
public class Provider {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("provider.xml");
context.start();
System.in.read(); // 按任意鍵退出
}
}
服務消費者
consumer.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<!-- 消費方應用名,用於計算依賴關系,不是匹配條件,不要與提供方一樣 -->
<dubbo:application name="consumer-of-helloworld-app"/>
<dubbo:registry address="N/A"/>
<!-- 生成遠程服務代理,可以和本地bean一樣使用demoService -->
<dubbo:reference id="demoService" interface="com.st.DemoService"
url="dubbo://localhost:20880/com.st.DemoService"/>
</beans>
加載Spring配置,並調用遠程服務
public class Consumer {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("consumer.xml");
context.start();
// 獲取遠程服務代理
DemoService demoService = (DemoService)context.getBean("demoService");
// 執行遠程方法
String hello = demoService.sayHello("world");
// Hello world
System.out.println( hello );
}
}
這就是典型的點對點的服務調用。當然我們為了高可用,可以在consumer.xml中配置多個服務提供者,並配置響應的負載均衡策略
配置多個服務調用者在comsumer.xml的dubbo:reference標簽的url屬性中加入多個地址,中間用分號隔開即可配置負載均衡策略在comsumer.xml的dubbo:reference標簽中增加loadbalance屬性即可,值可以為如下四種類型
- RoundRobin LoadBalance,隨機,按權重設置隨機概率。
- RoundRobin LoadBalance,輪詢,按公約后的權重設置輪詢比率。
- LeastActive LoadBalance,最少活躍調用數,相同活躍數的隨機,活躍數指調用前后計數差。
- ConsistentHash LoadBalance,一致性 Hash,相同參數的請求總是發到同一提供者。
<dubbo:reference id="demoService" interface="com.st.DemoService"
url="dubbo://192.168.11.1:20880/com.st.DemoService;
dubbo://192.168.11.2:20880/com.st.DemoService;
dubbo://192.168.11.3:20880/com.st.DemoService"
loadbalance="roundrobin"/>
現在整體架構是如下圖(假設服務消費者為訂單服務,服務提供者為用戶服務):
這樣會有什么問題呢?
- 當服務提供者增加節點時,需要修改配置文件
- 當其中一個服務提供者宕機時,服務消費者不能及時感知到,還會往宕機的服務發送請求
這個時候就得引入注冊中心了
注冊中心
Dubbo目前支持4種注冊中心,(multicast zookeeper redis simple) 推薦使用Zookeeper注冊中心,本文就講一下用zookeeper實現服務注冊和發現(敲黑板,又一種zookeeper的用處),大致流程如下
現在我們來看Dubbo官網對Dubbo的介紹圖,有沒有和我們上面畫的很相似
節點角色說明
節點 | 角色說明 |
---|---|
Provider | 暴露服務的服務提供方 |
Consumer | 調用遠程服務的服務消費方 |
Registry | 服務注冊與發現的注冊中心 |
Monitor | 統計服務的調用次數和調用時間的監控中心 |
Container | 服務運行容器 |
調用關系說明
- 服務容器負責啟動(上面例子為Spring容器),加載,運行服務提供者。
- 服務提供者在啟動時,向注冊中心注冊自己提供的服務。
- 服務消費者在啟動時,向注冊中心訂閱自己所需的服務。
- 注冊中心返回服務提供者地址列表給消費者,如果有變更,注冊中心將基於長連接推送變更數據給消費者。
- 服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一台提供者進行調用,如果調用失敗,再選另一台調用。
- 服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鍾發送一次統計數據到監控中心。
要使用注冊中心,只需要將provider.xml和consumer.xml更改為如下
<!--<dubbo:registry address="N/A"/>-->
<dubbo:registry protocol="zookeeper" address="192.168.11.129:2181"/>
如果zookeeper是一個集群,則多個地址之間用逗號分隔即可
<dubbo:registry protocol="zookeeper" address="192.168.11.129:2181,192.168.11.137:2181,192.168.11.138:2181"/>
把consumer.xml中配置的直連的方式去掉
<!-- 生成遠程服務代理,可以和本地bean一樣使用demoService -->
<!--<dubbo:reference id="demoService" interface="com.st.DemoService"-->
<!--url="dubbo://localhost:20880/com.st.DemoService"/>-->
<dubbo:reference id="demoService" interface="com.st.DemoService"/>
注冊信息在zookeeper中如何保存?
啟動上面服務后,我們觀察zookeeper的根節點多了一個dubbo節點及其他,圖示如下
最后一個節點中192.168.1.104是小編的內網地址,你可以任務和上面配置的localhost一個效果,大家可以想一下我為什么把最后一個節點標成綠色的。沒錯,最后一個節點是臨時節點,而其他節點是持久節點,這樣,當服務宕機時,這個節點就會自動消失,不再提供服務,服務消費者也不會再請求。如果部署多個DemoService,則providers下面會有好幾個節點,一個節點保存一個DemoService的服務地址
其實一個zookeeper集群能被多個應用公用,如小編Storm集群和Dubbo配置的就是一個zookeeper集群,為什么呢?因為不同的框架會在zookeeper上建不同的節點,互不影響。如dubbo會創建一個/dubbo節點,storm會創建一個/storm節點,如圖
zookeeper相關介紹
Zookeeper 是 Apacahe Hadoop 的子項目,是一個樹型的目錄服務,支持變更推送,適合作為 Dubbo 服務的注冊中心,工業強度較高,可用於生產環境,並推薦使用。
流程說明:
- 服務提供者啟動時: 向
/dubbo/com.foo.BarService/providers
目錄下寫入自己的 URL 地址 - 服務消費者啟動時: 訂閱
/dubbo/com.foo.BarService/providers
目錄下的提供者 URL 地址。並向/dubbo/com.foo.BarService/consumers
目錄下寫入自己的 URL 地址 - 監控中心啟動時: 訂閱
/dubbo/com.foo.BarService
目錄下的所有提供者和消費者 URL 地址。
支持以下功能:
- 當提供者出現斷電等異常停機時,注冊中心能自動刪除提供者信息
- 當注冊中心重啟時,能自動恢復注冊數據,以及訂閱請求
- 當會話過期時,能自動恢復注冊數據,以及訂閱請求
- 當設置
<dubbo:registry check="false" />
時,記錄失敗注冊和訂閱請求,后台定時重試 - 可通過
<dubbo:registry username="admin" password="1234" />
設置 zookeeper 登錄信息 - 可通過
<dubbo:registry group="dubbo" />
設置 zookeeper 的根節點,不設置將使用無根樹 - 支持
*
號通配符<dubbo:reference group="*" version="*" />
,可訂閱服務的所有分組和所有版本的提供者
Dubbo相關介紹
-
Dubbo是什么?
Dubbo是一個分布式服務框架,致力於提供高性能和透明化的RPC遠程服務調用方案,以及SOA服務治理方案。簡單的說,dubbo就是個服務框架,如果沒有分布式的需求,其實是不需要用的,只有在分布式的時候,才有dubbo這樣的分布式服務框架的需求,並且本質上是個服務調用的東東,說白了就是個遠程服務調用的分布式框架(告別Web Service模式中的WSdl,以服務者與消費者的方式在dubbo上注冊)
其核心部分包含:- 遠程通訊: 提供對多種基於長連接的NIO框架抽象封裝,包括多種線程模型,序列化,以及“請求-響應”模式的信息交換方式。
- 集群容錯: 提供基於接口方法的透明遠程過程調用,包括多協議支持,以及軟負載均衡,失敗容錯,地址路由,動態配置等集群支持。
- 自動發現: 基於注冊中心目錄服務,使服務消費方能動態的查找服務提供方,使地址透明,使服務提供方可以平滑增加或減少機器。
-
Dubbo能做什么?
- 透明化的遠程方法調用,就像調用本地方法一樣調用遠程方法,只需簡單配置,沒有任何API侵入。
- 軟負載均衡及容錯機制,可在內網替代F5等硬件負載均衡器,降低成本,減少單點。
- 服務自動注冊與發現,不再需要寫死服務提供方地址,注冊中心基於接口名查詢服務提供者的IP地址,並且能夠平滑添加或刪除服務提供者。
Dubbo采用全Spring配置方式,透明化接入應用,對應用沒有任何API侵入,只需用Spring加載Dubbo的配置即可,Dubbo基於Spring的Schema擴展進行加載。