欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

針對Dubbo接口Mock的解決方案詳解

 更新時間:2023年09月11日 15:58:59   作者:土豆肉絲蓋澆飯  
這篇文章主要為大家介紹了針對Dubbo接口Mock的解決方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

背景

為了提升減輕測試回歸壓力,提高項目開發(fā)交付質(zhì)量,我們開發(fā)和測試團隊合作在部分項目內(nèi)執(zhí)行自動化測試。

為了更好的理解,我們對mock的需要,先來看下wiki上對自動化測試的解釋。

在軟件測試中, 自動化測試指的是使用獨立于待測軟件的其他軟件來自動執(zhí)行測試、比較實際結(jié)果與預(yù)期并生成測試報告這一過程。

我們的自動化測試是按照我們預(yù)設(shè)的流程執(zhí)行的,我們不希望受到第三方服務(wù)的影響(上下線,接口返回錯誤數(shù)據(jù)),所以在調(diào)用三方接口的時候,我們會采取mock,返回我們預(yù)期的數(shù)據(jù)。

在自動化測試中,我們針對http,dubbo,mq消息這三種接口進行了mock,本文講解的是我們對dubbo接口進行mock的解決方案。

Dubbo目前提供方案

首先我們來看下dubbo框架本身提供的mock特性。

dubbo mock特性的核心代碼如下

//from MockClusterInvoker
public Result invoke(Invocation invocation) throws RpcException {
        Result result = null;
        //獲取方法級別mock配置
        String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), Constants.MOCK_KEY, Boolean.FALSE.toString()).trim();
        //沒有配置 或者 =false
        if (value.length() == 0 || value.equalsIgnoreCase("false")) {
            //no mock
            result = this.invoker.invoke(invocation);
        } else if (value.startsWith("force")) {
            // force 開頭 強制進行mock
            if (logger.isWarnEnabled()) {
                logger.warn("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + directory.getUrl());
            }
            //force:direct mock
            result = doMockInvoke(invocation, null);
        } else {
            //不是force的話 是失敗了再進行mock
            //fail-mock
            try {
                result = this.invoker.invoke(invocation);
            } catch (RpcException e) {
                //如果是業(yè)務(wù)異常不進行mock
                if (e.isBiz()) {
                    throw e;
                }
                if (logger.isWarnEnabled()) {
                    logger.warn("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + directory.getUrl(), e);
                }
                result = doMockInvoke(invocation, e);
            }
        }
        return result;
    }

針對url中key=mock對應(yīng)value的不同,分別對應(yīng)3種邏輯

  • value = null 不走mock
  • value = force xxx 強制走mock邏輯
  • value = xxx 調(diào)用服務(wù)失敗后走mock邏輯

看第三個邏輯,有沒有感覺到這其實是一個降級,失敗降級,而第二個邏輯,就稱為強制降級了。

dubbo提供的官方文檔,也將這個mock定義為降級

想了解Dubbo Mock表達式具體如何配置,可以看 Dubbo之降級Mock源碼分析

是否滿足我們需求

我們的需求是

  • 第三方是否在線不影響我們的mock
  • 配置靈活簡單

經(jīng)過測試,在設(shè)置check=false之后,給接口配置mock=force:return null之后,如果提供者不在線,會拋出沒有提供者異常,不滿足需求1

測試方式,對dubbo官方demo 增加如下配置

//from DemoServiceComponent
@Reference(mock = "force:return null",check = false)
private DemoService demoService;

對于需求2,也存在以下問題

  • 我們不可能去動原有項目中的dubbo配置,所以我們只能通過往dubbo的注冊中心增加override配置來觸發(fā)強制mock,使用上不方便
  • 從第1點也可以看到,mock功能依賴注冊中心,我們的mock環(huán)境和測試環(huán)境都是使用同一個注冊中心,不可行
  • mock value文檔不夠詳細,針對復(fù)雜類型的返回,構(gòu)造費勁

所以結(jié)論是,實現(xiàn)上和使用上都不能滿足我們需求,Dubbo的mock功能還是專注于生產(chǎn)級別的降級需求,我們需要開發(fā)方便我們使用的mock方案。

我們開發(fā)的擴展方案

我們開發(fā)針對dubbo框架的mock方案設(shè)計要點如下

  • 同樣的使用對Cluster擴展點包裝類來植入mock邏輯,保證服務(wù)下線不影響我們自動化測試運行
  • 使用properties配置文件來管理接口的mock開關(guān),配置可以托管到apollo,無代碼侵入
  • 轉(zhuǎn)發(fā)請求到我司的EsayMock服務(wù)器,配置接口返回類型的Json數(shù)據(jù)即可

能不能用Filter來做

之前在網(wǎng)上看到過類似的方案是使用Filter來實現(xiàn)的,其實我們第一版也是通過Filter來做,但是存在一個問題,我們mock的接口的提供者必須在線。

下面從源碼的角度來解釋為何出現(xiàn)這個問題

在使用zookeeper為注冊中心,以及check=false的前提下

Filter邏輯的植入是通過Protocol的包裝類ProtocolFilterWrapper,ProtocolFilterWrapper會對除了RegistryProtocol的其他Protocol植入Filter調(diào)用鏈邏輯。

//from ProtocolFilterWrapper
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
    if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
        return protocol.refer(type, url);
    }
    return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER);
}

