当前位置: 首页 > 工具软件 > Gatling > 使用案例 >

Gatling:Feeders

谢鸿飞
2023-12-01

目录

Feeders

策略

使用数组和列表

基于文件的feeders

CSV Feeders

加载模式

压缩文件

分布式文件(仅限 Gatling Enterprise)

JSON Feeders

JDBC Feeder

站点地图(Sitemap)feeders

Redis Feeder

转换记录

加载内存中的所有记录


Feeders

        从外部源(例如 CSV 文件)将数据注入您的虚拟用户
        Feeder 是 Iterator<Map<String, T>> 的类型别名,意思是 feed 方法创建的组件会轮询 Map<String, T> 记录并注入其内容。
        构建一个自定义的非常简单。 例如,以下是构建随机电子邮件生成器的方法:

import scala.util.Random

val feeder = Iterator.continually {
  Map("email" -> s"${Random.alphanumeric.take(20).mkString}@foo.com")
}

结构 DSL 提供了一个 feed 方法,可以在与 exec 相同的地方调用。

feed(feeder)

        这定义了一个工作流程步骤,其中每个虚拟用户都在同一个 Feeder 上提供内容。虚拟用户每到这一步,就会从Feeder中弹出一条记录,注入到用户的Session中,产生一个新的Session实例。 也可以一次输入多条记录。 在这种情况下,值将是包含同一键的所有值的数组。

策略

Gatling 为内置feeders提供多种策略:

// 默认行为:在底层序列上使用迭代器
csv("foo").queue()

// 随机选择序列中的一个条目
csv("foo").random()

// 洗牌改组条目,然后表现得像队列
csv("foo").shuffle()

// 到达终点后返回序列的顶部
csv("foo").circular()

        使用默认队列或随机播放策略时,请确保您的数据集包含足够的记录。 如果您的feeders用完记录,gatling将自动关闭。

使用数组和列表

Gatling 提供了一些转换器来使用内存中的数据结构作为 Feeder。

// 使用数组(隐式转换)
Array(
  Map("foo" -> "foo1", "bar" -> "bar1"),
  Map("foo" -> "foo2", "bar" -> "bar2"),
  Map("foo" -> "foo3", "bar" -> "bar3")
).random


// 使用 IndexedSeq(隐式转换)
IndexedSeq(
  Map("foo" -> "foo1", "bar" -> "bar1"),
  Map("foo" -> "foo2", "bar" -> "bar2"),
  Map("foo" -> "foo3", "bar" -> "bar3")
).random

