Java面試題2.0--dubbo

歡迎關注《Java面試題2.0》合集發佈頁,持續更新中!

 
dubbo是什麼
 
dubbo是一個分佈式框架,遠程服務調用的分佈式框架,其核心部分包含:
集羣容錯:提供基於接口方法的透明遠程過程調用,包括多協議支持,以及軟負載均衡,失敗容錯,地址路由,動態配置等集羣支持。
遠程通訊: 提供對多種基於長連接的NIO框架抽象封裝,包括多種線程模型,序列化,以及“請求-響應”模式的信息交換方式。
自動發現:基於註冊中心目錄服務,使服務消費方能動態的查找服務提供方,使地址透明,使服務提供方可以平滑增加或減少機器。
 
 
dubbo能做什麼
 
1.透明化的遠程方法調用,就像調用本地方法一樣調用遠程方法,只需簡單配置,沒有任何API侵入。
2.軟負載均衡及容錯機制,可在內網替代F5等硬件負載均衡器,降低成本,減少單點。
3.服務自動註冊與發現,不再需要寫死服務提供方地址,註冊中心基於接口名查詢服務提供者的IP地址,並且能夠平滑添加或刪除服務提供者。
 
 
在 Provider 上可以配置的 Consumer 端的屬性有哪些?
 
1)timeout:方法調用超時
2)retries:失敗重試次數,默認重試 2 次
3)loadbalance:負載均衡算法,默認隨機
4)actives 消費者端,最大併發調用限制
 
 
Dubbo支持服務多協議嗎?
Dubbo 允許配置多協議,在不同服務上支持不同協議或者同一服務上同時支持多種協議。
 
當一個服務接口有多種實現時怎麼做?
當一個接口有多種實現時,可以用 group 屬性來分組,服務提供方和消費方都指定同一個 group 即可。
 
服務上線怎麼兼容舊版本?
可以用版本號(version)過渡,多個不同版本的服務註冊到註冊中心,版本號不同的服務相互間不引用。這個和服務分組的概念有一點類似。
 
Dubbo可以對結果進行緩存嗎?
可以,Dubbo 提供了聲明式緩存,用於加速熱門數據的訪問速度,以減少用戶加緩存的工作量。
 
Dubbo服務之間的調用是阻塞的嗎?
默認是同步等待結果阻塞的,支持異步調用。
Dubbo 是基於 NIO 的非阻塞實現並行調用,客戶端不需要啓動多線程即可完成並行調用多個遠程服務,相對多線程開銷較小,異步調用會返回一個 Future 對象。
 
Dubbo中zookeeper做註冊中心,如果註冊中心集羣都掛掉,發佈者和訂閱者之間還能通信麼?
可以通信的,啓動dubbo時,消費者會從zk拉取註冊的生產者的地址接口等數據,緩存在本地。每次調用時,按照本地存儲的地址進行調用;
註冊中心對等集羣,任意一臺宕機後,將會切換到另一臺;註冊中心全部宕機後,服務的提供者和消費者仍能通過本地緩存通訊。服務提供者無狀態,任一臺 宕機後,不影響使用;服務提供者全部宕機,服務消費者會無法使用,並無限次重連等待服務者恢復;
掛掉是不要緊的,但前提是你沒有增加新的服務,如果你要調用新的服務,則是不能辦到的。
 
 
dubbo服務負載均衡策略?
l Random LoadBalance
    隨機,按權重設置隨機概率。在一個截面上碰撞的概率高,但調用量越大分佈越均勻,而且按概率使用權重後也比較均勻,有利於動態調整提供者權重。(權重可以在dubbo管控臺配置)
 
l RoundRobin LoadBalance
    輪循,按公約後的權重設置輪循比率。存在慢的提供者累積請求問題,比如:第二臺機器很慢,但沒掛,當請求調到第二臺時就卡在那,久而久之,所有請求都卡在調到第二臺上。
 
l LeastActive LoadBalance
   最少活躍調用數,相同活躍數的隨機,活躍數指調用前後計數差。使慢的提供者收到更少請求,因爲越慢的提供者的調用前後計數差會越大。
 
