1.什么是 ZooKeeper?
答:ZooKeeper 是一個開源的分布式應用程序協調服務,是一個典型的分布式數據一致性解決方案。設計目的是將那些復雜且容易出錯的分布式一致性服務封裝起來,構成一個高效可靠的系統,并以一系列簡單易用的原子操作提供給用戶使用。
2.ZooKeeper 提供了哪些功能?
答:ZooKeeper 主要提供以下功能:
分布式服務注冊與訂閱:在分布式環境中,為了保證高可用性,通常同一個應用或同一個服務的提供方都會部署多份,達到對等服務。而消費者就須要在這些對等的服務器中選擇一個來執行相關的業務邏輯,比較典型的服務注冊與訂閱,如 Dubbo。
分布式配置中心:發布與訂閱模型,即所謂的配置中心,顧名思義就是發布者將數據發布到 ZooKeeper 節點上,供訂閱者獲取數據,實現配置信息的集中式管理和動態更新。
命名服務:在分布式系統中,通過命名服務客戶端應用能夠根據指定名字來獲取資源、服務地址和提供者等信息。
分布式鎖:這個主要得益于 ZooKeeper 為我們保證了數據的強一致性。
3.ZooKeeper 有幾種搭建模式?
答:ZooKeeper 通常有三種搭建模式:
單機模式:zoo.cfg 中只配置一個 server.id 就是單機模式了,此模式一般用在測試環境,如果當前主機宕機,那么所有依賴于當前 ZooKeeper 服務工作的其他服務器都不能進行正常工作;
偽分布式模式:在一臺機器啟動不同端口的 ZooKeeper,配置到 zoo.cfg 中,和單機模式相同,此模式一般用在測試環境;
分布式模式:多臺機器各自配置 zoo.cfg 文件,將各自互相加入服務器列表,上面搭建的集群就是這種完全分布式。
4.ZooKeeper 有哪些特性?
答: ZooKeeper 特性如下:
順序一致性(Sequential Consistency):來自相同客戶端提交的事務,ZooKeeper 將嚴格按照其提交順序依次執行;
原子性(Atomicity):于 ZooKeeper 集群中提交事務,事務將“全部完成”或“全部未完成”,不存在“部分完成”;
單一系統鏡像(Single System Image):客戶端連接到 ZooKeeper 集群的任意節點,其獲得的數據視圖都是相同的;
可靠性(Reliability):事務一旦完成,其產生的狀態變化將永久保留,直到其他事務進行覆蓋;
實時性(Timeliness):事務一旦完成,客戶端將于限定的時間段內,獲得最新的數據。
5.以下關于 ZooKeeper 描述錯誤的是?
A:所有的節點都具有穩定的存儲能力 B:ZooKeeper 任意節點之間都能夠進行通信(消息發送 & 接收) C:為了提高性能,ZooKeeper 允許同一份數據存在一部分節點寫成功,另一部分節點寫失敗 D:ZooKeeper 集群運行期間,只要半數以上節點存活,ZooKeeper 就能正常服務 答:C 題目解析:ZooKeeper 不允許同一份數據存在一部分節點寫成功,另一部分節點寫失敗的情況,這不符合 ZooKeeper“一致性”的原則。
6.ZooKeeper 如何實現分布式鎖?
答:ZooKeeper 實現分布式鎖的步驟如下:
客戶端連接 ZooKeeper,并在 /lock 下創建臨時的且有序的子節點,第一個客戶端對應的子節點為 /lock/lock-10000000001,第二個為 /lock/lock-10000000002,以此類推。
客戶端獲取 /lock 下的子節點列表,判斷自己創建的子節點是否為當前子節點列表中序號最小的子節點,如果是則認為獲得鎖,否則監聽剛好在自己之前一位的子節點刪除消息,獲得子節點變更通知后重復此步驟直至獲得鎖;
執行業務代碼;
完成業務流程后,刪除對應的子節點釋放鎖。
7.ZooKeeper 如何實現分布式事務?
答:ZooKeeper 實現分布式事務,類似于兩階段提交,總共分為以下 4 步:
客戶端先給 ZooKeeper 節點發送寫請求;
ZooKeeper 節點將寫請求轉發給 Leader 節點,Leader 廣播給集群要求投票,等待確認;
Leader 收到確認,統計投票,票數過半則提交事務;
事務提交成功后,ZooKeeper 節點告知客戶端。
8.集群中為什么要有主節點?
答:在分布式環境中,有些業務邏輯只需要集群中的某一臺機器進行執行,其他的機器可以共享這個結果,這樣可以大大減少重復計算,提高性能,這就是主節點存在的意義。
9.Dubbo 是什么?
答:Dubbo 是一款高性能、輕量級的開源 Java RPC 框架,它提供了三大核心能力:面向接口的遠程方法調用,智能容錯和負載均衡,以及服務自動注冊和發現。
10.Dubbo 有哪些特性?
答:Dubbo 特性如下:
面向接口代理的高性能 RPC 調用:提供高性能的基于代理的遠程調用能力,服務以接口為粒度,為開發者屏蔽遠程調用底層細節;
智能負載均衡:內置多種負載均衡策略,智能感知下游節點健康狀況,顯著減少調用延遲,提高系統吞吐量;
服務自動注冊與發現:支持多種注冊中心服務,服務實例上下線實時感知;
高度可擴展能力:遵循微內核+插件的設計原則,所有核心能力如 Protocol、Transport、Serialization 被設計為擴展點,平等對待內置實現和第三方實現;
運行期流量調度:內置條件、腳本等路由策略,通過配置不同的路由規則,輕松實現灰度發布,同機房優先等功能;
可視化的服務治理與運維:提供豐富服務治理、運維工具:隨時查詢服務元數據、服務健康狀態及調用統計,實時下發路由策略、調整配置參數。
11.Dubbo 有哪些核心組件?
答:Dubbo 核心組件如下:
Provider:服務提供方
Consumer:服務消費方
Registry:服務注冊與發現的注冊中心
Monitor:主要用來統計服務的調用次數和調用時間
Container:服務的運行容器
12.Dubbo 有哪些負載均衡策略?
答:Dubbo 負責均衡策略如下:
隨機負載均衡(Random LoadBalance):按權重設置隨機概率,在一個截面上碰撞的概率高,但調用量越大分布越均勻,而且按概率使用權重后也比較均勻,有利于動態調整提供者權重;
輪詢負載均衡(RoundRobin LoadBalance):按公約后的權重設置輪詢比率,存在慢的提供者累積請求的問題,比如:第二臺機器很慢,但沒掛,當請求調到第二臺時就卡在那,久而久之,所有請求都卡在調到第二臺上;
最少活躍調用數負載均衡(LeastActive LoadBalance):使用最少活躍調用數,活躍數指調用前后計數差;
哈希負載均衡(ConsistentHash LoadBalance):使用哈希值轉發,相同參數的請求總是發到同一提供者。
負載均衡配置如下:
服務端服務級別
\<dubbo:service interface="xxx" loadbalance="roundrobin" /\>
服務端方法級別
\<dubbo:reference interface="xxx" loadbalance="roundrobin" /\>
客戶端方法級別
\<dubbo:service interface="xxx"\>
? \<dubbo:method name="xxx" loadbalance="roundrobin"/\>
\</dubbo:service\>
客戶端方法級別
\<dubbo:reference interface="xxx"\>
? \<dubbo:method name="xxx" loadbalance="roundrobin"/\>
\</dubbo:reference\>
13.Dubbo 不支持以下哪種協議?
A:dubbo://
B:rmi://
C:redis://
D:restful://
答:D
題目解析:restful 是一種編程規范,并不是一種傳輸協議,也不被 Dubbo 支持。
14.Dubbo 默認使用什么注冊中心,還有別的選擇嗎?
答:推薦使用 ZooKeeper 作為注冊中心,還有 Nacos、Redis、Simple 注冊中心(普通的 Dubbo 服務)。
15.Dubbo 支持多注冊中心嗎?
答:Dubbo 支持同一服務向多注冊中心同時注冊,或者不同服務分別注冊到不同的注冊中心上去,甚至可以同時引用注冊在不同注冊中心上的同名服務。
多注冊中心注冊:
\<?xml version="1.0" encoding="UTF-8"?\>
\<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"\>
? ? \<dubbo:application name="world" /\>
? ? \<!-- 多注冊中心配置 --\>
? ? \<dubbo:registry id="hangzhouRegistry" address="10.20.141.150:9090" /\>
? ? \<dubbo:registry id="qingdaoRegistry" address="10.20.141.151:9010" default="false" /\>
? ? \<!-- 向多個注冊中心注冊 --\>
? ? \<dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" registry="hangzhouRegistry,qingdaoRegistry" /\>
\</beans\>
16.Dubbo 支持的連接方式有哪些?
答:Dubbo 支持的主要連接方式有:組播、直連和 ZooKeeper 等注冊中心。
① 組播方式,不需要啟動任何中心節點,只要廣播地址一樣,就可以互相發現。
提供方啟動時廣播自己的地址
消費方啟動時廣播訂閱請求
提供方收到訂閱請求時,單播自己的地址給訂閱者,如果設置了 unicast=false,則廣播給訂閱者
消費方收到提供方地址時,連接該地址進行 RPC 調用
組播受網絡結構限制,只適合小規模應用或開發階段使用。組播地址段:224.0.0.0 ~ 239.255.255.255
配置
\<dubbo:registry address="multicast://224.5.6.7:1234" /\>
或
\<dubbo:registry protocol="multicast" address="224.5.6.7:1234" /\>
為了減少廣播量,Dubbo 缺省使用單播發送提供者地址信息給消費者,如果一個機器上同時啟了多個消費者進程,消費者需聲明 unicast=false,否則只會有一個消費者能收到消息;當服務者和消費者運行在同一臺機器上,消費者同樣需要聲明 unicast=false,否則消費者無法收到消息,導致 No provider available for the service 異常:
\<dubbo:registry address="multicast://224.5.6.7:1234?unicast=false" /\>
或
\<dubbo:registry protocol="multicast" address="224.5.6.7:1234"\>
? ? \<dubbo:parameter key="unicast" value="false" /\>
\</dubbo:registry\>
② 直連方式,注冊中心本身就是一個普通的 Dubbo 服務,可以減少第三方依賴,使整體通訊方式一致。
\<dubbo:registry protocol="zookeeper" address="N/A" file="./.dubbo-platform"/\>
將 Simple 注冊中心暴露成 Dubbo 服務:
\<?xml version="1.0" encoding="UTF-8"?\>
\<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"\>
? ? \<!-- 當前應用信息配置 --\>
? ? \<dubbo:application name="simple-registry" /\>
? ? \<!-- 暴露服務協議配置 --\>
? ? \<dubbo:protocol port="9090" /\>
? ? \<!-- 暴露服務配置 --\>
? ? \<dubbo:service interface="org.apache.dubbo.registry.RegistryService" ref="registryService" registry="N/A" ondisconnect="disconnect" callbacks="1000"\>
? ? ? ? \<dubbo:method name="subscribe"\>\<dubbo:argument index="1" callback="true" /\>\</dubbo:method\>
? ? ? ? \<dubbo:method name="unsubscribe"\>\<dubbo:argument index="1" callback="false" /\>\</dubbo:method\>
? ? \</dubbo:service\>
? ? \<!-- 簡單注冊中心實現,可自行擴展實現集群和狀態同步 --\>
? ? \<bean id="registryService" class="org.apache.dubbo.registry.simple.SimpleRegistryService" /\>
\</beans\>
引用 Simple Registry 服務:
\
或者:
或者:
適用性說明:此 SimpleRegistryService 只是簡單實現,不支持集群,可作為自定義注冊中心的參考,但不適合直接用于生產環境。
③ 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="*" />,可訂閱服務的所有分組和所有版本的提供者
Zookeeper 使用
在 provider 和 consumer 中增加 zookeeper 客戶端 jar 包依賴:
\<dependency\>
? ? \<groupId\>org.apache.zookeeper\</groupId\>
? ? \<artifactId\>zookeeper\</artifactId\>
? ? \<version\>3.3.3\</version\>
\</dependency\>
Dubbo 支持 zkclient 和 curator 兩種 Zookeeper 客戶端實現:
注意:在 2.7.x 的版本中已經移除了 zkclient 的實現,如果要使用 zkclient 客戶端,需要自行拓展。
使用 zkclient 客戶端
從 2.2.0 版本開始缺省為 zkclient 實現,以提升 zookeeper 客戶端的健狀性。zkclient?是 Datameer 開源的一個 Zookeeper 客戶端實現。
缺省配置:
\<dubbo:registry ... client="zkclient" /\>
或:
dubbo.registry.client=zkclient
或:
zookeeper://10.20.153.10:2181?client=zkclient
需依賴或直接下載:
\<dependency\>
? ? \<groupId\>com.github.sgroschupf\</groupId\>
? ? \<artifactId\>zkclient\</artifactId\>
? ? \<version\>0.1\</version\>
\</dependency\>
使用 curator 客戶端
從 2.3.0 版本開始支持可選 curator 實現。Curator 是 Netflix 開源的一個 Zookeeper 客戶端實現。
如果需要改為 curator 實現,請配置:
\<dubbo:registry ... client="curator" /\>
或:
dubbo.registry.client=curator
或:
zookeeper://10.20.153.10:2181?client=curator
需依賴或直接下載:
\<dependency\>
? ? \<groupId\>com.netflix.curator\</groupId\>
? ? \<artifactId\>curator-framework\</artifactId\>
? ? \<version\>1.1.10\</version\>
\</dependency\>
Zookeeper 單機配置:
\<dubbo:registry address="zookeeper://10.20.153.10:2181" /\>
或:
\<dubbo:registry protocol="zookeeper" address="10.20.153.10:2181" /\>
Zookeeper 集群配置:
\<dubbo:registry address="zookeeper://10.20.153.10:2181?backup=10.20.153.11:2181,10.20.153.12:2181" /\>
或:
\<dubbo:registry protocol="zookeeper" address="10.20.153.10:2181,10.20.153.11:2181,10.20.153.12:2181" /\>
同一 Zookeeper,分成多組注冊中心:
17.什么是服務熔斷?
答:在應用系統服務中,當依賴服務因訪問壓力過大而響應變慢或失敗,上游服務為了保護系統整體的可用性,臨時切斷對下游服務的調用。這種犧牲局部,保全整體的措施就叫做熔斷。
18.Dubbo 可以對結果進行緩存嗎?支持的緩存類型都有哪些?
答:可以,Dubbo 提供了聲明式緩存,用于加速熱門數據的訪問速度,以減少用戶加緩存的工作量。
Dubbo 支持的緩存類型有:
lru 基于最近最少使用原則刪除多余緩存,保持最熱的數據被緩存;
threadlocal 當前線程緩存,比如一個頁面渲染,用到很多 portal,每個 portal 都要去查用戶信息,通過線程緩存,可以減少這種多余訪問;
jcache 集成,可以橋接各種緩存實現。
配置如下:
\<dubbo:reference interface="com.foo.BarService" cache="lru" /\>
或
\<dubbo:reference interface="com.foo.BarService"\>
? ? \<dubbo:method name="findBar" cache="lru" /\>
\</dubbo:reference\>
19.Dubbo 有幾種集群容錯模式?
答:Dubbo 集群容錯模式如下。
① Failover Cluster
失敗自動切換,當出現失敗,重試其他服務器。通常用于讀操作,但重試會帶來更長延遲。可通過?retries="2"?來設置重試次數(不含第一次)。
重試次數配置如下:
\<dubbo:service retries="2" /\>
或
\\<dubbo:reference retries="2" /\>
或
\<dubbo:reference\>\\</dubbo:reference\>
② Failfast Cluster
快速失敗,只發起一次調用,失敗立即報錯。通常用于非冪等性的寫操作,比如新增記錄。
③ Failsafe Cluster
失敗安全,出現異常時,直接忽略。通常用于寫入審計日志等操作。
④ Failback Cluster
失敗自動恢復,后臺記錄失敗請求,定時重發。通常用于消息通知操作。
⑤ Forking Cluster
并行調用多個服務器,只要一個成功即返回。通常用于實時性要求較高的讀操作,但需要浪費更多服務資源。可通過 forks="2" 來設置最大并行數。
⑥ Broadcast Cluster
廣播調用所有提供者,逐個調用,任意一臺報錯則報錯。通常用于通知所有提供者更新緩存或日志等本地資源信息。