如何为Gatling中asLongAs循环的重试请求设置超时?
asLongAs Loop for Polling a REST Endpoint Great question! When using Gatling's asLongAs for polling a service until you get a result, you don’t have to rely on infinite loops—there are two clean ways to add a timeout. Let’s adapt your code with both approaches:
Option 1: Use asLongAs's Built-in maxDuration Parameter
Gatling’s asLongAs has an overloaded method that accepts a maxDuration parameter, which is the easiest way to set a hard timeout for your polling loop. You’ll need to import Scala’s duration utilities to use readable time units like seconds.
Modified Code
First, add the import at the top of your file:
import scala.concurrent.duration._
Then update your scenario:
scenario("my-scenario") .feed(feeder) .exec( http("post-to-A") .post("/execution") .body(StringBody( """{ | "information": ${INFORMATION} |}""".stripMargin )) .asJSON .check(status.is(200)) ) .exec(_.set("result", "")) // Set a 60-second timeout; loop stops either when result is non-empty OR 60s passes .asLongAs(session => session("result").validate[String].get != "", maxDuration = 60 seconds) { exec( http("get-to-B") .get("/result") .check(status.is(200)) .check(jsonPath("$.result").saveAs("result")) ) // Add a pause to avoid overwhelming Service B with too-frequent requests .pause(1 second) } // Optional: Handle the timeout case after the loop ends .exec(session => { val result = session("result").validate[String].get if (result.isEmpty) { // Log or mark the session as timed out for reporting session.set("polling_timed_out", true) } session })
How It Works
- The
maxDuration = 60 secondstells Gatling to terminate the loop after 60 seconds, regardless of whether theresultis still empty. - Adding a
pauseis crucial to prevent your test from flooding Service B with requests—adjust the duration based on how quickly you expect the result to be ready.
Option 2: Manually Track Poll Start Time (For Custom Logic)
If you need more control (e.g., combining timeout with max retry count), you can track the start time of your polling in the session and add a time check to your loop condition.
Modified Code
scenario("my-scenario") .feed(feeder) .exec( http("post-to-A") .post("/execution") .body(StringBody( """{ | "information": ${INFORMATION} |}""".stripMargin )) .asJSON .check(status.is(200)) ) // Save the current timestamp when polling starts .exec(session => session.set("poll_start_time", System.currentTimeMillis())) .exec(_.set("result", "")) // Loop only if result is empty AND we haven't exceeded 60 seconds .asLongAs(session => { val result = session("result").validate[String].get val startTime = session("poll_start_time").validate[Long].get val elapsedTime = System.currentTimeMillis() - startTime result.isEmpty && elapsedTime < 60000 // 60000ms = 60 seconds }) { exec( http("get-to-B") .get("/result") .check(status.is(200)) .check(jsonPath("$.result").saveAs("result")) ) .pause(1 second) }
How It Works
- We store the start time of the polling phase in the session.
- The loop condition now checks two things: whether the
resultis still empty, and whether less than 60 seconds have passed since polling started. - This approach lets you add extra logic (like counting retries) alongside the timeout check if needed.
Key Notes
- Adjust Timings: Tweak the
maxDurationor elapsed time threshold to match your service’s expected execution time. - Reporting: Use the optional post-loop
execblock to mark timed-out sessions, which you can then analyze in Gatling’s test reports. - Avoid Over-Polling: Always include a
pausebetween polling requests to be kind to your target service.
内容的提问来源于stack exchange,提问作者riccardo.cardin