l ConsistentHash LoadBalance
一致性Hash,相同參數的請求總是發到同一提供者。當某一臺提供者掛時,原本發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引起劇烈變動。缺省只對第一個參數Hash,如果要修改,請配置
 
 
 Dubbo在安全機制方面是如何解決的
Dubbo通過Token令牌防止用戶繞過註冊中心直連,然後在註冊中心上管理授權。Dubbo還提供服務黑白名單,來控制服務所允許的調用方。
 
dubbo的調用流程
Provider
第 0 步,start 啓動服務。
第 1 步,register 註冊服務到註冊中心。
Consumer
第 2 步,subscribe 向註冊中心訂閱服務。
注意,只訂閱使用到的服務。
再注意,首次會拉取訂閱的服務列表,緩存在本地。
【異步】第 3 步,notify 當服務發生變化時,獲取最新的服務列表,更新本地緩存。
invoke 調用
Consumer 直接發起對 Provider 的調用,無需經過註冊中心。而對多個 Provider 的負載均衡,Consumer 通過 cluster 組件實現。
count 監控
【異步】Consumer 和 Provider 都異步通知監控中心。
 
 
Dubbo 可以對調用結果進行緩存嗎?
Dubbo 通過 CacheFilter 過濾器,提供結果緩存的功能,且既可以適用於 Consumer 也可以適用於 Provider 。
通過結果緩存,用於加速熱門數據的訪問速度,Dubbo 提供聲明式緩存,以減少用戶加緩存的工作量。
Dubbo 目前提供三種實現:
 
lru :基於最近最少使用原則刪除多餘緩存,保持最熱的數據被緩存。
threadlocal :當前線程緩存,比如一個頁面渲染,用到很多 portal,每個 portal 都要去查用戶信息,通過線程緩存,可以減少這種多餘訪問。
jcache :與 JSR107 集成,可以橋接各種緩存實現。
 
 
服務提供方的優雅停機過程
 
首先,從註冊中心中取消註冊自己,從而使消費者不要再拉取到它。
然後,sleep 10 秒( 可配 ),等到服務消費,接收到註冊中心通知到該服務提供者已經下線,加大了在不重試情況下優雅停機的成功率。
之後,廣播 READONLY 事件給所有 Consumer 們,告訴它們不要在調用我了!!!【很有趣的一個步驟】並且,如果此處註冊中心掛掉的情況,依然能達到告訴 Consumer ,我要下線了的功能。
再之後,sleep 10 毫秒,保證 Consumer 們,儘可能接收到該消息。
再再之後,先標記爲不接收新請求,新請求過來時直接報錯,讓客戶端重試其它機器。
再再再之後,關閉心跳線程。
最後,檢測線程池中的線程是否正在運行,如果有,等待所有線程執行完成,除非超時,則強制關閉。
最最後,關閉服務器。
 
Dubbo Consumer 只能調用從註冊中心獲取的 Provider 麼?
不是,Consumer 可以強制直連 Provider 。
 
在開發及測試環境下,經常需要繞過註冊中心,只測試指定服務提供者,這時候可能需要點對點直連,點對點直連方式,將以服務接口爲單位,忽略註冊中心的提供者列表,A 接口配置點對點,不影響 B 接口從註冊中心獲取列表。
 
Dubbo 支持哪些通信協議?
對應【protocol 遠程調用層】。
Dubbo 目前支持如下 9 種通信協議:
【重要】dubbo:
【重要】rest:
webservice:
redis:
http:
 
spi 是啥?
 
spi,簡單來說,就是 service provider interface ,說白了是什麼意思呢,比如你有個接口,現在這個接口有 3 個實現類,那麼在系統運行的時候對這個接口到底選擇哪個實現類呢?這就需要 spi 了,需要根據指定的配置或者是默認的配置,去找到對應的實現類加載進來,然後用這個實現類的實例對象。
 
分佈式服務接口請求的順序性如何保證?
 
首先,一般來說,個人建議是,你們從業務邏輯上設計的這個系統最好是不需要這種順序性的保證,因爲一旦引入順序性保障,比如使用分佈式鎖,會導致系統複雜度上升,而且會帶來效率低下,熱點數據壓力過大等問題。
 
