首頁>技術>

因目前公司內部對http介面自動化,dubbo介面自動化都是使用指令碼來管理,技術棧還分java 和python ,內部對接很不方便,為了降低使用門檻,提升介面測試效率,所以決定在原有的功能用例管理平臺新增介面自動化來統一管理。

MeterSphere

首先吹一波MeterSphere,個人覺得目前最好,功能最完善的介面自動化平臺,專案還在持續更新,並且有開源版,大家有興趣可以看一下專案程式碼https://github.com/metersphere/

個人對於這個平臺Http介面測試的部分理解:透過前端的入參將其封裝成JMeter能識別的 .jmx檔案,再透過JMeter的開放API去執行.jmx檔案。

這裡不得不說 該專案成員對JMeter非常熟悉,拋棄了jmeter難用的GUI,實現了一套非常好用UI,MeterSphere牛皮。

移植MeterSphere部分功能

因為只需要介面測試的功能,所以只移介面測試部分。首先要做的就是在本地部署MeterSphere,官方文件只有docker部署教程,沒有windows下搭建的教程,而且sql檔案還分別放在不同的檔案下面,這無疑增加了二次開發 的成本。最後我在linux下部署專案,然後將sql匯出,在application.properties新增資料庫配置,註釋了原專案中的部分程式碼,在windows 下成功啟動,並且移植了介面測試模組的功能,然後,在測試的時候發現Dubbo介面無法成功呼叫,於是便有了第一次修改原始碼的操作……

發現問題:dubbo介面測試報錯

MeterSphere這裡對Dubbo的配置很多,原本想簡化測試,這一套配置填下去,感覺比原有的方式還要麻煩,於是這裡我便將配置預設寫死,因為公司目前使用zk做註冊中心,其他的consumer&Service、Config Service這個配置也無需使用人員去配置。

在這裡插入圖片描述

但是當我填入對應的引數,請求dubbo介面的時候,問題就出現了

Failed to check the status of the service xxx.xxx.xxx . No provider available for the service

一直報錯找不到對應的服務,而我用現有的指令碼請求是能夠成功的,確認了環境沒有問題之後,我想可能是Dubbo版本的原因

定位問題:dubbo版本

先來看兩張圖

在這裡插入圖片描述

在這裡插入圖片描述

我在maven倉庫裡面搜出來結果可以發現,Dubbo是在2.7.x版本被apache收錄,2.6.x的版本 groupId是com.alibaba。於是在專案中找到對應依賴,果然版本對不上,我們系統目前使用的Dubbo是2.5.x,阿里的版本。而這兩個版本連線ZK的方式也不同,老版本是透過

        <dependency>            <groupId>com.101tec</groupId>            <artifactId>zkclient</artifactId>        </dependency>

新版本則是使用

        <dependency>            <groupId>org.apache.curator</groupId>            <artifactId>curator-framework</artifactId>        </dependency>

確定問題就是版本問,於是便開始了改原始碼

解決問題:修改jmeter-plugins-for-apache-dubbo外掛程式碼

Jmeter支援Dubbo介面需要jmeter-plugins-for-apache-dubbo這個三方外掛支援,官方目前使用的是2.7.12不適合我們系統

        <dependency>            <groupId>io.metersphere</groupId>            <artifactId>jmeter-plugins-dubbo</artifactId>            <version>2.7.12</version>        </dependency>

於是我將其修改為官方提供的1.3.x,發現呼叫Dubbo介面還是失敗,無法找到對應的服務。

最後我將1.3.x三方包下載到本地,研究其泛化呼叫的程式碼,發現其中很大一部分程式碼其實是對不同註冊中心如:zookeeper、nacos、redis的支援,而公司目前使用的zookeeper,我完全可以將這些不用的程式碼註釋掉,自己封裝一套泛化呼叫的邏輯,

    @SuppressWarnings({"unchecked", "rawtypes"})    private Object callDubbo(SampleResult res) {        try {            ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();            ApplicationConfig applicationConfig = new ApplicationConfig();            applicationConfig.setName("remoteInvoke");            applicationConfig.setVersion("");            RegistryConfig registryConfig = new RegistryConfig();            registryConfig.setFile("/tmp/dubbo.cachr");            String address = getAddress();            registryConfig.setAddress(address);            registryConfig.setProtocol("zookeeper");            reference.setApplication(applicationConfig);            reference.setRegistry(registryConfig);            // 弱型別介面名            String interfaceName = getInterface();            reference.setInterface(interfaceName);            reference.setVersion("1.0.0");            // 宣告為泛化介面            reference.setGeneric(true);            reference.setProtocol("dubbo");            //不重試,重試會造成資料重複執行            reference.setRetries(0);            reference.setTimeout(10000);            String methodName = getMethod();            if (StringUtils.isBlank(methodName)) {                res.setSuccessful(false);                return ErrorCode.MISS_METHOD.getMessage();            }            // 用org.apache.dubboinfo.rpc.service.GenericService可以替代所有介面引用            GenericService genericService = reference.get();            if (genericService == null) {                res.setSuccessful(false);                return MessageFormat.format(ErrorCode.GENERIC_SERVICE_IS_NULL.getMessage(), interfaceName);            }            String[] parameterTypes = null;            Object[] parameterValues = null;            List<MethodArgument> args = getMethodArgs();            List<String> paramterTypeList =  new ArrayList<String>();;            List<Object> parameterValuesList = new ArrayList<Object>();;            for(MethodArgument arg : args) {                ClassUtils.parseParameter(paramterTypeList, parameterValuesList, arg);            }            parameterTypes = paramterTypeList.toArray(new String[paramterTypeList.size()]);            parameterValues = parameterValuesList.toArray(new Object[parameterValuesList.size()]);            Object result = null;            try {                result = genericService.$invoke(methodName, parameterTypes, parameterValues);                res.setSuccessful(true);            } catch (Exception e) {                log.error("RpcException:", e);                //TODO                //當介面返回異常時,sample標識為successful,透過響應內容做斷言來判斷是否標識sample錯誤,因為sample的錯誤會統計到用例的error百分比內。                //比如介面有一些校驗性質的異常,不代表這個操作是錯誤的,這樣就可以靈活的判斷,不至於正常的校驗返回導致測試用例error百分比的不真實                res.setSuccessful(true);                result = e;            }            return result;        } catch (Exception e) {            log.error("UnknownException:", e);            res.setSuccessful(false);            return e;        } finally {            //TODO 不能在sample結束時destroy//            if (registry != null) {//                registry.destroyAll();//            }//            reference.destroy();        }    }

最後,將程式碼打成jar包,透過maven離線呼叫

        <dependency>            <groupId>io.metersphere</groupId>            <artifactId>jmeter-plugins-dubbo</artifactId>            <version>1.3.8</version>            <scope>system</scope>            <systemPath>${project.basedir}/lib/jmeter-plugins-dubbo-1.3.8.jar</systemPath>        </dependency>

終於請求成功

在這裡插入圖片描述

結語

正當我幻想著給MeterSphere提交issure,並提交pr,成為一個熱門開源專案的貢獻者,從此走上人生巔峰時。我發現MeterSphere專案上的提交記錄赫然寫著 :

"fix: 修復dubbo客戶端v2.7.7以上版本在進行泛化呼叫server端為v2.6.x以前版本時出現No Provider錯誤"

BUG其實在兩個月前被解決了…雖然沒能成為MeterSphere 的貢獻者,但是第一次透過修改原始碼來解決BUG,還是很有成就感的。

13
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 如果雲是水滴,Kubernetes就是水滴管理平臺