From 24b4cc4eb5a80ae63e0387377b9f44fd48d2d51e Mon Sep 17 00:00:00 2001 From: tjq Date: Sun, 8 Jan 2023 19:34:44 +0800 Subject: [PATCH] feat: use gatling to have a presure test for remote framework --- powerjob-common/pom.xml | 2 +- .../powerjob-remote-benchmark/pom.xml | 54 ++++++++ .../benchmark/PressureTestController.java | 26 +++- .../src/test/java/Engine.java | 20 +++ .../src/test/java/IDEPathHelper.java | 30 +++++ .../powerjob/remote/benchmark/Constant.java | 14 ++ .../remote/benchmark/HttpSimulation.java | 35 +++++ .../src/test/resources/gatling.conf | 127 ++++++++++++++++++ .../powerjob-remote-impl-akka/pom.xml | 2 +- 9 files changed, 307 insertions(+), 3 deletions(-) create mode 100644 powerjob-remote/powerjob-remote-benchmark/src/test/java/Engine.java create mode 100644 powerjob-remote/powerjob-remote-benchmark/src/test/java/IDEPathHelper.java create mode 100644 powerjob-remote/powerjob-remote-benchmark/src/test/java/tech/powerjob/remote/benchmark/Constant.java create mode 100644 powerjob-remote/powerjob-remote-benchmark/src/test/java/tech/powerjob/remote/benchmark/HttpSimulation.java create mode 100644 powerjob-remote/powerjob-remote-benchmark/src/test/resources/gatling.conf diff --git a/powerjob-common/pom.xml b/powerjob-common/pom.xml index 227733be..444e579e 100644 --- a/powerjob-common/pom.xml +++ b/powerjob-common/pom.xml @@ -19,7 +19,7 @@ 2.7 31.1-jre 3.14.9 - 2.6.12 + 2.6.20 5.0.4 2.12.2 5.9.0 diff --git a/powerjob-remote/powerjob-remote-benchmark/pom.xml b/powerjob-remote/powerjob-remote-benchmark/pom.xml index 09f0b97b..88b3fee5 100644 --- a/powerjob-remote/powerjob-remote-benchmark/pom.xml +++ b/powerjob-remote/powerjob-remote-benchmark/pom.xml @@ -16,14 +16,28 @@ 8 UTF-8 + 3.10.1 + 3.2.2 + 1.2.9 2.7.4 4.2.0 4.2.0 + + 3.9.0 + 4.2.9 + + + io.gatling.highcharts + gatling-charts-highcharts + ${gatling.version} + test + + ch.qos.logback logback-classic @@ -47,6 +61,46 @@ powerjob-remote-impl-akka ${powerjob-remote-impl-akka.version} + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${springboot.version} + + tech.powerjob.remote.benchmark.BenchmarkApplication + + + + + repackage + + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + + maven-jar-plugin + ${maven-jar-plugin.version} + + + io.gatling + gatling-maven-plugin + ${gatling-maven-plugin.version} + + + + + + + \ No newline at end of file diff --git a/powerjob-remote/powerjob-remote-benchmark/src/main/java/tech/powerjob/remote/benchmark/PressureTestController.java b/powerjob-remote/powerjob-remote-benchmark/src/main/java/tech/powerjob/remote/benchmark/PressureTestController.java index 290112c3..e54d8613 100644 --- a/powerjob-remote/powerjob-remote-benchmark/src/main/java/tech/powerjob/remote/benchmark/PressureTestController.java +++ b/powerjob-remote/powerjob-remote-benchmark/src/main/java/tech/powerjob/remote/benchmark/PressureTestController.java @@ -1,5 +1,7 @@ package tech.powerjob.remote.benchmark; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.BooleanUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -10,6 +12,8 @@ import tech.powerjob.remote.framework.base.URL; import javax.annotation.Resource; +import java.util.concurrent.CompletionStage; + import static tech.powerjob.remote.benchmark.EngineService.*; /** @@ -18,6 +22,7 @@ import static tech.powerjob.remote.benchmark.EngineService.*; * @author tjq * @since 2023/1/7 */ +@Slf4j @RestController @RequestMapping("/pressure") public class PressureTestController { @@ -31,7 +36,26 @@ public class PressureTestController { public void httpTell(Integer blockMs, Integer responseSize, String content) { URL url = new URL().setLocation(HL).setAddress(new Address().setPort(SERVER_HTTP_PORT).setHost(HOST)); final BenchmarkActor.BenchmarkRequest request = new BenchmarkActor.BenchmarkRequest().setContent(content).setBlockingMills(blockMs).setResponseSize(responseSize); - engineService.getHttpTransporter().tell(url, request); + try { + engineService.getHttpTransporter().tell(url, request); + } catch (Exception e) { + log.error("[HttpTell] process failed!", e); + } + } + + @GetMapping("/httpAsk") + public void httpAsk(Integer blockMs, Integer responseSize, String content, Boolean debug) { + URL url = new URL().setLocation(HL).setAddress(new Address().setPort(SERVER_HTTP_PORT).setHost(HOST)); + final BenchmarkActor.BenchmarkRequest request = new BenchmarkActor.BenchmarkRequest().setContent(content).setBlockingMills(blockMs).setResponseSize(responseSize); + try { + CompletionStage responseOpt = engineService.getHttpTransporter().ask(url, request, BenchmarkActor.BenchmarkResponse.class); + final BenchmarkActor.BenchmarkResponse response = responseOpt.toCompletableFuture().get(); + if (BooleanUtils.isTrue(debug)) { + log.info("[httpAsk] response: {}", response); + } + } catch (Exception e) { + log.error("[httpAsk] process failed", e); + } } } diff --git a/powerjob-remote/powerjob-remote-benchmark/src/test/java/Engine.java b/powerjob-remote/powerjob-remote-benchmark/src/test/java/Engine.java new file mode 100644 index 00000000..02ade1b0 --- /dev/null +++ b/powerjob-remote/powerjob-remote-benchmark/src/test/java/Engine.java @@ -0,0 +1,20 @@ +import io.gatling.app.Gatling; +import io.gatling.core.config.GatlingPropertiesBuilder; + +/** + * 压测启动入口 + * + * @author tjq + * @since 2023/1/8 + */ +public class Engine { + + public static void main(String[] args) { + GatlingPropertiesBuilder props = new GatlingPropertiesBuilder() + .resourcesDirectory(IDEPathHelper.mavenResourcesDirectory.toString()) + .resultsDirectory(IDEPathHelper.resultsDirectory.toString()) + .binariesDirectory(IDEPathHelper.mavenBinariesDirectory.toString()); + + Gatling.fromMap(props.build()); + } +} diff --git a/powerjob-remote/powerjob-remote-benchmark/src/test/java/IDEPathHelper.java b/powerjob-remote/powerjob-remote-benchmark/src/test/java/IDEPathHelper.java new file mode 100644 index 00000000..a6befe0b --- /dev/null +++ b/powerjob-remote/powerjob-remote-benchmark/src/test/java/IDEPathHelper.java @@ -0,0 +1,30 @@ +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static java.util.Objects.requireNonNull; + +public class IDEPathHelper { + + static final Path mavenSourcesDirectory; + static final Path mavenResourcesDirectory; + static final Path mavenBinariesDirectory; + static final Path resultsDirectory; + static final Path recorderConfigFile; + + static { + try { + Path projectRootDir = Paths.get(requireNonNull(IDEPathHelper.class.getResource("gatling.conf"), "Couldn't locate gatling.conf").toURI()).getParent().getParent().getParent(); + Path mavenTargetDirectory = projectRootDir.resolve("target"); + Path mavenSrcTestDirectory = projectRootDir.resolve("src").resolve("test"); + + mavenSourcesDirectory = mavenSrcTestDirectory.resolve("java"); + mavenResourcesDirectory = mavenSrcTestDirectory.resolve("resources"); + mavenBinariesDirectory = mavenTargetDirectory.resolve("test-classes"); + resultsDirectory = mavenTargetDirectory.resolve("gatling"); + recorderConfigFile = mavenResourcesDirectory.resolve("recorder.conf"); + } catch (URISyntaxException e) { + throw new ExceptionInInitializerError(e); + } + } +} diff --git a/powerjob-remote/powerjob-remote-benchmark/src/test/java/tech/powerjob/remote/benchmark/Constant.java b/powerjob-remote/powerjob-remote-benchmark/src/test/java/tech/powerjob/remote/benchmark/Constant.java new file mode 100644 index 00000000..71820edb --- /dev/null +++ b/powerjob-remote/powerjob-remote-benchmark/src/test/java/tech/powerjob/remote/benchmark/Constant.java @@ -0,0 +1,14 @@ +package tech.powerjob.remote.benchmark; + +/** + * Constant + * 压测时需要修改的常量 + * + * @author tjq + * @since 2023/1/8 + */ +public class Constant { + + public static final String SERVER_HOST = "127.0.0.1"; + +} diff --git a/powerjob-remote/powerjob-remote-benchmark/src/test/java/tech/powerjob/remote/benchmark/HttpSimulation.java b/powerjob-remote/powerjob-remote-benchmark/src/test/java/tech/powerjob/remote/benchmark/HttpSimulation.java new file mode 100644 index 00000000..3f22d040 --- /dev/null +++ b/powerjob-remote/powerjob-remote-benchmark/src/test/java/tech/powerjob/remote/benchmark/HttpSimulation.java @@ -0,0 +1,35 @@ +package tech.powerjob.remote.benchmark; + +import static io.gatling.javaapi.core.CoreDsl.*; +import static io.gatling.javaapi.http.HttpDsl.*; + +import io.gatling.javaapi.core.*; +import io.gatling.javaapi.http.*; +/** + * description + * + * @author tjq + * @since 2023/1/8 + */ +public class HttpSimulation extends Simulation { + + String baseUrl = String.format("http://%s:8080", Constant.SERVER_HOST); + HttpProtocolBuilder httpProtocol = http // 4 + .baseUrl(baseUrl) // 5 + .acceptHeader("application/json") // 6 + .doNotTrackHeader("1") + .acceptLanguageHeader("en-US,en;q=0.5") + .acceptEncodingHeader("gzip, deflate") + .userAgentHeader("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0"); + + ScenarioBuilder scn = scenario("HttpSimulation") // 7 + .exec(http("request_http") // 请求名称,用于压测报表展示 + .get("/httpAsk?debug=true&responseSize=1024")) // 9 + .pause(5); // 10 + + { + setUp( // 11 + scn.injectOpen(atOnceUsers(1)) // 12 + ).protocols(httpProtocol); // 13 + } +} diff --git a/powerjob-remote/powerjob-remote-benchmark/src/test/resources/gatling.conf b/powerjob-remote/powerjob-remote-benchmark/src/test/resources/gatling.conf new file mode 100644 index 00000000..c6db7626 --- /dev/null +++ b/powerjob-remote/powerjob-remote-benchmark/src/test/resources/gatling.conf @@ -0,0 +1,127 @@ +######################### +# Gatling Configuration # +######################### + +# This file contains all the settings configurable for Gatling with their default values + +gatling { + core { + #outputDirectoryBaseName = "" # The prefix for each simulation result folder (then suffixed by the report generation timestamp) + #runDescription = "" # The description for this simulation run, displayed in each report + #encoding = "utf-8" # Encoding to use throughout Gatling for file and string manipulation + #simulationClass = "" # The FQCN of the simulation to run (when used in conjunction with noReports, the simulation for which assertions will be validated) + #elFileBodiesCacheMaxCapacity = 200 # Cache size for request body EL templates, set to 0 to disable + #rawFileBodiesCacheMaxCapacity = 200 # Cache size for request body Raw templates, set to 0 to disable + #rawFileBodiesInMemoryMaxSize = 1000 # Below this limit, raw file bodies will be cached in memory + #pebbleFileBodiesCacheMaxCapacity = 200 # Cache size for request body Peeble templates, set to 0 to disable + #feederAdaptiveLoadModeThreshold = 100 # File size threshold (in MB). Below load eagerly in memory, above use batch mode with default buffer size + #shutdownTimeout = 10000 # Milliseconds to wait for the actor system to shutdown + extract { + regex { + #cacheMaxCapacity = 200 # Cache size for the compiled regexes, set to 0 to disable caching + } + xpath { + #cacheMaxCapacity = 200 # Cache size for the compiled XPath queries, set to 0 to disable caching + } + jsonPath { + #cacheMaxCapacity = 200 # Cache size for the compiled jsonPath queries, set to 0 to disable caching + } + css { + #cacheMaxCapacity = 200 # Cache size for the compiled CSS selectors queries, set to 0 to disable caching + } + } + directory { + #simulations = user-files/simulations # Directory where simulation classes are located (for bundle packaging only) + #resources = user-files/resources # Directory where resources, such as feeder files and request bodies are located (for bundle packaging only) + #reportsOnly = "" # If set, name of report folder to look for in order to generate its report + #binaries = "" # If set, name of the folder where compiles classes are located: Defaults to GATLING_HOME/target. + #results = results # Name of the folder where all reports folder are located + } + } + socket { + #connectTimeout = 10000 # Timeout in millis for establishing a TCP socket + #tcpNoDelay = true + #soKeepAlive = false # if TCP keepalive configured at OS level should be used + #soReuseAddress = false + } + netty { + #useNativeTransport = true # if Netty native transport should be used instead of Java NIO + #allocator = "pooled" # switch to unpooled for unpooled ByteBufAllocator + #maxThreadLocalCharBufferSize = 200000 # Netty's default is 16k + } + ssl { + #useOpenSsl = true # if OpenSSL should be used instead of JSSE (only the latter can be debugged with -Djava.net.debug=ssl) + #useOpenSslFinalizers = false # if OpenSSL contexts should be freed with Finalizer or if using RefCounted is fine + #handshakeTimeout = 10000 # TLS handshake timeout in millis + #useInsecureTrustManager = true # Use an insecure TrustManager that trusts all server certificates + #enabledProtocols = [] # Array of enabled protocols for HTTPS, if empty use Netty's defaults + #enabledCipherSuites = [] # Array of enabled cipher suites for HTTPS, if empty enable all available ciphers + #sessionCacheSize = 0 # SSLSession cache size, set to 0 to use JDK's default + #sessionTimeout = 0 # SSLSession timeout in seconds, set to 0 to use JDK's default (24h) + #enableSni = true # When set to true, enable Server Name indication (SNI) + keyStore { + #type = "" # Type of SSLContext's KeyManagers store + #file = "" # Location of SSLContext's KeyManagers store + #password = "" # Password for SSLContext's KeyManagers store + #algorithm = "" # Algorithm used SSLContext's KeyManagers store + } + trustStore { + #type = "" # Type of SSLContext's TrustManagers store + #file = "" # Location of SSLContext's TrustManagers store + #password = "" # Password for SSLContext's TrustManagers store + #algorithm = "" # Algorithm used by SSLContext's TrustManagers store + } + } + charting { + #noReports = false # When set to true, don't generate HTML reports + #maxPlotPerSeries = 1000 # Number of points per graph in Gatling reports + #useGroupDurationMetric = false # Switch group timings from cumulated response time to group duration. + indicators { + #lowerBound = 800 # Lower bound for the requests' response time to track in the reports and the console summary + #higherBound = 1200 # Higher bound for the requests' response time to track in the reports and the console summary + #percentile1 = 50 # Value for the 1st percentile to track in the reports, the console summary and Graphite + #percentile2 = 75 # Value for the 2nd percentile to track in the reports, the console summary and Graphite + #percentile3 = 95 # Value for the 3rd percentile to track in the reports, the console summary and Graphite + #percentile4 = 99 # Value for the 4th percentile to track in the reports, the console summary and Graphite + } + } + http { + #fetchedCssCacheMaxCapacity = 200 # Cache size for CSS parsed content, set to 0 to disable + #fetchedHtmlCacheMaxCapacity = 200 # Cache size for HTML parsed content, set to 0 to disable + #perUserCacheMaxCapacity = 200 # Per virtual user cache size, set to 0 to disable + #warmUpUrl = "https://gatling.io" # The URL to use to warm-up the HTTP stack (blank means disabled) + #enableGA = true # Very light Google Analytics (Gatling and Java version), please support + #pooledConnectionIdleTimeout = 60000 # Timeout in millis for a connection to stay idle in the pool + #requestTimeout = 60000 # Timeout in millis for performing an HTTP request + #enableHostnameVerification = false # When set to true, enable hostname verification: SSLEngine.setHttpsEndpointIdentificationAlgorithm("HTTPS") + dns { + #queryTimeout = 5000 # Timeout in millis of each DNS query in millis + #maxQueriesPerResolve = 6 # Maximum allowed number of DNS queries for a given name resolution + } + } + jms { + #replyTimeoutScanPeriod = 1000 # scan period for timedout reply messages + } + data { + #writers = [console, file] # The list of DataWriters to which Gatling write simulation data (currently supported : console, file, graphite) + console { + #light = false # When set to true, displays a light version without detailed request stats + #writePeriod = 5 # Write interval, in seconds + } + file { + #bufferSize = 8192 # FileDataWriter's internal data buffer size, in bytes + } + leak { + #noActivityTimeout = 30 # Period, in seconds, for which Gatling may have no activity before considering a leak may be happening + } + graphite { + #light = false # only send the all* stats + #host = "localhost" # The host where the Carbon server is located + #port = 2003 # The port to which the Carbon server listens to (2003 is default for plaintext, 2004 is default for pickle) + #protocol = "tcp" # The protocol used to send data to Carbon (currently supported : "tcp", "udp") + #rootPathPrefix = "gatling" # The common prefix of all metrics sent to Graphite + #bufferSize = 8192 # Internal data buffer size, in bytes + #writePeriod = 1 # Write period, in seconds + } + } +} diff --git a/powerjob-remote/powerjob-remote-impl-akka/pom.xml b/powerjob-remote/powerjob-remote-impl-akka/pom.xml index e422b0c8..8b8a738b 100644 --- a/powerjob-remote/powerjob-remote-impl-akka/pom.xml +++ b/powerjob-remote/powerjob-remote-impl-akka/pom.xml @@ -19,7 +19,7 @@ 4.2.0 - 2.6.12 + 2.6.20