天天看點

dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化

 dubbo接口自動化用例性能優化

目錄:導讀

前言

優化本地調試時間

單用例執行時間的優化

提高并發

最後

dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化

前言

去年換了一個新部門,看了下目前的自動化用例的情況,發現存在三類性能問題:

  • 本地調試運作時等待時間較長,就算是一個簡單的case,執行時間都需要1分鐘以上
  • 單用例執行時間比較長,部分用例執行時間超過2分鐘
  • 內建到CI中運作時,執行時間較長

對于上述三個問題花時間進行了一定程度的優化,總結如下

優化本地調試時間

通過調試可以發現,一個需要執行660ms的case,在執行前的初始化工作就需要消耗約1分半鐘,那麼就需要思考下能否減少這部分初始化時間了。

dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化

公司用的自動化架構是基于AbstractTestNGSpringContextTests的架構。AbstractTestNGSpringContextTests是一個spring內建testNg的工具,可以通過ApplicationContext加載bean。ApplicationContext實作的預設行為就是在啟動伺服器時将所有bean提前進行執行個體化。提前執行個體化意味着作為初始化過程的一部分,applicationContext執行個體會建立并配置所有的bean。

如果是作為一個spring服務,在啟動時将bean提前進行執行個體化,然後可以處理所有的請求,這樣的做法是很合理的。但是作為本地調試,更關注是自己case運作時所需要的bean是否執行個體化,而不需要将所有bean進行執行個體化。

查閱了下spring相關文檔,發現可以引入lazy-init來告訴ApplicationContext按需加載bean。

配置方式有兩種:

  1. default-lazy-init參數,其配置形式如下:

    <beans default-lazy-init="true" > </beans>

    dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化
  2. lazy-init參數,其配置形式如下:

    <bean id="stu" lazy-init=“true”></bean>

配置完成後,運作了一下,發現并沒有速度上的提升,原因是之前編寫時将大部分的bean的初始化放在了測試用例裡的基類裡面,導緻啟動時認為這些bean都需要初始化。

dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化

這說明要讓lazy-init生效,提高單用例的啟動速度,那就要盡可能少的使用不需要的bean,需要做一定改造:

  1. 将service/DAO初始化挪到測試用例裡面。
  2. 去除不需要的多餘的service/DAO。

按照上面的思路對用例進行了優化,可以将用例的初始化時間精簡到30秒左右。

dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化

單用例執行時間的優化

為什麼會出現很多的用例執行時間超過2分鐘呢?做了一些分析和調試後,主要有幾個原因:

  • 業務決定了服務之間很多是通過消息的方式進行傳遞,存在異步調用,是以需要等待再進行後續執行,為了用例的穩定性往往設定了過大的sleep time。
  • 一些資料準備和初始化操作不合理,無謂的耗時。

下面來看幾個案例:

  1. 在beforeclass裡面都會有一段初始化資料的操作,先調接口查詢資料是否存在,不存在則進行初始化,導緻每運作一個測試用例類都需要做一次對應操作。
    dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化
    實際上這些資料初始化完後可以一直被使用,不需要多次檢查,可以優化的地方是用個靜态變量判斷資料已初始化的話就不檢查,或者将該操作設定為跑一次用例集隻運作一次。
  2. 大量使用了sleep做等待,如果操作需要等待1s左右才生效,那麼用sleep往往需要sleep2秒,是以sleep一般會造成50%左右的性能浪費。

    引入異步校驗工具Awaitility對原有代碼進行改寫。

Awaitility的基本的文法為:

  • pollInterval:執行間隔
  • pollDelay:等待多久開始執行
  • atMoast:執行的逾時時間
  • until()-> 執行其中的語句直到傳回true或逾時
    dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化

這樣的寫法比較優雅簡介,如果判斷執行完成可以提前結束等待,避免時間浪費。

提高并發

當優化了單用例的運作時間後,雖然對總體自動化內建測試的運作速度有一定幫助,但當用例越來越多的時候,時間也會變得無法忍受,能想到的一個辦法是增加用例的并發。

用例能夠并發執行的前提是用例之間具有隔離性,一個用例的執行不會影響另一個用例的執行,比如我在店鋪A下單和在店鋪B下單這兩個用例就不會有幹擾,又比如我在店鋪A建立商品和我在店鋪A下單也不會有影響。

是以考慮用例并發的時候,需要先針對自己的業務特性進行一定程度的分組隔離。

在我們的案例中,考慮對店鋪進行分組,用例并發用到的并發基本機制是

testNG parallel="tests"/"class" thread-count=“N"

在實際執行中,分組的實施也會有兩種模式,按case的緯度還是按照類的緯度:

1.使用店鋪id分組進行并發,使用group=店鋪id 次元

優點:任意次元擴充

缺點:每個case需要加@group

2.把不同測試類按店鋪id分組,使用package/class次元

優點:改動簡單

缺點:需要每個測試類隻使用一個店鋪id,缺乏擴充性,需要頻繁改動配置檔案

最後選擇了按case緯度,因為現存的用例并未很好的按店鋪id進行組織,比較散亂,使用類的緯度改動較大。

dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化

使用了兩個并發以後,性能提升明顯,時間從547s->270s。

dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化

最後

解決了一部分性能問題後,尤其是提高了用例并發以後,對用例穩定性也更高了。

和開發寫代碼需要考慮異常和容錯處理一樣,測試人員在自動化設計、實施等各階段都需要考慮用例的穩定性問題:

  • 減少外部依賴。如果執行過程需要依賴其他系統的接口,那麼其他系統發生了變更或故障就會影響自身用例的進行。可以考慮通過預先生成的資料來替代調用外部接口生成資料在用例中使用。第三方接口的調用可以考慮mock
。
  • 預置資料代替建立過程。由于操作越多穩定性越低,使用預置資料而不是實時生成它,速度更快,穩定性更高。
  • 使用不同次元進行隔離。通過隔離,用例執行失敗的髒資料就不會影響其他用例。
  • 調優:逾時、等待時間。線上逾時時間設定的比較短,測試環境的機器配置不如線上,需要适時調大逾時和等待時間來保證接口調用不會逾時。
  • 防禦式程式設計。編寫測試代碼時不能假設資料已存在或者沒有髒資料殘留,是以預先的判斷和清理很重要,比如檢查到資料缺失就實時修複、用例運作之前考慮清除臨時資料等。
  • 定位并解決不穩定的問題。有時候偶現用例失敗,可以考慮給被測應用增加日志,同時持續多次運作用例多次(如 testNg 裡增加threadPoolSize=1, invocationCount=50)來複現問題,最終解決問題。

寫在最後

如果你覺得文章還不錯,請大家 點贊、分享、留言 下,因為這将是我持續輸出更多優質文章的最強動力!

看到這篇文章的人有覺得我的了解有誤的地方,也歡迎評論和探讨~

你也可以加入下方的的群聊去和同行大神交流切磋

dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化
dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化
dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化
dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化
dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化
dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化
dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化
dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化
dubbo接口自動化用例性能優化 dubbo接口自動化用例性能優化

繼續閱讀