Gatling中Feeders的使用,这些Feeders用于在性能测试中提供数据驱动能力。我们将覆盖CSV、JSON、JDBC和Redis数据源,并提供详细的代码示例和解释。
1. Feeders概述
Feeders在Gatling中用于为虚拟用户提供测试数据。它们是一种数据源,可以在模拟运行过程中为每个用户提供不同的数据。Feeder本质上是一个迭代器,它返回键值对,这些键值对可以注入到Session中。
2. CSV Feeder
CSV Feeder从CSV文件中读取数据。每行是一个记录,每个记录是一个Map,键是CSV的列名。
基本用法
假设我们有一个名为users.csv的文件,内容如下:
csv
id,username,password
1,user1,pass1
2,user2,pass2
3,user3,pass3
在Gatling中,我们可以这样使用:
scala
val csvFeeder = csv("users.csv").circular
val scn = scenario("CSV Feeder Test")
.feed(csvFeeder)
.exec(http("Get user by ID")
.get("/user/${id}")
.check(status.is(200)))
循环策略
circular: 循环使用数据,当到达文件末尾时,从第一行重新开始。
random: 随机选择一行。
shuffle: 打乱顺序然后循环。
queue: 按顺序使用,每个用户获取下一行,如果到达末尾则失败。
3. JSON Feeder
JSON Feeder从JSON文件中读取数据。JSON文件应该是一个数组,每个元素是一个对象。
基本用法
假设我们有一个名为users.json的文件,内容如下:
json
[
{
"id": 1,
"username": "user1",
"password": "pass1"
},
{
"id": 2,
"username": "user2",
"password": "pass2"
}
]
在Gatling中,我们可以这样使用:
scala
val jsonFeeder = jsonFile("users.json").circular
val scn = scenario("JSON Feeder Test")
.feed(jsonFeeder)
.exec(http("Get user by ID")
.get("/user/${id}")
.check(status.is(200)))
4. JDBC Feeder
JDBC Feeder从数据库中读取数据。需要配置数据库连接。
基本用法
首先,在build.sbt中添加数据库驱动依赖,例如MySQL:
scala
libraryDependencies += "mysql" % "mysql-connector-java" % "8.0.33"
然后,在Gatling中配置JDBC Feeder:
scala
val jdbcFeeder = jdbcFeeder(
"jdbc:mysql://localhost:3306/test",
"username",
"password",
"SELECT id, username, password FROM users"
)
val scn = scenario("JDBC Feeder Test")
.feed(jdbcFeeder)
.exec(http("Get user by ID")
.get("/user/${id}")
.check(status.is(200)))
5. Redis Feeder
Redis Feeder从Redis中读取数据。Gatling不直接支持Redis Feeder,但我们可以通过编写自定义Feeder来实现。
自定义Redis Feeder
首先,添加Redis客户端依赖,例如lettuce-core:
scala
libraryDependencies += "io.lettuce" % "lettuce-core" % "6.2.4.RELEASE"
然后,我们可以创建一个自定义Feeder:
scala
import io.lettuce.core._
import io.lettuce.core.api.sync._
import scala.collection.JavaConverters._
def redisFeeder(redisUri: String, keyPattern: String): Feeder[String] = {
val redisClient = RedisClient.create(redisUri)
val connection = redisClient.connect()
val commands = connection.sync()
// 假设我们从Redis中获取一个列表,然后循环使用
val keys = commands.keys(keyPattern).asScala.toList
val iterator = keys.iterator
feeder[String] { _ =>
if (iterator.hasNext) {
val key = iterator.next()
// 这里我们假设存储的是String,根据实际情况调整
val value = commands.get(key)
Map("redisKey" -> key, "redisValue" -> value)
} else {
Map.empty
}
}.circular
}
// 使用自定义Redis Feeder
val redisFeeder = redisFeeder("redis://localhost:6379", "user:*")
val scn = scenario("Redis Feeder Test")
.feed(redisFeeder)
.exec(http("Get user by ID")
.get("/user/${redisValue}")
.check(status.is(200)))
注意:这只是一个示例,实际使用时需要根据Redis中数据的存储结构和需要的数据进行调整。
6. 自定义Feeder
如果内置的Feeder不满足需求,我们可以自定义Feeder。自定义Feeder是一个返回Iterator[Map[String, T]]的函数,其中T是任何类型。
示例:随机生成数据
scala
val randomEmailFeeder = Iterator.continually(
Map("email" -> (s"user${java.util.UUID.randomUUID()}@example.com"))
)
val scn = scenario("Random Email Feeder Test")
.feed(randomEmailFeeder)
.exec(http("Register user")
.post("/register")
.formParam("email", "${email}")
.check(status.is(200)))
7. 数据源策略与性能考虑
循环方式:保证每个虚拟用户都能获得唯一的数据,避免重复。
数据量:如果测试需要大量数据,确保数据源能够快速提供数据,避免成为瓶颈。
连接管理:对于JDBC和Redis等外部数据源,注意连接的管理和释放,避免资源泄露。
8. 综合示例
下面是一个综合使用多种Feeder的示例:
scala
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
class FeederSimulation extends Simulation {
val httpProtocol = http
.baseUrl("http://localhost:8080")
.acceptHeader("application/json")
// CSV Feeder
val csvFeeder = csv("users.csv").queue
// JSON Feeder
val jsonFeeder = jsonFile("users.json").random
// JDBC Feeder
val jdbcFeeder = jdbcFeeder(
"jdbc:mysql://localhost:3306/test",
"user",
"password",
"SELECT id, username FROM users WHERE status = 'active'"
)
// 自定义Redis Feeder(假设我们已经定义了上面的redisFeeder函数)
val redisFeeder = redisFeeder("redis://localhost:6379", "user:*")
val scn = scenario("Multiple Feeder Test")
.feed(csvFeeder)
.feed(jsonFeeder)
.feed(jdbcFeeder)
.feed(redisFeeder)
.exec(http("Complex Request")
.post("/complex")
.formParam("csvId", "${id}") // 来自CSV
.formParam("jsonUsername", "${username}") // 来自JSON
.formParam("jdbcId", "${id}") // 来自JDBC
.formParam("redisKey", "${redisKey}") // 来自Redis
.check(status.is(200)))
setUp(
scn.inject(
rampUsers(100) during (10 seconds)
)
).protocols(httpProtocol)
}
注意:在实际测试中,不建议同时使用多个Feeder,除非有特殊需求。通常一个测试场景使用一种数据源即可。
9. 总结
Gatling的Feeders提供了灵活的数据驱动测试能力。我们可以根据测试需求选择合适的数据源和策略。对于不满足内置Feeder的情况,我们可以通过自定义Feeder来扩展。