最近幾年雖然微服務十分火熱,但是仍然有不少人不喜歡微服務,甚至抵制它。其中最主要的原因就是其成本高,難度大。就困難而言,主要是遇到了一些不易解決的問題,其中包括以下三個與測試資料和測試環境有關的問題:
1
問題一:測試環境被多個團隊共同使用
在大規模的微服務系統中,某些核心服務很多時候都是會被多個團隊在共同調用,并且它可能也有多個依賴服務。而當一個服務的某個測試環境被多個團隊(服務)共同使用的時候,主要會存在以下兩個困難點。1、同一測試資料可能會被不同的團隊修改。有些團隊通過建立多套測試環境來解決這個問題,但是這樣的成本很高。對于很多技術強大的網際網路公司,可以通過 Docker 等技術手段來降低一些成本,但是對于很多傳統企業來講,高成本的多環境很難實施。2、同一測試資料可能被其他團隊占用,所謂的占用就是一個測試資料一旦不小心被某個人使用了,他可能按自己的場景在進行使用,這個時候你去用它,很可能受到影響而得不到自己想要的結果。
2
問題二:測試資料準備需要花費大量時間
當測試一些業務不是很複雜的系統時,準備測試資料也許不是一件困難的事情。但是在一些傳統行業的複雜系統中,準備測試資料是一項非常困難的事情,比如在銀行,保險,通信等複雜系統中。我曾經測試過一個保險系統,要在測試環境中準備一套資料甚至需要幾個小時,因為整個系統的業務非常複雜,資料庫設計也非常複雜,而且還是遺留系統,幾乎沒有人懂得直接操作資料庫來準備資料。是以,資料的準備必須由系統建立。而系統本身是基于 MainFrame 的,而且 UI 全部是 Console 下的 UI,操作十分繁瑣和複雜,導緻建立一套測試資料需要花費很長時間。很多銀行和保險公司的核心系統到現在也是保留這樣的模式。是以在這樣的傳統行業中的遺留系統中,測試資料的準備是一個非常大的問題, 其次很多系統中,測試資料一旦使用了,狀态就會改變,進而不能重複使用。是以再次測試就需要重新建立測試資料,這也是一個常見的嚴重的問題。
3
問題三:服務部署或網絡等問題導緻的測試環境不穩定以及版本不比對
這個也是經常會遇到的情況。對于一些穩定而沒有什麼變化的系統,也許這不是一個問題,但是對于一些正在開發過程中,或者有大量修改或者本身不穩定的系統中,這個問題就十分常見。某些服務部署和網絡問題,這個容易了解了,就是依賴的服務正在部署。其次是依賴服務的正在調試,而調試的過程中,服務本身的一些狀态可能在不停的改變。或者依賴服務存在 Bug,導緻服務也存在問題。最終,使用者可能隻需要 1.0 版的依賴服務,但在測試環境中已經部署了 2.0 版的服務,是以使用者無法使用服務。
解決方案:服務虛拟化可以使用服務虛拟化(Service Virtualization)技術來解決以上這些問題。下圖是服務虛拟化的簡單示意圖:
服務虛拟化看起來雖然簡單,但是其實作已經做到非常豐富的功能,比如 Hoverfly 等,進而解決上面那一系列問題。
4
Hoverfly
Hoverfly 是一個開源免費(Apache 2)的服務虛拟化的一個工具,其虛拟資料是可以複用的 Json 格式的 Simulation。它是基于 Go 開發的,輕巧,高效。同時支援 Python 和 Java 進行擴充,也提供 REST API 來對其進行控制。并且暫時提供模拟網絡延遲,随機錯誤和限定速率。但是其支援的協定優先,暫時隻支援 HTTP 和 HTTPS。但是其最重要的是其支援六種工作模型,它們分别是:Capture 模型,Simulate 模型,Spy 模型,Synthesize 模型,Modify 模型,Diff 模型。通過這六種模型,基本可以實作服務虛拟化的各種功能。首先,通過 Capture 模型可以擷取到在手工測試和系統正常使用的情況下,各種服務的互動資料,然後再進行分析和修改,可以獲得更多類型的資料。将這些資料通過 Spy、Synthesize、Modify 和 Simulate 模型進行不同類型的服務虛拟。不同的團隊可以根據基礎類型資料快速定制自己團隊的私有虛拟資料集,并且還可以根據不同版本的服務,定制不同版本的虛拟資料集,進而隔離了不同版本服務之間的資料,避免了不同團隊之間的的測試資料沖突。
下面就來逐個介紹一下這六個模型。
4.1
Capture 模型
Capture 模型是标準的錄制功能。這個時候 Hoverfly 就是一個标準的 Proxy 服務。把它架設在被測的服務和外部服務之間,都可以把所有的互動資料錄制成特定的 Json 檔案,稱之為 Simulation。然後就可以根據不同的需求更改 Simulation,并用到其他模型裡面。
4.2
Simulate 模型
Simulate 是标準的 Stub 模型。可以将通過 Capture 模型錄制到的 Simulation 或者手動編寫的 Simulation 直接加載進 Hoverfly,然後所有滿足 Simulation 裡面的比對規則的 Request 就會傳回 Simulation 裡面的虛拟 Response,不然就不會傳回任何正确的 Response。
4.3
Spy 模型
Spy 模型是一個最為特殊的模型,也是我在正式項目中最常用的一種模型。它最特殊的功能就是可以讓部分請求獲得虛拟的 Response,而其他部分請求獲得真實的 Response。
是以,通過改變測試資料本身,可以确定使用的是實際依賴系統還是虛拟依賴活動。而這種情況下,在傳統已有的這種 Stub 工具裡面可能是需要自己手工去實作的,至少它預設不支援。但是 Hoverfly 是預設就支援,是以隻需要把規則加到 Hoverfly 的這個虛拟檔案裡面,它就能實作這個功能。
其次有些時候在同一個測試環境裡面,我既需要虛拟的資料,又要真實資料的情況下,Spy 模型是最佳解決方案。因為隻有這樣才能以最低的成本,來實作了既可以測真實的資料,又可以測虛拟的資料。
為什麼會需要這個模型?因為不少時候測試環境不穩定,大規模的回歸測試不能依賴于外部服務,是以其需要依賴于虛拟的資料。但是依然要測一些外部的真實服務,為什麼呢?因為擔心外部服務的更新怎麼辦呢?那可能更新之後,服務的 Request 和 Response 的 Schema 改了,就會産生一個 Bug。現實中會把一些所謂的重要的場景,依然是跑真實的外部服務,這樣就算它的外部服務的 Schema 更改了,測試就可以在第一時間發現這個更改。
是以,這是一個最為經典和實用的模型。
4.4
Synthesize 模型
Synthesize 模型最主要解決的一個需求是根據不同的情況傳回動态的 Response 資料。
是以,這個時候其實是 Hoverfly 提供一種中間插件的功能,可以在開發一個基于 Python 或者 Java 的中間插件,當某個 Request 收到之後,可以對這個 Request 進行加密解密,進行一個特定的判斷,之後再傳回一個特定的 Response。
可以對 Request 進行判斷、處理,對 Response 進行一些特定的組合,并不是一個固定的值,或者說固定的某一到兩個值。
4.5
Modify 模型
Modify 模型要等待真正的 Request 收到後,才能将 Request 轉換為特定的内容,并發送給外部依賴,而外部依賴傳回到 Response,再傳回到特定的模式,以實作特定狀态的虛拟。
比如需要模拟一個 Request 裡面被加了某些東西,或者是做一些混淆,産生一些特定的用例,或者更改真實的 Response 中的某些資料等。
4.6
Diff 模型
Diff 模型相當于一個變異版的契約測試方案。首先當被測系統的 API 的時候,它會将依賴服務的傳回資料儲存起來。當下一次執行相同的測試用例的時候,它會把上一次的和本一次的依賴服務傳回的資料的進行比較。
如果下一次的和第一次存儲的的 Schema 有不一樣的,那這個時候 Hoverfly 會報警,并顯示出來兩次不一樣的内容。這個就相當于就做了一部分被測系統和依賴系統之間的一種被動的契約的檢查,雖然它不屬于一個完整契約測試方案,但是至少做了單邊的契約檢查。
為什麼要選擇 Hoverfly?
首先服務虛拟中心化,它是基于 Proxy 模型的,是以在它隻要加一台機器搭建一個服務就可以了。其次它是非侵入式的,它是不需要改動被測系統的代碼或者配置的,而隻需要改動 JVM 自己的 property 或者是作業系統的 Proxy 配置。然後其靈活性很高,它支援各種模型,使用非常友善。最後它是開源軟體,是以如果有特定的定制化需求,可以自己修改後供自己使用。
5
總結
随着傳統 Stub 和 Mock 服務技術的發展,以及微服務系統開發中對于服務測試的各種問題和需求,服務虛拟化孕育而生。服務虛拟化是對 Stub 以及 Mock 技術的提升和系統化,功能更為強大,進而可以更加容易使用和定制化,以便滿足服務測試的各種新需求,解決各種新出現的問題。