基于文件的feeders

        Gatling 提供各种基于文件的feeders。 使用捆绑分发时,文件必须位于 user-files/resources 目录中。 此位置可以被覆盖,请参阅 [configuration`。 使用 maven、gradle 或 sbt 等构建工具时,文件必须放在 src/main/resources 或 src/test/resources 中。
        为了定位文件,Gatling 依次尝试以下策略:作为来自类路径根的类路径资源,例如 data/file.csv 用于定位 your_project/src/main/resources/data/file.csv 文件。 这是推荐的策略。
        作为文件的绝对文件系统路径。 如果您希望单独部署feeders文件,请使用此策略。
        不要使用相对文件系统路径,例如 src/main/resources/data/file.csv,而是使用类路径路径 data/file.csv。

CSV Feeders

        Gatling 提供了几个用于读取字符分隔值文件的内置插件。 我们的解析器遵循 RFC4180 规范。 唯一的区别是标题字段被修剪掉了包装空白。

// 使用逗号分隔符
csv("foo.csv")

// 使用制表分隔符
tsv("foo.tsv")

// 使用分号分隔符
ssv("foo.ssv")

// 使用自定义分隔符
separatedValues("foo.txt", '#')

加载模式

        CSV 文件馈送器提供了几种数据应如何加载到内存中的选项。在模拟开始之前,eager 将整个数据加载到内存中,从而节省了运行时的磁盘访问。 此模式最适用于可以快速解析而不会延迟模拟开始时间并且可以轻松存放在内存中的相当小的文件。 此行为是 Gatling 3.1 之前的默认行为,您仍然可以强制加载它

csv("foo.csv").eager

        批处理更适用于解析会延迟模拟开始时间并占用大量堆空间的大文件。 然后按块读取数据。在批处理模式下,random 和 shuffle 当然不能对全部库存进行操作,而只能对记录的内部缓冲区进行操作。 此缓冲区的默认大小为 2,000,并且可以更改

// 使用默认缓冲区大小 (2000 lines)
csv("foo.csv").batch
// 调整内部缓冲区大小
csv("foo.csv").batch(200)

        默认行为是基于(解压缩,分片)文件大小的自适应策略,请参阅配置文件中的 gatling.core.feederAdaptiveLoadModeThreshold。 Gatling 将使用低于阈值的渴望和高于阈值的批处理。

压缩文件

        如果您的文件非常大,您可以提供压缩文件并要求 gatling 即时解压缩它们:

csv("foo.csv.zip").unzip

        支持的格式是 gzip 和 zip(但存档必须只包含一个文件)。

分布式文件(仅限 Gatling Enterprise)

        如果您想与 Gatling Enterprise 一起运行分布式并且希望分发数据,以便用户在不同集群节点上运行时不会使用相同的数据,您可以使用 shard 选项。 例如,如果您有一个包含 30,000 条记录的文件部署在 3 个节点上,则每个节点将使用 10,000 条记录切片。
        shard 仅在与 Gatling Enterprise 一起运行时有效,否则它不起任何作用。

csv("foo.csv").shard

JSON Feeders

有些人可能希望使用 JSON 格式的数据而不是 CSV:

​jsonFile("foo.json")
jsonUrl("http://me.com/foo.json")

例如,以下 JSON:

[
 {
    "id":19434,
    "foo":1
  },
  {
    "id":19435,
    "foo":2
  }
]

会变成:

Map("id" -> 19434, "foo" -> 1) // record #1
Map("id" -> 19435, "foo" -> 2) // record #2

请注意,根元素当然必须是一个数组。

JDBC Feeder

Gatling 还提供了一个从 JDBC 连接读取的内置函数。

// 注意:您需要导入 jdbc 模块
import io.gatling.jdbc.Predef._

jdbcFeeder("databaseUrl", "username", "password", "SELECT * FROM users")

        就像 File parser built-ins 一样,它返回一个 RecordSeqFeederBuilder 实例。databaseUrl 必须是 JDBC URL(例如 jdbc:postgresql:gatling),用户名和密码是访问数据库的凭据,sql 是获取所需值的查询。仅支持 JDBC4 驱动程序,因此它们会自动注册到 DriverManager。

不要忘记在类路径中添加所需的 JDBC 驱动程序 jar(包中的 lib 文件夹)

站点地图(Sitemap)feeders

 Gatling 支持从站点地图文件读取数据的feeders。

// 注意:您需要导入 http 模块
import io.gatling.http.Predef._

sitemap("/path/to/sitemap/file")

以下站点地图文件:

​
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>http://www.example.com/</loc>
    <lastmod>2005-01-01</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.8</priority>
  </url>
  <url>
    <loc>http://www.example.com/catalog?item=12&desc=vacation_hawaii</loc>
    <changefreq>weekly</changefreq>
  </url>
  <url>
    <loc>http://www.example.com/catalog?item=73&desc=vacation_new_zealand</loc>
    <lastmod>2004-12-23</lastmod>
    <changefreq>weekly</changefreq>
  </url>
</urlset>

会变成:

// record #1
Map(
  "loc" -> "http://www.example.com/",
  "lastmod" -> "2005-01-01",
  "changefreq" -> "monthly",
  "priority" -> "0.8"
)
// record #2
Map(
  "loc" -> "http://www.example.com/catalog?item=12&amp;desc=vacation_hawaii",
  "changefreq" -> "weekly"
)
// record #3
Map(
  "loc" -> "http://www.example.com/catalog?item=73&amp;desc=vacation_new_zealand",
  "lastmod" -> "2004-12-23",
  "changefreq" -> "weekly"
)

Redis Feeder

此功能最初由 Krishnen Chedambarum 贡献。
Gatling 可以使用以下 Redis 命令之一从 Redis 读取数据。
        LPOP - 删除并返回列表的第一个元素
        SPOP - 从集合中移除并返回一个随机元素
        SRANDMEMBER - 从集合中返回一个随机元素
        RPOPLPUSH - 返回列表的最后一个元素并作为第一个元素存储到另一个列表
默认情况下,RedisFeeder 使用 LPOP 命令:

// 注意:你需要导入 redis 模块
import io.gatling.redis.Predef._
import com.redis._

val redisPool = new RedisClientPool("localhost", 6379)

// 使用一个列表,所以每条记录只有一个值,这里命名为“foo”
// 与redisFeeder(redisPool, "foo").LPOP相同
redisFeeder(redisPool, "foo")

然后,您可以覆盖所需的 Redis 命令:

// 使用 SPOP 命令从名为“foo”的集合中读取数据
redisFeeder(redisPool, "foo").SPOP

// 使用 SRANDMEMBER 命令从名为“foo”的集合中读取数据
redisFeeder(redisPool, "foo").SRANDMEMBER

您可以使用与 RPOPLPUSH 相同的键来创建循环进纸器

// 使用 RPOPLPUSH 命令从名为“foo”的列表中读取数据,并以原子方式存储在名为“bar”的列表中
redisFeeder(redisPool, "foo", "bar").RPOPLPUSH

// 与上面相同,但我们使用相同的键创建一个循环列表
redisFeeder(redisPool, "foo", "foo").RPOPLPUSH();

转换记录

        有时,您可能想要转换从feeder获得的原始数据。 例如,一个 csv feeder只会给您字符串,但您可能希望将其中一个属性转换为 Int。 转换需要: 在 Java 和 Kotlin 中,BiFunction<String, T, Object> 在 Scala 中,PartialFunction[(String, T), Any] 仅针对您要转换的记录定义,其他记录保持原样 例如:

csv("myFile.csv").transform {
  case ("attributeThatShouldBeAnInt", string) => string.toInt
}

加载内存中的所有记录

有时,您可能只想重复使用或方便的内置feeder以满足自定义需求并获得实际记录。

val records: Seq[Map[String, Any]] = csv("myFile.csv").readRecords

请注意,每个 readRecords 调用都会读取底层源,例如解析 CSV 文件。

参考:Gatling

 类似资料:

相关阅读

相关文章

相关问答