問題就出在RegistryProtocol,RegistryProtocol通過Cluster,Directory模塊間接依賴了DubboProtocl,而在Directory模塊中,也就是RegistryDirectory中會對提供者數(shù)量進行檢查,如果為0,會拋出異常。這一切都發(fā)生在對DubboProtocl生成的invoker調(diào)用之前。

DubboProtocol生成的invoker,封裝了filter邏輯以及對遠端服務(wù)調(diào)用邏輯

RegistryProtcol生成的invoekr,在DubboProtocol基礎(chǔ)上封裝了集群調(diào)用,負載均衡等服務(wù)治理功能

//from RegistryDirectory
private void refreshInvoker(List<URL> invokerUrls) {
        Assert.notNull(invokerUrls, "invokerUrls should not be null");
        //這邊為什么是一個,針對沒有提供者目錄,dubbo框架會自動返回一個empty的url
        if (invokerUrls.size() == 1
                && invokerUrls.get(0) != null
                && Constants.EMPTY_PROTOCOL.equals(invokerUrls.get(0).getProtocol())) {
            this.forbidden = true; // Forbid to access
            this.invokers = Collections.emptyList();
            routerChain.setInvokers(this.invokers);
            destroyAllInvokers(); // Close all invokers
        }
        //...
}
public List<Invoker<T>> doList(Invocation invocation) {
        if (forbidden) {
            // 1. No service provider 2. Service providers are disabled
            throw new RpcException(RpcException.FORBIDDEN_EXCEPTION, "No provider available from registry " +
                    getUrl().getAddress() + " for service " + getConsumerUrl().getServiceKey() + " on consumer " +
                    NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() +
                    ", please check status of providers(disabled, not registered or in blacklist).");
        }
        //...
}

 沒看過dubbo源碼的朋友可能看不懂,你可以看了dubbo refer原理之后再來品味

不足

mock服務(wù)器中的json和dubbo接口不是強關(guān)聯(lián),不過問題不大,我們跑的都是預(yù)設(shè)流程。

開源項目

講了這么多,都是原理性的內(nèi)容,下面貼上鏈接,歡迎大家使用以及提建議。

dubbo-easy-mock 項目地址

以上就是針對Dubbo接口Mock的解決方案詳解的詳細內(nèi)容,更多關(guān)于Dubbo接口Mock解決的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java爬取豆瓣電影示例解析

    java爬取豆瓣電影示例解析

    這篇文章主要介紹了java爬取豆瓣電影示例解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧
    2020-07-07
  • MyBatis實現(xiàn)遞歸查詢的方法詳解

    MyBatis實現(xiàn)遞歸查詢的方法詳解

    在項目開發(fā)過程中,往往會遇到多級菜單、分類等多層級結(jié)構(gòu)數(shù)據(jù)的查詢。本文就來為大家講講MyBatis實現(xiàn)遞歸查詢的方法,感興趣的可以動手嘗試一下
    2022-08-08
  • 全網(wǎng)最深分析SpringBoot MVC自動配置失效的原因

    全網(wǎng)最深分析SpringBoot MVC自動配置失效的原因

    這篇文章主要介紹了全網(wǎng)最深分析SpringBoot MVC自動配置失效的原因,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧
    2020-07-07
  • SpringBoot配置連接兩個或多個數(shù)據(jù)庫的實現(xiàn)

    SpringBoot配置連接兩個或多個數(shù)據(jù)庫的實現(xiàn)

    本文主要介紹了SpringBoot配置連接兩個或多個數(shù)據(jù)庫的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧
    2023-05-05
  • 詳解如何在React中逃離閉包陷阱

    詳解如何在React中逃離閉包陷阱

    眾所周知,JavaScript 中的閉包(Closures)一定是這種語言最可怕的特性之一,另外它可能也是最隱蔽的語言特性之一,我們在編寫 React 代碼時經(jīng)常會用到它,但是大多數(shù)時候我們甚至沒有意識到這一點,本文小編將和大家一起深入探討如何在React中逃離閉包陷阱
    2023-09-09
  • SpringBoot整合Quartz實現(xiàn)定時任務(wù)詳解

    SpringBoot整合Quartz實現(xiàn)定時任務(wù)詳解

    這篇文章主要介紹了Java?任務(wù)調(diào)度框架?Quartz,Quartz是OpenSymphony開源組織在Job?scheduling領(lǐng)域又一個開源項目,完全由Java開發(fā),可以用來執(zhí)行定時任務(wù),類似于java.util.Timer。,下面我們來學(xué)習一下關(guān)于?Quartz更多的詳細內(nèi)容,需要的朋友可以參考一下
    2022-08-08
  • RestTemplate自定義ErrorHandler方式

    RestTemplate自定義ErrorHandler方式

    這篇文章主要介紹了RestTemplate自定義ErrorHandler方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • JAVA控制流程break?continue的示例代碼

    JAVA控制流程break?continue的示例代碼

    JAVA流程控制中有相關(guān)代碼可以終止整個流程的進程,他們就是(break和continue),本文通過實例代碼介紹下JAVA控制流程break?continue的相關(guān)知識,感興趣的朋友一起看看吧
    2022-03-03
  • Java并發(fā)系列之ReentrantLock源碼分析

    Java并發(fā)系列之ReentrantLock源碼分析

    這篇文章主要為大家詳細介紹了Java并發(fā)系列之ReentrantLock源碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • java實現(xiàn)圖片上插入文字并保存

    java實現(xiàn)圖片上插入文字并保存

    這篇文章主要為大家詳細介紹了java實現(xiàn)圖片上插入文字并保存,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06

最新評論