随着主流系統的服務化設計,特别是SOA架構和微服務架構的流行,接口已經成為各系統間通信的橋梁。是以,接口的性能壓測也變得越來越重要。 SOA(Server OrientedArchitecture,面向服務架構)是目前通用的元件模型。它将軟體系統的不同功能子產品(被稱為服務)通過接口的形式聯系起來。這裡的接口可以是具體的接口服務也可以是連接配接兩個子產品通信的中間件。一個大型項目通常是由多個系統開發組成的,每個系統都有專門的研發團隊來負責,單個系統的功能被稱作一個子產品。而子產品的功能是按背景的接口實作和UI呈現來劃分。 微服務架構在某種程度上是面向服務的架構SOA繼續發展的下一步。基本上,這種架構類型是開發軟體,網絡或移動應用程式作為獨立服務套件(又稱微服務)的一種特殊方式。這些服務的建立僅限于一個特定的業務功能,如使用者管理、使用者角色、電子商務車、搜尋引擎、社交媒體登入等。此外,它們是完全獨立的,也就是說它們可以寫入不同的程式設計語言并使用不同的資料庫。集中式服務管理幾乎不存在,微服務使用輕量級HTTP、REST或Thrift API進行通信。
獲得單接口/單業務容量
發現應用程式的性能瓶頸
發現資料庫的性能瓶頸
很多時候我們在設計接口性能壓測腳本需要調用系統接口平台,如果接口平台沒有提供可用的UI界面,那麼就需要我們自己寫代碼結合壓測工具連接配接接口平台,按照對應的協定調用接口。接口方法運作過程中需要調用很多依賴的方法。依賴方法不同的傳回内容也是需要考慮的。但是依賴接口内容我們是不可控的。有時候是依賴子產品不能正常運作,有時是依賴子產品還未開發完,有時是我們是客觀上無條件讓依賴子產品傳回想要的異常值。這時候我們在壓測的時候就需要Mock系統實作了,在Mock系統(擋闆)定義好接口相關資料後,填入目标傳回結果,就能模拟依賴接口傳回想要的内容 結合開源的性能測試工具Jmeter(本文隻講此工具),隻需要把URL通過模拟HTTP并發請求就可以得到對應的執行結果,再根據傳回結果判斷接口執行是否正确。 是以相對來說時間成本比較低,一個場景轉化成測試腳本也是比較簡單的事情。接口釋出上線後,參數很少發生變化。因為接口做為服務釋出後會有多個調用方,如果參數發生變化将通知所有調用方做響應的修改,否則将出現調用方無法使用的情況。接口定義穩定不太容易發生變化,是以接口性能壓測的後期維護工作也就不多。
類型
具體内容
效率(性能)
并發數、響應時間 、TPS、錯誤率、資源占用
穩定性
單使用者長時間下的反複操作、多使用者長時間并發操作、異常值下的長時間反複操作、最大故障時長
壓力
超規格負載下的規格内的處理
恢複性
負載正常後,系統是否正常恢複
目前主流系統的接口大緻可分為HTTP接口和自研RPC(Remote Procedure call,遠端過程調用)接口,而HTTP接口可能更為普遍一些。
一般壓測WEB系統都會接觸HTTP接口 常見有HTTP和HTTPS兩種協定
HTTP 超文本傳輸協定,預設80端口
HTTPS 安全超文本傳輸協定,可以了解為http協定的安全版,默443端口
HTTP常見兩種請求方法:GET和POST
與Server進行請求/響應時,兩種最常被用到的兩種方法
GET 從指定的資源請求資料
POST向指定的資源送出要被處理的資料
RPC(Remote Procedure Call Protocol)——遠端過程調用協定,它是一種通過網絡從遠端計算機程式上請求服務,而不需要了解底層網絡技術的協定。 其實簡單的說,就是象調用本地的類的方法樣來調用伺服器端的方法實作。 需要要對RMI(Remote Method Invoke,遠端方法調用)中的stu(樁)和skeleton(骨架)的概念有一點了解。RMI的代理模式是通過代理對象将方法傳遞給實際對象的。Stub駐留用戶端,承擔着代理遠端對象實作者的角色。skeleton類幫助遠端對象與sttub連接配接進行通信。
主要組成元素:
主要原理:
實體對象和業務接口由用戶端和服務端公用。 接口實作是由服務端對定義好的業務接口進行功能實作,并将接口執行個體注冊服務中提供給用戶端調用。
目前我們接觸到RPC接口主要有Hession、Dubbo、HTTP、Thrift、Hprose等
Hession、Dubbo、Thrift、Hprose都是遠端方法調用的一種實作,用戶端需要保留stub來調用接口。這就是為什麼我們性能壓測的時候需要Jmeter引用jar包。
Hession:是一個輕量級的remoting onhttp工具,使用簡單的方法提供了RMI的功能,遠端方法調用的一種,采用二進制RPC協定(基于Http協定),适合發送二進制資料,不适合複雜對象類型的傳輸。
Dubbo:阿裡巴巴開源的一個高性能優秀的服務架構,一個遠端方法調用的架構。Dubbo注冊中心負責服務位址的注冊和查找,相當于服務目錄:Dubbo監控中心負責統計各服務調用次數、調用時間
Thrift:facebook開源的一個可互操作和可伸縮服務的架構一個遠端方法調用的架構,可擴充且跨語言的服務的開發。允許你定義一個簡單的定義檔案中的資料類型和服務接口(IDL)。之後生成伺服器骨架和用戶端調用代理
Hprose:國人開發的一個遠端方法調用的開源架構。它是一個先進的輕量級的跨語言跨平台面向對象的高性能遠端動态通訊中間件。
HTTP:常見于WEB應用,基于HTTP協定傳輸文本。當一個URL發送請求時,服務端doGet或者doPost方法會被調用,擷取相應的參數。壓測HTTP接口時,隻需要通過定位URL接口并傳參斷言,相對比較簡單。
下面針對幾種接口簡要說明: Hession接口壓測:
通過接口URL擷取接口,如果複制接口定義及其自定義類,包名盡量跟開發包保持一緻,不建議使用直接複制代碼的方式,因為這樣不便于維護,使用Maven在pom檔案引入接口和Hessian依賴的jar包。通常借助HessianSpringFactoryBean擷取,再結合Jmeter自定義JAVA類請求和Stub的方式接入測試工具進行壓測
HessianProxy是hessian client處理用戶端請求的核心類,采用proxy模式,代理用戶端對遠端接口的調用,hessian client的主程式的時序圖如下:
Dubbo接口壓測測試:
如果通過Dubbo注冊中心擷取服務接口,那麼搭建測試環境的時候需要指定Dubbo注冊中心的位址,擴充Jmeter也需要配置Dubbo注冊中心位址以及對外提供服務的接口名稱。直連的方式在Jmeter需要導入Dubbo架構相關的JAR包。現在有現成的Jemter dubbo插件,直接引入即可
節點說明:
Provider:暴露服務的服務提供方
Consumer:調用遠端服務的服務消費方
Registry:服務注冊與發現的注冊中心
Monitor:統計服務調用次數和服務調用時間的監控中心
Container:服務運作容器
Jemter Dubbo插件位址:https://github.com/dubbo/jmeter-plugins-dubbo
Jemter DubboSample截圖
Thrift接口壓測:
通過Stub駐留用戶端調用用接口描述語言來寫接口(IDL),生成伺服器skeleton(骨架)類和用戶端調用代理,skeleton類幫助遠端對象與sttubb駐留用戶端連接配接進行通信,用戶端和伺服器端是緊耦合在一起的,你不能單獨修改任何一端的接口(不是說伺服器端代碼的實作),伺服器和用戶端傳遞的資料類型是嚴格比對的
具體的方法可以參照下面這篇文章:
性能工具之Jmeter壓測Thrift RPC服務
Hprose接口壓測:
由服務端對定義好的業務接口進行功能實作,并将接口執行個體注冊服務中提供給用戶端調用。本地的函數和方法作為服務釋出,而用戶端通過可以根據自己的需要來定義調用接口,或者直接調用伺服器端的函數或方法。再結合Jmeter自定義JAVA類請求和Stub的方式接入測試工具進行壓測。
HTTP接口壓測:
相對來說最簡單,通過Jmeter HTTP Request Sampel并發調用接口斷言即可
總之,接口壓測測試方法因架構不同其實作請求壓測有所差異,但總的來說都是擷取接口,并發請求,參數化資料,執行腳本,斷言結果,監控資料這些步驟。
下面來做兩個實踐小例子
首先介紹下什麼叫Mock?
此處引用淘寶網《接口測試白皮書》中的對mock的定義:
mock 是指使用各種技術手段模拟出各種需要的資源以供測試使用。 被mock的資源通常有以下特征: 被測目标依賴該資源 該資源可能因為各種原因不穩定、傳回結果不斷變化或者并不總是能夠擷取到 該資源跟被測目标本身品質無關 這些資源可能是一個外部或底層接口、一個系統、一組資料對象或者是一整套目标軟體的工作環境等。通過mock避免對外部真實資源的依賴實作對被測目标的孤立測試,進而大大降低測試的難度,節約測試成本。 需要注意的是利用mock通過的測試與使用真實環境通過的測試畢竟還是有一定差别的。有些時候我們就是需要所測試的系統能夠處理依賴所産生的各種情況,包括正常情況和異常情況,我們同樣不能保證我們的mock 可以模拟到每種這樣的情況。是以隻在确實有必要的情況下才運用mock。
Moco
簡單來說Moco就是類似一個mock的工具架構,下載下傳就是一個JAR包
在Moco的github上面有這段話。
Integration, especially based on HTTP protocol, e.g. web service, REST etc, is wildly used in most of our development. In the old days, we just deployed another WAR to an application server, e.g. Jetty or Tomcat etc. As we all know, it's so boring to develop a WAR and deploy it to any application server, even if we use an embeded server. And the WAR needs to be reassembled even if we just want to change a little bit.
翻譯過來:
內建,特别是基于HTTP協定的內建,例如web服務、REST等,在我們的大多數開發中都被廣泛使用。 在過去,我們隻是将另一場WAR包部署到應用伺服器上,例如Jetty或Tomcat等。衆所周知,開發一個WAR包并将其部署到任何應用伺服器上是非常枯燥的,即使我們使用的是嵌入式伺服器。war包也需要被重新打包即使我們隻是想稍微改變一下。
簡單來說,Moco就是解決了開發前端時沒有後端支援,開發接口時依賴沒有到位的尴尬場景。當然Moco的靈活性,讓其有越來越多的應用場景,比如我們在開發接口性能壓測腳本的時候。
特點:
隻需要簡單的配置request、response等即可滿足要求,支援http、https、socket。可以說是非常的靈活性。
支援在request 中設定 Headers , Cookies , StatusCode等。
對GET、POST、PUT、DELETE等請求方式均支援,很适合web開發。
無需環境配置,有java環境即可。
修改配置後,立刻生效。隻需要維護接口,也就是契約即可。
對可能用到的資料格式都支援,如json、text、xml、file等。
還能與其他工具內建,如Junit、Maven、Gradle等。
foo.json配置示例:
加載配置啟動Moco HTTP Server
Github位址:https://github.com/dreamhead/moco
此處示例均隻設定一個線程
startupGet.json配置檔案:
Jmeter設定Cookies
name字段為一個cookie的名稱。
value字段為一個cookie的值。
domain字段為可以通路此cookie的域名,本機為localhost
非頂級域名,如二級域名或者三級域名,設定的cookie的domain隻能為頂級域名或者二級域名或者三級域名本身,不能設定其他二級域名的cookie,否則cookie無法生成。
Jmeter設定HTTP GET Request
注意,查詢字元串(名稱/值對)是在 GET 請求的 URL 中發送的:
/7dget?name1=value1&name2=value2
Jmeter接受的Response結果
正确接受到服務端的傳回資訊
Jmeter設定headers
Jmeter設定HTTP POST Request
注意此次參數的格式是JOSN格式,是在消息主體中發送的。
根據我們的配置,服務端傳回的是一個Json格式的傳回資料