对移动应用后端API进行性能测试,不是简单模拟HTTP请求。要求测试工具能模拟移动网络的不稳定性、移动设备的资源限制以及真实用户的行为模式。
一,移动应用后端
和传统Web后端不同,移动后端面临:
网络环境多变:需要在Wi-Fi、4G/5G、弱网(高延迟、低带宽)间无缝切换,并处理频繁的断线重连。
用户行为:用户会话通常更短、更频繁(碎片化使用),并伴随特定的操作序列(如启动App->刷新内容->点赞->退出)。
API设计:大量使用短连接、推送通知、分页、数据同步和二进制协议(如Protocol Buffers)。
设备和系统碎片化:需处理海量设备标识、操作系统版本和推送Token。
二、 使用Gatling精准模拟移动网络特性
这是和桌面测试本质的区别。Gatling的throttling机制和连接管理是关键。
scala
import scala.concurrent.duration._
import io.gatling.core.Predef._
import io.gatling.http.Predef._
class MobileAPIPerformanceTest extends Simulation {
val httpProtocol = http
.baseUrl("https://your-api.com")
// 1. 模拟移动网络连接池特性:连接数少,生命周期短
.disableCaching // 移动App通常自主控制缓存
.maxConnectionsPerHost(10) // 模拟移动设备有限的并行连接数
.shareConnections // 更真实地复用连接
// 2. 设置全局超时,模拟移动用户耐心
.requestTimeout(5.seconds)
.connectTimeout(3.seconds)
val scn = scenario("模拟移动用户典型会话")
.exec(
http("启动App - 获取配置")
.get("/api/v1/config")
.header("User-Agent", "YourApp/1.0 (iPhone; iOS 15.4)")
.header("Device-ID", "${deviceId}") // 动态设备ID
)
.pause(2.seconds) // 模拟用户阅读时间
.exec(
http("刷新信息流")
.get("/api/v1/feed?page=1")
.header("Authorization", "Bearer ${authToken}")
.check(jsonPath("$.nextCursor").saveAs("nextCursor")) // 处理分页
)
// 3. 注入网络节流:模拟特定网络类型
.during(5.minutes) {
// 模拟不稳定的4G网络:下载100 Mbps,上传20 Mbps,高延迟
throttle(
reachRps(50).in(10.seconds), // 4G下请求速率可达50 RPS
holdFor(4.minutes),
jumpToRps(5), // 突然降至弱网状态
holdFor(50.seconds)
).exec(
http("弱网下提交操作")
.post("/api/v1/action")
.body(StringBody("""{"action": "like", "id": "${itemId}"}"""))
.expectation(
// 弱网下用户容忍更长的响应时间
responseTimeInMillis.percentile4.lt(3000) // P95响应时间<3秒
)
)
}
setUp(
scn.inject(
// 4. 模拟移动用户的启动潮汐:例如,早晨高峰
rampUsersPerSec(1).to(50).during(30.minutes),
constantUsersPerSec(50).during(2.hours),
rampUsersPerSec(50).to(1).during(30.minutes)
)
).protocols(httpProtocol)
// 5. 应用全局网络节流
.throttle(
// 模拟全球用户混合网络状况
reachRps(1000).in(1.minute), // 峰值吞吐
holdFor(3.hours),
jumpToRps(100), // 进入夜间低峰
holdFor(4.hours)
)
// 6. 定义断言:移动API性能标准通常更宽松但必须稳定
.assertions(
global.failedRequests.percent.lt(0.1), // 错误率<0.1%
global.responseTime.percentile4.lt(2000), // P95响应时间<2秒
details("弱网下提交操作").responseTime.percentile4.lt(3000)
)
}
三、模拟真实移动用户行为
移动用户行为具有场景化特征,需用更精细的场景设计来模拟。
scala
// 定义不同行为模式的用户群体
val regularUser = scenario("活跃用户")
.exec(Login.flow)
.exec(
// 模拟“下拉刷新->浏览->互动”的短周期循环
repeat(15) {
exec(Feed.refresh) // 刷新内容
.pause(1.second, 5.seconds) // 随机浏览时间
.randomSwitch(
60.0 -> exec(Interaction.like), // 60%概率点赞
20.0 -> exec(Interaction.comment), // 20%概率评论
20.0 -> exec(Interaction.share) // 20%概率分享
)
}
)
val backgroundUser = scenario("后台用户")
.exec(Login.flow)
.exec(
// 模拟后台静默同步:低频、定时的数据拉取
forever() {
exec(DataSync.sync)
.pause(5.minutes, 10.minutes) // 每5-10分钟同步一次
}
)
// 在setUp中混合不同用户群体,模拟真实用户构成
setUp(
regularUser.inject(rampUsers(5000).during(30.minutes)), // 70%为活跃用户
backgroundUser.inject(rampUsers(2000).during(30.minutes)) // 30%为后台用户
)
四、 测试移动API机制
移动API包含诸多特有机制,测试中必须包含。
scala
// 1. 测试Token认证和刷新机制
val authScenario = scenario("认证流程测试")
.exec(
http("初始登录")
.post("/auth/login")
.body(ElFileBody("bodies/login.json"))
.check(
jsonPath("$.access_token").saveAs("accessToken"),
jsonPath("$.refresh_token").saveAs("refreshToken"),
jsonPath("$.expires_in").saveAs("tokenExpiresIn")
)
)
.pause("${tokenExpiresIn}") // 模拟token自然过期
.exec(
http("自动刷新Token")
.post("/auth/refresh")
.body(StringBody("""{"refresh_token": "${refreshToken}"}"""))
.check(jsonPath("$.access_token").saveAs("accessToken"))
)
// 2. 模拟推送通知接收和点击(通过API调用模拟)
val pushScenario = scenario("推送互动测试")
.exec(
http("模拟接收推送")
.post("/api/v1/push/report-receipt")
.header("Authorization", "Bearer ${accessToken}")
.body(StringBody("""{"push_id": "${pushId}", "action": "received"}"""))
)
.pause(2.seconds, 30.seconds) // 用户看到推送后可能的延迟
.exec(
http("模拟点击推送")
.post("/api/v1/push/report-action")
.body(StringBody("""{"push_id": "${pushId}", "action": "clicked"}"""))
)
// 3. 测试数据同步和冲突解决
val syncScenario = scenario("数据同步测试")
.exec(
http("增量同步")
.get("/api/v1/sync/updates?last_sync=${lastSyncTime}")
.check(
jsonPath("$.updates").saveAs("updates"),
jsonPath("$.full_sync_required").saveAs("needsFullSync")
)
)
.doIf("${needsFullSync}") {
exec(http("全量同步").get("/api/v1/sync/full"))
}
五、 专项测试建议
后端和客户端指标关联:在测试中注入唯一的trace_id,便于在分布式追踪系统(如Jaeger)中关联客户端请求和后端全链路处理。
重点注意弱网和边缘情况:
高延迟测试:使用Gatling的throttling模拟高达1000ms的RTT。
丢包测试:虽然Gatling无法直接模拟丢包,但可结合TC(Traffic Control)等网络工具在测试机层面实现。
频繁重连测试:在场景中设计repeat循环,模拟App从后台唤醒后重新建立连接的行为。
设备资源模拟:
通过限制并发连接数、请求队列来模拟设备资源限制。
测试后端在客户端频繁崩溃重启(表现为连接突然断开)后的容错能力。
六、 通过标准
移动API的性能标准应结合业务实际制定:
成功率:关键API(如登录、支付)必须在99.9%以上。
端到端延迟:主要操作(如 feed 刷新)的P95响应时间,在良好网络下应<1秒,在弱网下应<3秒。
网络效率:关注单个请求的数据传输量,特别是在蜂窝网络下,避免不必要的冗余数据。
电池影响模拟:通过分析请求的频率和模式,评估后端API设计是否有利于省电(如使用批量操作、减少轮询)。