接觸過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的通信機制描述難免有誤。但這里并 不只是記錄如何實現一種壓力測試,而是表達一種個人對于性能測試思想的理解,很多時候不要一味地去追求自動化工具的強大,而忽略了其性能測試本身的思想。 希望能通過不斷總結,來逐步提高自己!