接觸過Flex應用的,基本上對於其表現層的視覺效果都是非常讚賞的,也正是由於其華麗的外表掩蓋了其諸多內在的缺陷,比如說響應速度、記憶體流失等等效能問題,對於大部分的Flex開發程式員或者是測試人員都是非常頭痛的事情。本人最近就碰到基於Flex應用程式的效能測試,由於它本身的特殊性,通訊組建、協議基本上都是Adobe自己開發的,所以基本上通用的測試載入器對他支援都是不太理想的。通過一系列的摸索,最終還是得把注意力轉移到Flex本身上來,全面去解析AMF協議,其實AMF協議還是走HTTP協議的,但從執行效率上來說,我們不能單純通過HTTP協議來類比其執行過程,因為中間必須要走AMF協議,雖然LoadRunner也有支援AMF協議,但AMF本身是需要Flash
Player來支援,錄製得到的指令碼,不易於理解和分析,我們無法很好分析其執行過程,而且它封包和解包都是二進位格式,如果以這種方案去執行,我們就需要解析它每一次封包和解包過程,相當於要去深入到AMF協議包解析過程,這樣就把簡單的問題複雜化。本身對於C/S應用程式的效能測試,最大的問題就是資料包解析,通過LoadRunner去壓測,就可能要面臨丟包的情況。所以通常情況下,我們為了保證協議資料包傳輸的完整性,盡量去避開直接去與協議資料包打交道,而且是通過上層的封裝方式進行請求,而不去幹預內在的複雜過程,這樣就既能保證資料轉送的完整性,同時也保證與商務邏輯實現方式的一致性,達到真實環境的壓測方案。
下面我們將具體瞭解哈AMF協議,並通過類比Client與Server實現AMF協議通訊的串連方式來完成大並發的壓力測試。
AMF是Adobe獨家開發出來的通訊協定,它採用二進位壓縮,序列化、還原序列化、傳輸資料,從而為Flash 播放器與Flash Remoting網關通訊提供了一種輕量級的、高效能的通訊方式。
類比AMF請求與Server端建立通訊,Adobe官方提供了一個Server端的通訊服務就是BlazeDS,Flex將資料通過AMF協議轉換成二進位格式進行傳輸給Server端的BlazeDS服務,然後BlazeDS再將資料解析成Java需要的格式,完成Flex用戶端與Server端的通訊過程。因此通過進一步分析發現,我們的目的就是要類比AMF與BlazeDS建立串連,就解決了問題了。這裡,就是利用Java來類比AMF請求,通過AMFConnection串連Blazeds介面,具體Demo代碼如下:
package org.test.service.TestLogin;import flex.messaging.io.amf.client.AMFConnection;import flex.messaging.io.amf.client.exceptions.ClientStatusException;import flex.messaging.io.amf.client.exceptions.ServerStatusException;public class AMFDemo { public static void main(String[] args) { // 建立AMF串連 AMFConnection amfCon = new AMFConnection(); //串連 remote URL String url = "http://localhost:8080/TestLogin/messagebroker/amf" ; try{ amfCon.connect(url); }catch(ClientStatusException cse){ System.out.println(cse); return ; } TestLogin result ; try{ result = (TestLogin)amfCon.call("TestLogin.login","username","passwd");//傳輸對象的參數,登入使用者、密碼 }catch(ClientStatusException ce){ System.out.println(ce); }catch(ServerStatusException se){ System.out.println(se); } amfCon.close(); System.out.println("Sucessfull!!!"); }}如果以上串連測試成功之後,那麼接下來的問題就好解決了,那就是類比並發,對於Java來說,那就是多線程的事兒了,通過多線程來控制實現並發使用者量,完成BlaseDS介面的壓力測試。多線程代碼實現如下:
package org.test.service.TestLogin;import flex.messaging.io.amf.client.AMFConnection;import flex.messaging.io.amf.client.exceptions.ClientStatusException;import flex.messaging.io.amf.client.exceptions.ServerStatusException;public class AMFDemo implements Runnable{ public void run(){ // 建立AMF串連 AMFConnection amfCon = new AMFConnection(); //串連 remote URL String url = "http://localhost:8080/TestLogin/messagebroker/amf" ; try{ amfCon.connect(url); }catch(ClientStatusException cse){ System.out.println(cse); return ; } //迴圈100次 for(int i=0; i<100; i++){ TestLogin result ; try{ Thread.sleep(1000L); long TestStart = System.currentTimeMillis(); result = (TestLogin)amfCon.call("TestLogin.login","username","passwd");//傳輸對象的參數,登入使用者、密碼 System.out.println("login:" + (System.currentTimeMillis() - TestStart));//列印出登入的回應時間 }catch(ClientStatusException ce){ System.out.println(ce); }catch(ServerStatusException se){ System.out.println(se); }catch (final InterruptedException e) { e.printStackTrace(); } } amfCon.close(); System.out.println("Sucessfull!!!"); }} public class AMFDemoTest { //建立100個線程 public static void main(String[] args) throws Exception { for (int i = 0; i < 100; i++) { Runnable runnable = new AMFDemo(); new Thread(runnable).start(); } }}
通過Java類比AMF請求與BlazeDS建立通訊串連,完成基於AMF協議的Flex應用程式的壓力測試,拋棄傳統的工具壓測方式,從而尋找最適合FLex本身的效能測試方案。當然,這個只是一種純程式碼方式來實現,我們也可以藉助通用工具來完成,至少在完成以上的代碼實現過程,之後可以通過LoadRunner或者是JMeter來調用Java程式碼完成,不過似乎JMeter對於Java支援更方便。使用工具的目的其實為了採樣壓力測試的資料方便分析,而真正實現壓力測試,其實不管是工具還是指令碼,其實都是通過類比底層的互動方式來達到同樣的目的。
作為一名測試人員,對於Java與Flex的通訊方式的理解遠不如開發人員,所以可能以上對於BlazeDS的通訊機制描述難免有誤。但這裡並不只是記錄如何?一種壓力測試,而是表達一種個人對於效能測試思想的理解,很多時候不要一味地去追求自動化工具的強大,而忽略了其效能測試本身的思想。希望能通過不斷總結,來逐步提高自己!