下面我給個我們用過的方案吧,簡單來說,首先你得用 Dubbo 的一致性 hash 負載均衡策略,將比如某一個訂單 id 對應的請求都給分發到某個機器上去,接着就是在那個機器上,因爲可能還是多線程併發執行的,你可能得立即將某個訂單 id 對應的請求扔一個內存隊列裏去,強制排隊,這樣來確保他們的順序性。
 
分佈式服務接口的冪等性如何設計(比如不能重複扣款)?
 
保證冪等性主要是三點:
 
1、對於每個請求必須有一個唯一的標識,舉個栗子:訂單支付請求,肯定得包含訂單 id,一個訂單 id 最多支付一次,對吧。
2、每次處理完請求之後,必須有一個記錄標識這個請求處理過了。常見的方案是在 mysql 中記錄個狀態啥的,比如支付之前記錄一條這個訂單的支付流水。
3、每次接收請求需要進行判斷,判斷之前是否處理過。比如說,如果有一個訂單已經支付了,就已經有了一條支付流水,那麼如果重複發送這個請求,則此時先插入支付流水,orderId 已經存在了,唯一鍵約束生效,報錯插入不進去的。然後你就不用再扣款了。
 
服務調用超時問題怎麼解決
dubbo在調用服務不成功時,默認是會重試兩次的。這樣在服務端的處理時間超過了設定的超時時間時,就會有重複請求,比如在發郵件時,可能就會發出多份重複郵件,執行註冊請求時,就會插入多條重複的註冊數據,那麼怎麼解決超時問題呢?如下
1.對於核心的服務中心,去除dubbo超時重試機制,並重新評估設置超時時間。
2.業務處理代碼必須放在服務端,客戶端只做參數驗證和服務調用,不涉及業務流程處理
全局配置實例
 
<dubbo:provider delay="-1" timeout="6000" retries="0"/>  
當然Dubbo的重試機制其實是非常好的QOS保證,它的路由機制,是會幫你把超時的請求路由到其他機器上,而不是本機嘗試,所以 dubbo的重試機器也能一定程度的保證服務的質量。但是請一定要綜合線上的訪問情況,給出綜合的評估。
 
默認使用什麼序列化框架,還有其他的嗎?
Dubbo默認使用的是Hessian序列化。hessian是一個採用二進制格式傳輸的服務框架,相對傳統soap web service,更輕量,更快速。
 
SpringCloud與Dubbo區別?
 
相同點:
dubbo與springcloud都可以實現RPC遠程調用。
dubbo與springcloud都可以使用分佈式、微服務場景下。
區別:
dubbo有比較強的背景,在國內有一定影響力。
dubbo使用zk或redis作爲作爲註冊中心
springcloud使用eureka作爲註冊中心
dubbo支持多種協議,默認使用dubbo協議。
Springcloud只能支持http協議。
Springcloud是一套完整的微服務解決方案。
Dubbo目前已經停止更新,SpringCloud更新速度快。
 
遇到的問題
場景描述:客戶端遠程異步調用ServiceA,ServiceA在處理客戶端請求的過程中需要遠程同步調用ServiceB,ServiceA從ServiceB的響應中取數據時,得到的是null。
對於上面的問題,解決辦法有三個:
1.方法調用兩次
 
ServiceA調用ServiceB的地方寫兩次一樣的調用,這個方法原理就像ServiceB調用ServiceC一樣,即清除attachements。
這個方法最簡單,但是可能對不瞭解的人來說,這塊業務代碼寫重複了,會不小心刪除掉,而且從寫代碼的角度來說,這個很雞肋,所以不推薦。
2.修改Dubbo源碼
 
修改AbstractInvoker第137行,改成每次都對async進行實際賦值,
boolean isAsync = getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false);
invocation.setAttachment(Constants.ASYNC_KEY, String.valueOf(isAsync));
3.自定義Filter
 
實現com.alibaba.dubbo.rpc.Filter,在RpcContext中清除這個async,
@Activate(group = {Constants.PROVIDER})
  public class AsyncFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
     RpcContext.getContext().getAttachments().remove(Constants.ASYNC_KEY);
return invoker.invoke(invocation);
}
}
同時在src/main/resources/META-INF/dubbo/下添加com.alibaba.dubbo.rpc.Filter文件,內容文件如下:
asyncFilter=com.abc.filter.AsyncFilter
 
 
 
 
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章