Skip to content

Commit 1b02391

Browse files
committed
Add more realistic test scenario and bump versions
1 parent 9ba5b4d commit 1b02391

File tree

4 files changed

+55
-18
lines changed

4 files changed

+55
-18
lines changed

build.sbt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ val keycloakVersion = "26.0.1"
1919
val sttpVersion = "3.10.1"
2020
val influxdbVersion = "7.1.0"
2121
val awsClientVersion = "2.25.32"
22-
val gatlingVersion = "3.12.0"
22+
val gatlingVersion = "3.13.1"
2323
val circeVersion = "0.14.8"
2424

2525
libraryDependencies ++= Seq(
26-
"org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.4",
26+
"org.scala-lang.modules" %% "scala-parallel-collections" % "1.1.0",
2727

2828
"org.apache.pekko" %% "pekko-stream" % pekkoVersion,
2929
"org.apache.pekko" %% "pekko-stream-typed" % pekkoVersion,
@@ -124,7 +124,7 @@ libraryDependencies ++= Seq(
124124
"org.testcontainers" % "localstack" % testContainersVersion,
125125
"org.testcontainers" % "clickhouse" % testContainersVersion,
126126

127-
"com.clickhouse" % "clickhouse-jdbc" % "0.6.1",
127+
"com.clickhouse" % "clickhouse-jdbc" % "0.6.5",
128128
"com.crobox.clickhouse" %% "client" % "1.2.2",
129129

130130
"org.opensearch" % "opensearch-testcontainers" % "2.0.1",
@@ -140,8 +140,8 @@ libraryDependencies ++= Seq(
140140
"org.jboss.spec.javax.ws.rs" % "jboss-jaxrs-api_2.1_spec" % "2.0.2.Final",
141141

142142
"org.postgresql" % "postgresql" % "42.7.4",
143-
"io.zonky.test.postgres" % "embedded-postgres-binaries-bom" % "16.4.0" % Test pomOnly(),
144-
"io.zonky.test" % "embedded-postgres" % "2.0.7" % Test,
143+
"io.zonky.test.postgres" % "embedded-postgres-binaries-bom" % "16.6.0" % Test pomOnly(),
144+
"io.zonky.test" % "embedded-postgres" % "2.1.0" % Test,
145145

146146
"org.scalatest" %% "scalatest" % "3.2.18" % Test,
147147
"org.apache.pekko" %% "pekko-testkit" % pekkoVersion % Test,

project/plugins.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.12.1")
44
//addDependencyTreePlugin
55

66
// https://docs.gatling.io/reference/integrations/build-tools/sbt-plugin
7-
addSbtPlugin("io.gatling" % "gatling-sbt" % "4.10.1")
7+
addSbtPlugin("io.gatling" % "gatling-sbt" % "4.10.2")

src/main/scala/akkahttp/ReverseProxy.scala

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ import scala.util.{Failure, Success}
4646
* Remarks:
4747
* - The target server selection is via the "Host" HTTP header
4848
* - Local/Remote target servers are designed to be flaky to show Retry/CircuitBreaker behavior
49-
* - On top of the built-in client, you may also try other clients
49+
* eg for Local adjust [[responseCodes]]
50+
* - On top of the built-in client, you may also try other clients, see below
5051
* - This PoC may not scale well, possible bottlenecks are:
5152
* - Combination of Retry/CircuitBreaker
5253
* - Round robin impl. with `requestCounter` means shared state
@@ -93,9 +94,12 @@ object ReverseProxy extends App {
9394
)
9495
)
9596

96-
localTargetServers(maxConnections = 5) // 1-1024
97+
// For Mode.local: Adjust to provoke more retries on ReverseProxy
98+
val responseCodes = List(200, 200, 200, 200, 200, 200, 200, 200, 500, 503)
99+
100+
localTargetServers(maxConnections = 100) // 1-1024
97101
reverseProxy()
98-
// Switch here to force ReverseProxy to forward requests to local or remote target server(s)
102+
// Switch here to force ReverseProxy to forward requests to local/remote target server(s)
99103
clients(nbrOfClients = 10, requestsPerClient = 10, Mode.local)
100104

101105
// HTTP client(s)
@@ -233,11 +237,9 @@ object ReverseProxy extends App {
233237
Thread.sleep(500)
234238
val id = request.getHeader("X-Correlation-ID").orElse(RawHeader("X-Correlation-ID", "N/A")).value()
235239

236-
// Adjust to provoke more retries on ReverseProxy
237-
val codes = List(200, 200, 200, 500, 500, 500)
238-
val randomResponse = codes(new scala.util.Random().nextInt(codes.length))
239-
logger.info(s"Target server: ${request.uri.authority.host}:${request.uri.effectivePort} got echo request with id: $id, reply with: $randomResponse")
240-
(StatusCode.int2StatusCode(randomResponse), Seq(RawHeader("X-Correlation-ID", id)))
240+
val randomResponseCode = responseCodes(new scala.util.Random().nextInt(responseCodes.length))
241+
logger.info(s"Target server: ${request.uri.authority.host}:${request.uri.effectivePort} got echo request with id: $id, reply with: $randomResponseCode")
242+
(StatusCode.int2StatusCode(randomResponseCode), Seq(RawHeader("X-Correlation-ID", id)))
241243
}
242244
}
243245

src/test/scala/ReverseProxySimulation.scala

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,45 @@ class ReverseProxySimulation extends Simulation {
3838
.exec(session => session.set("correlationId", session("correlationId").as[Int] + 1))
3939
}
4040

41-
setUp(
42-
scn.inject(
43-
atOnceUsers(10),
44-
rampUsers(50).during(30.seconds)
41+
// Adjust to scale load
42+
val loadFactorMorning = 0.01
43+
val loadFactorMidday = 0.02
44+
val loadFactorEvening = 0.03
45+
46+
val morningPeak = scenario("Morning Peak")
47+
.exec(scn)
48+
.inject(
49+
nothingFor(5.seconds), // initial quiet period
50+
rampUsers((20 * loadFactorMorning).toInt).during(10.seconds), // ramp up
51+
constantUsersPerSec(50 * loadFactorMorning).during(20.seconds), // peak load
52+
rampUsersPerSec(50 * loadFactorMorning).to(10 * loadFactorMorning).during(10.seconds), // ramp down
53+
constantUsersPerSec(10 * loadFactorMorning).during(10.seconds), // tail off
54+
nothingFor(30.seconds) // cool down period
55+
)
56+
57+
val middayPeak = scenario("Midday Peak")
58+
.exec(scn)
59+
.inject(
60+
nothingFor(5.seconds),
61+
rampUsers((20 * loadFactorMidday).toInt).during(10.seconds),
62+
constantUsersPerSec(50 * loadFactorMidday).during(20.seconds),
63+
rampUsersPerSec(50 * loadFactorMidday).to(10 * loadFactorMidday).during(10.seconds),
64+
constantUsersPerSec(10 * loadFactorMidday).during(10.seconds),
65+
nothingFor(30.seconds)
4566
)
67+
68+
val eveningPeak = scenario("Evening Peak")
69+
.exec(scn)
70+
.inject(
71+
nothingFor(5.seconds),
72+
rampUsers((20 * loadFactorEvening).toInt).during(10.seconds),
73+
constantUsersPerSec(50 * loadFactorEvening).during(20.seconds),
74+
rampUsersPerSec(50 * loadFactorEvening).to(10 * loadFactorEvening).during(10.seconds),
75+
constantUsersPerSec(10 * loadFactorEvening).during(10.seconds),
76+
nothingFor(30.seconds)
77+
)
78+
79+
setUp(
80+
morningPeak.andThen(middayPeak).andThen(eveningPeak)
4681
).protocols(httpProtocol)
4782
}

0 commit comments

Comments
 (0)