基于AMF协议的Flex应用程序的性能测试

接触过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!!!");

}

}

$new_page$

  如果以上连接测试成功之后,那么接下来的问题就好解决了,那就是模拟并发,对于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的通信机制描述难免有误。但这里并不只是记录如何实现一种压力测试,而是表达一种个人对于性能测试思想的理解,很多时候不要一味地去追求自动化工具的强大,而忽略了其性能测试本身的思想。希望能通过不断总结,来逐步提高自己!

时间: 2024-08-01 13:01:35

基于AMF协议的Flex应用程序的性能测试的相关文章

15.基于UDP协议的聊天室程序

使用UDP协议完成一个聊天室程序的小项目,大部分代码都有注释,一看就能看到的. 实现的功能:               (1)查看/显示已经登陆的用户信息               (2)向已登陆的用户发送消息               (3)输出错误消息,给予提示               (4)退出 共有三个文件: chat_public.h #ifndef _CHAT_PUB_H_ #define _CHAT_PUB_H_ //chat_public.h #include <lis

基于UDP协议的网络程序

下图是基于UDP协议的客户端/服务器程序的一般流程: 图1.1 UDP协议通信流程 UDP套接口是无连接的.不可靠的数据报协议: 既然他不可靠为什么还要用呢?其一:当应用程序使用广播或多播时只能使用UDP协议:其二:由于他是无连接的,所以速度快.因为UDP套接口是无连接的,如果一方的数据报丢失,那另一方将无限等待,解决办法是设置一个超时. 建立UDP套接口时socket函数的第二个参数应该是SOCK_DGRAM,说明是建立一个UDP套接口:由于UDP是无连接的,所以服务器端并不需要listen或

Java网络编程 - 基于UDP协议 实现简单的聊天室程序

最近比较闲,一直在抽空回顾一些Java方面的技术应用. 今天没什么事做,基于UDP协议,写了一个非常简单的聊天室程序. 现在的工作,很少用到socket,也算是对Java网络编程方面的一个简单回忆. 先看一下效果: 实现的效果可以说是非常非常简单,但还是可以简单的看到一个实现原理. "聊天室001"的用户,小红和小绿相互聊了两句,"聊天室002"的小黑无人理会,在一旁寂寞着. 看一下代码实现: 1.首先是消息服务器的实现,功能很简单: 将客户端的信息(进入了哪一个聊

基于XMPP协议聊天程序【Openfire+asmark】

    本文章提供了实现IM聊天程序最基础的配置和使用案例,可以实现点对点聊天.可做为入门阅读使用.文章转载请注明来源:http://blog.csdn.net/fengfeng91 一:搭建服务器: 官方网站下载openfire服务器安装.配置密码,权限,数据库(内置数据库或者添加外部数据库支持Mysql) 注意* 如果配置外部数据库,需先保证数据库服务已被开启,才能保证服务器开启. Windows环境下开启抛出异常/乱码时,关闭服务器,以管理员身份运行,当出现以下提示时,表示服务器启动成功.

基于XMPP协议的手机多方多端即时通讯方案

目   录 基于XMPP协议的手机多方多端即时通讯方案................................................................. 1 目   录.................................................................................................................... 2 一. 开发背景........................

基于TCP协议之——socket编程

一. 套接字(socket) socket英文为插座的意思,也就是为用户提供了一个接入某个链路的接口.而在计算机网络中,一个IP地址标识唯一一台主机,而一个端口号标识着主机中唯一一个应用进程,因此"IP+端口号"就可以称之为socket. 两个主机的进程之间要通信,就可以各自建立一个socket,其实可以看做各自提供出来一个"插座",然后通过连接上"插座"的两头也就是由这两个socket组成的socket pair就标识唯一一个连接,以此来表示网

第13章 TCP编程(3)_基于自定义协议的多进程模型

5. 自定义协议编程 (1)自定义协议:MSG //自定义的协议(TLV:Type length Value) typedef struct{ //协议头部 char head[10];//TLV中的T unsigned int checkNum; //校验码 unsigned int cbSizeContent; //协议体的长度 //协议体部 char buff[512]; //数据 }MSG; (2)自定义读写函数 ①extern int write_msg(int sockfd, cha

网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程

Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服务器进程B1同时为客户进程A1.A2和B2提供服务. Socket概述 ①   所谓Socket通常也称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过“套接字”向网络发出请求或者应答网络请求. ②   Socket是连接运行在网络上的两个程序间的双向通信的端点. ③  

第13章 TCP编程(4)_基于自定义协议的多线程模型

7. 基于自定义协议的多线程模型 (1)服务端编程 ①主线程负责调用accept与客户端连接 ②当接受客户端连接后,创建子线程来服务客户端,以处理多客户端的并发访问. ③服务端接到的客户端信息后,回显给客户端 (2)客户端编程 ①从键盘输入信息,并发送给服务端 ②接收来自服务端的信息 //msg.h与前一节相同 #ifndef __MSG_H__ #define __MSG_H__ #include <sys/types.h> //求结构体中成员变量的偏移地址 #define OFFSET(T