SlideShare a Scribd company logo
1 of 85
which you
always wanted
LOAD TESTING
by @antyadev
Data Feed
Terminals
select * from Games where isLive = true
order by totalBets desc
limit 10
PUSH changes
Sports Data
API
• Document size ~15Kb
• 5K sport games available for betting
• 73K markets (categories of bets)
• 500K selections (positions to win an event)
• Up to 1M incoming events per minute consumed by one
process
• 10K outgoing events per second
• 10TB of streaming data per day
{ update }
{ push }
{ pull }
Data Consistency Problem
{ update }
{ push }
{ pull }
Data Propagation Problem
DB
Agenda
- The real need of load testing
- Load testing basics
- Current state of load testing on 2019
- NBomber – your drug to load testing
Do you know
how many
concurrent requests
your service
can handle?
The real need of Load Testing
- Choose technology stack
- Prove architecture design (POC)
- System regression (CI/CD pipeline)
- Explore system limits
Load Testing basics
- in many cases, you don’t need a cluster
- make sure that targeting node is fully loaded (100% CPU) to
get max RPS
- make sure that you have long running tests
- make sure that you have controllability (your test
input/output should be consistent)
Current state
of
Load Testing
Load Testing
is not easy
Current state of Load Testing
Gatling (open-source, Scala, Akka):
- free + commercial version
- test as code
- very good for HTTP (has API for WebSockets, SSE)
- very nice reports
- has integration with Grafana, Jenkins
- has UI recorder to playback actions
- no back pressure
- not easy to customize
- no cluster in free version
class BasicSimulation extends Simulation {
val httpConf = http
.baseURL("http://computer-database.gatling.io")
.acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
.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/
val scn = scenario("BasicSimulation")
.exec(
http("request_1").get("/"))
.pause(5)
setUp(
scn.inject(atOnceUsers(1))
).protocols(httpConf)
}
Current state of Load Testing
- Easy to cover HTTP only systems
- Hard to cover any other Pull/Push systems
- Complicated and not flexible API
- Limited cluster support (different
workloads)
Current state of Load Testing
- Easy to cover HTTP only systems
- Hard to cover any other Pull/Push systems
- Complicated and not flexible API
- Limited cluster support
Batch Update Process 1
Batch Update Process 3
MongoDB
Batch Update Process 2
insert
read
read
Producer
KAFKA
ETL
KAFKA
No SQL
1 2
34
WebSockets
API
What about
1 Million
connections???
WebSockets
Users
API
WebSockets
Payments
API
WebSockets
Orders
API
Combine to one connection
let start = getCurrentTimer()
execFunc()
let end = getCurrentTimer()
let latency = end - start
let start = getCurrentTimer()
sendHttpReqeust()
let end = getCurrentTimer()
let latency = end - start
let start = getCurrentTimer()
queryMongoDb()
let end = getCurrentTimer()
let latency = end - start
let start = getCurrentTimer()
publishToKafka()
let end = getCurrentTimer()
let latency = end - start
let start = getCurrentTimer()
let! response = websockets.ReceivePush()
let end = getCurrentTimer()
let latency = end - start
Load test any system
https://nbomber.com
PM> Install-Package NBomber
Why another {x} framework for load testing?
The main reasons are:
- To be technology agnostic as much as possible (no dependency on any protocol:
HTTP, WebSockets, SSE etc).
- To be able to test .NET implementation of specific driver. During testing, it was
identified many times that the performance could be slightly different because of
the virtual machine(.NET, Java, PHP, Js, Erlang, different settings for GC) or just
quality of drivers. For example there were cases that drivers written in C++ and
invoked from NodeJs app worked faster than drivers written in C#/.NET. Therefore,
it does make sense to load test your app using your concrete driver and runtime.
- Technology agnostic
(no dependency on HTTP, WebSockets, SSE)
- Very simple API
(to test Pull and Push scenarios)
- CI/CD integration
Pull and Push
Scenarios
xUnit/NUnit
integration
Sequential flow
ReportingDistributed clusterPlugins
Features
type Scenario = {
ScenarioName: string
TestInit: (ScenarioContext -> Task) option
TestClean: (ScenarioContext -> Task) option
Steps: Step[] // these steps will be executed sequentially
Assertions: Assertion[]
ConcurrentCopies: int
WarmupDuration: TimeSpan
Duration: TimeSpan
}
type Step = {
StepName: string
Execute: StepContext -> Task<Response>
}
Very simple API
Very simple API
Step.Create("step", () => {...})
ScenarioBuilder
.CreateScenario("scenario", step1, step2)
.WithConcurrentCopies(10)
.WithDuration(TimeSpan.FromSeconds(60))
NBomberRunner.RegisterScenarios(scenario)
.RunInConsole();
Step.create("step", fun () -> {...})
Scenario.create("scenario", [step1; step2])
|> Scenario.withConcurrentCopies(10)
|> Scenario.withDuration(TimeSpan.FromSeconds(60))
NBomberRunner.registerScenario(scenario)
|> NBomberRunner.runInConsole
Step 1
Scenario
while true
{
}
Scenario
Step 2Step 1
}
while true
{
Scenario
Step 3Step 1 Step 2
}
while true
{
var scenario = ScenarioBuilder
.CreateScenario("Hello World from NBomber!", step)
.WithConcurrentCopies(10)
.WithDuration(TimeSpan.FromSeconds(10));
var step = Step.Create("simple step", async context => {
// you can do any logic here: go to http, websocket etc
await Task.Delay(TimeSpan.FromSeconds(0.1));
return Response.Ok();
});
NBomberRunner.RegisterScenarios(scenario)
.RunInConsole();
let step = Step.create("simple step", fun context -> task {
// you can do any logic here: go to http, websocket etc
do! Task.Delay(TimeSpan.FromSeconds(0.1))
return Response.Ok()
})
Scenario.create("Hello World from NBomber!", [step])
|> Scenario.withConcurrentCopies(10)
|> Scenario.withDuration(TimeSpan.FromSeconds(10.0))
|> NBomberRunner.registerScenario
|> NBomberRunner.runInConsole
Scenario withConcurrentCopies 2
Scenario withConcurrentCopies 2
Task<T>
Task<T>
Step 2Step 1
Step 2Step 1
var client = new HttpClient();
var step1 = Step.Create("GET html", async context =>
{
var request = new HttpRequestMessage(HttpMethod.Get, "https://nbomber.com");
var response = await client.SendAsync(request);
return response.IsSuccessStatusCode
? Response.Ok()
: Response.Fail();
});
var scenario = ScenarioBuilder.CreateScenario("test_nbomber", step1);
NBomberRunner.RegisterScenarios(scenario)
.RunInConsole();
Http example
Assertions[Test]
public void Test()
{
var assertions = new[] {
Assertion.ForStep("simple step", stats => stats.OkCount > 2),
Assertion.ForStep("simple step", stats => stats.RPS > 8),
Assertion.ForStep("simple step", stats => stats.Min > 8),
Assertion.ForStep("simple step", stats => stats.Max > 8),
Assertion.ForStep("simple step", stats => stats.Percent95 >= 102),
Assertion.ForStep("simple step", stats => stats.DataMinKb == 1.0),
Assertion.ForStep("simple step", stats => stats.AllDataMB >= 0.01)
};
var scenario = BuildScenario()
.WithConcurrentCopies(1)
.WithWarmUpDuration(TimeSpan.FromSeconds(0))
.WithDuration(TimeSpan.FromSeconds(2))
.WithAssertions(assertions);
NBomberRunner.RegisterScenarios(scenario)
.RunTest();
}
.Http
https://nbomber.com
PM> Install-Package NBomber.Http
var client = new HttpClient();
var step1 = Step.Create("GET html", async context =>
{
var request = new HttpRequestMessage(HttpMethod.Get, "https://nbomber.com");
var response = await client.SendAsync(request);
return response.IsSuccessStatusCode
? Response.Ok()
: Response.Fail();
});
var scenario = ScenarioBuilder.CreateScenario("test_nbomber", step1);
NBomberRunner.RegisterScenarios(scenario)
.RunInConsole();
Http example
var step1 = HttpStep.Create("simple step", async (context) =>
Http.CreateRequest("GET", "https://nbomber.com")
.WithHeader("accept", "application/json"));
var scenario = ScenarioBuilder.CreateScenario("test_nbomber", step1);
NBomberRunner.RegisterScenarios(scenario)
.RunInConsole();
Nbomber.Http
Advanced
Example
Batch Update Process 1
Batch Update Process 3
MongoDB
Batch Update Process 2
write
read
read
var insertStep = Step.Create("insert", async context =>
{
await mongoCollection.InsertManyAsync { ... };
});
var pause_200 = Step.Create("pause 200", async context =>
{
await Task.Delay(TimeSpan.FromMilliseconds(200));
});
var readStep = HttpStep.Create("TOP 100 games", async (context) =>
Http.CreateRequest("GET", "https://sbtech/games?top=100")
.WithHeader("accept", "application/json"));
// insert scenario: batch insert per 200 ms
var insertScenario = ScenarioBuilder.CreateScenario("mongo", insertStep, pause_200);
// read scenario: in parallel, we want to read data
var readScenario = ScenarioBuilder.CreateScenario("http", readStep);
NBomberRunner.RegisterScenarios(insertScenario, readScenario)
.RunInConsole();
The Kids
want cluster
Agent
Agent
Coordinator
MongoDB
read
write
read
Test
Scenarios.fs
Compile
Test
Scenarios.EXE
Upload
Test
Scenarios.EXE
config
Test
Scenarios.EXE
config
Test
Scenarios.EXE
config
Test
Scenarios.EXE
config
Test
Scenarios.EXE
coordinator_config
Test
Scenarios.EXE
agent_config
Test
Scenarios.EXE
coordinator_config
Test
Scenarios.EXE
agent_config
Test
Scenarios.EXE
agent_config
{
"ClusterSettings": {
"Agent": {
"ClusterId": "test_cluster",
"TargetGroup": "group_1",
"MqttServer": "104.155.3.33"
}
}
}
Agent
Agent
Agent Config
Coordinator
Config
{
"ClusterSettings": {
"Coordinator": {
"ClusterId": "test_cluster",
"TargetScenarios": [ "mongo_insert" ]
"Agents": [
{
"TargetGroup": "group_1",
"TargetScenarios": [ "mongo_read" ]
}
]
},
}
} Coordinator
The Kids
want PUSH
var url = "ws://localhost:53231";
var webSocketsPool = ConnectionPool.Create("webSocketsPool", openConnection: () =>
{
var ws = new ClientWebSocket();
ws.ConnectAsync(new Uri(url), CancellationToken.None).Wait();
return ws;
});
var pingStep = Step.Create("ping", webSocketsPool, async context =>
{
var msg = new WebSocketRequest
{
CorrelationId = context.CorrelationId,
RequestType = RequestType.Ping
};
await context.Connection.SendAsync(msg, WebSocketMessageType.Text);
return Response.Ok();
});
var pingStep = Step.Create("ping", webSocketsPool, async context =>
{
var msg = new WebSocketRequest
{
CorrelationId = context.CorrelationId,
RequestType = RequestType.Ping
};
await context.Connection.SendAsync(msg, WebSocketMessageType.Text);
return Response.Ok();
});
var pongStep = Step.Create("pong", webSocketsPool, async context =>
{
while (true)
{
var message = await context.Connection.ReceiveMessage();
if (msg.CorrelationId == context.CorrelationId)
{
return Response.Ok(msg);
}
}
});
Internals
NBomber
Runner
let run (dep: Dependency, context: NBomberContext) =
asyncResult {
let! ctx = Validation.validateContext(context)
let! nodeStats =
NBomberContext.tryGetClusterSettings(ctx)
|> Option.map(function
| Coordinator c -> runClusterCoordinator(dep, ctx, c)
| Agent a -> runClusterAgent(dep, ctx, a))
|> Option.orElseWith(fun _ -> runSingleNode(dep, ctx))
|> Option.get
return nodeStats
|> calcStatistics(dep, ctx)
|> saveStatistics(ctx)
|> applyAsserts(ctx)
|> buildReport(dep)
|> saveReport(dep, ctx)
}
|> AsyncResult.mapError(handleError(dep))
|> Async.RunSynchronously
|> ignore
Validation
type Result<TOk, TError> =
<!>
<*>
>>=
>=>
module ScenarioValidation =
let validate (context: NBomberContext) =
context.Scenarios
|> checkEmptyName
>>= checkDuplicateName
>>= checkEmptyStepName
>>= checkDuplicateStepName
>>= checkDuration
>>= checkConcurrentCopies
>>= fun _ -> Ok context
module GlobalSettingsValidation =
let validate (context: NBomberContext) =
context.NBomberConfig
|> Option.bind(fun x -> x.GlobalSettings)
|> Option.map(fun glSettings ->
glSettings
|> checkEmptyTarget
>>= checkAvailableTarget
>>= checkDuration
>>= checkConcurrentCopies
>>= checkEmptyReportName
>>= fun _ -> Ok context
)
|> Option.defaultValue(Ok context)
module ScenarioValidation =
let validate (context) = ...
module GlobalSettingsValidation =
let validate (context) = ...
module Validation =
let validate =
ScenarioValidation.validate >=> GlobalSettingsValidation.validate
Type Safe
Cluster
(>>=)
type IClusterCoordinator =
abstract StartNewSession: ScenarioSetting[] -> Task<Result<unit,Error>>
abstract WaitOnAllAgentsReady: unit -> Task<Result<unit,Error>>
abstract StartWarmUp: unit -> Task<Result<unit,Error>>
abstract StartBombing: unit -> Task<Result<unit,Error>>
abstract GetStatistics: unit -> Task<Result<NodeStats[],Error>>
let runCoordinator (cluster: IClusterCoordinator, localHost: IScenariosHost,
settings: ScenarioSetting[], targetScns: string[]) =
asyncResult {
do! cluster.SendStartNewSession(settings)
do! localHost.InitScenarios(settings, targetScns)
do! cluster.WaitOnAllAgentsReady()
do! cluster.SendStartWarmUp()
do! localHost.WarmUpScenarios()
do! cluster.WaitOnAllAgentsReady()
do! cluster.SendStartBombing() // Task<Result<unit,Error>>
do! localHost.StartBombing()
do! cluster.WaitOnAllAgentsReady()
let localStats = localHost.GetStatistics()
let! agentsStats = cluster.GetStatistics()
let allStats = Array.append [|localStats|] agentsStats
localHost.StopScenarios()
return allStats
}
- (2663) LOC
- (6) OOP objects
- (~160) functions
Summary
THANKS
@antyadev
antyadev@gmail.com
http://nbomber.com

More Related Content

What's hot

Performance tests with Gatling (extended)
Performance tests with Gatling (extended)Performance tests with Gatling (extended)
Performance tests with Gatling (extended)Andrzej Ludwikowski
 
DIY Java Profiler
DIY Java ProfilerDIY Java Profiler
DIY Java Profileraragozin
 
PostgreSQL Troubleshoot On-line, (RITfest 2015 meetup at Moscow, Russia).
PostgreSQL Troubleshoot On-line, (RITfest 2015 meetup at Moscow, Russia).PostgreSQL Troubleshoot On-line, (RITfest 2015 meetup at Moscow, Russia).
PostgreSQL Troubleshoot On-line, (RITfest 2015 meetup at Moscow, Russia).Alexey Lesovsky
 
Sessionization with Spark streaming
Sessionization with Spark streamingSessionization with Spark streaming
Sessionization with Spark streamingRamūnas Urbonas
 
Java profiling Do It Yourself
Java profiling Do It YourselfJava profiling Do It Yourself
Java profiling Do It Yourselfaragozin
 
Using Grails to power your electric car
Using Grails to power your electric carUsing Grails to power your electric car
Using Grails to power your electric carMarco Pas
 
Varnish presentation for the Symfony Zaragoza user group
Varnish presentation for the Symfony Zaragoza user groupVarnish presentation for the Symfony Zaragoza user group
Varnish presentation for the Symfony Zaragoza user groupJorge Nerín
 
GitLab PostgresMortem: Lessons Learned
GitLab PostgresMortem: Lessons LearnedGitLab PostgresMortem: Lessons Learned
GitLab PostgresMortem: Lessons LearnedAlexey Lesovsky
 
Kernel Recipes 2017: Using Linux perf at Netflix
Kernel Recipes 2017: Using Linux perf at NetflixKernel Recipes 2017: Using Linux perf at Netflix
Kernel Recipes 2017: Using Linux perf at NetflixBrendan Gregg
 
Stress test your backend with Gatling
Stress test your backend with GatlingStress test your backend with Gatling
Stress test your backend with GatlingAndrzej Ludwikowski
 
基于Mongodb的压力评测工具 ycsb的一些概括
基于Mongodb的压力评测工具 ycsb的一些概括基于Mongodb的压力评测工具 ycsb的一些概括
基于Mongodb的压力评测工具 ycsb的一些概括Louis liu
 
Adopting GraalVM - Scala eXchange London 2018
Adopting GraalVM - Scala eXchange London 2018Adopting GraalVM - Scala eXchange London 2018
Adopting GraalVM - Scala eXchange London 2018Petr Zapletal
 
Performance Analysis Tools for Linux Kernel
Performance Analysis Tools for Linux KernelPerformance Analysis Tools for Linux Kernel
Performance Analysis Tools for Linux Kernellcplcp1
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaFrank Lyaruu
 
How to cook lettuce @Java casual
How to cook lettuce @Java casualHow to cook lettuce @Java casual
How to cook lettuce @Java casualGo Hagiwara
 
HBASE Performane Test
HBASE Performane TestHBASE Performane Test
HBASE Performane TestLouis liu
 
Profiling your Applications using the Linux Perf Tools
Profiling your Applications using the Linux Perf ToolsProfiling your Applications using the Linux Perf Tools
Profiling your Applications using the Linux Perf ToolsemBO_Conference
 
BKK16-104 sched-freq
BKK16-104 sched-freqBKK16-104 sched-freq
BKK16-104 sched-freqLinaro
 
PostgreSQL Streaming Replication Cheatsheet
PostgreSQL Streaming Replication CheatsheetPostgreSQL Streaming Replication Cheatsheet
PostgreSQL Streaming Replication CheatsheetAlexey Lesovsky
 

What's hot (20)

Performance tests with Gatling (extended)
Performance tests with Gatling (extended)Performance tests with Gatling (extended)
Performance tests with Gatling (extended)
 
DIY Java Profiler
DIY Java ProfilerDIY Java Profiler
DIY Java Profiler
 
PostgreSQL Troubleshoot On-line, (RITfest 2015 meetup at Moscow, Russia).
PostgreSQL Troubleshoot On-line, (RITfest 2015 meetup at Moscow, Russia).PostgreSQL Troubleshoot On-line, (RITfest 2015 meetup at Moscow, Russia).
PostgreSQL Troubleshoot On-line, (RITfest 2015 meetup at Moscow, Russia).
 
Sessionization with Spark streaming
Sessionization with Spark streamingSessionization with Spark streaming
Sessionization with Spark streaming
 
Performance tests with Gatling
Performance tests with GatlingPerformance tests with Gatling
Performance tests with Gatling
 
Java profiling Do It Yourself
Java profiling Do It YourselfJava profiling Do It Yourself
Java profiling Do It Yourself
 
Using Grails to power your electric car
Using Grails to power your electric carUsing Grails to power your electric car
Using Grails to power your electric car
 
Varnish presentation for the Symfony Zaragoza user group
Varnish presentation for the Symfony Zaragoza user groupVarnish presentation for the Symfony Zaragoza user group
Varnish presentation for the Symfony Zaragoza user group
 
GitLab PostgresMortem: Lessons Learned
GitLab PostgresMortem: Lessons LearnedGitLab PostgresMortem: Lessons Learned
GitLab PostgresMortem: Lessons Learned
 
Kernel Recipes 2017: Using Linux perf at Netflix
Kernel Recipes 2017: Using Linux perf at NetflixKernel Recipes 2017: Using Linux perf at Netflix
Kernel Recipes 2017: Using Linux perf at Netflix
 
Stress test your backend with Gatling
Stress test your backend with GatlingStress test your backend with Gatling
Stress test your backend with Gatling
 
基于Mongodb的压力评测工具 ycsb的一些概括
基于Mongodb的压力评测工具 ycsb的一些概括基于Mongodb的压力评测工具 ycsb的一些概括
基于Mongodb的压力评测工具 ycsb的一些概括
 
Adopting GraalVM - Scala eXchange London 2018
Adopting GraalVM - Scala eXchange London 2018Adopting GraalVM - Scala eXchange London 2018
Adopting GraalVM - Scala eXchange London 2018
 
Performance Analysis Tools for Linux Kernel
Performance Analysis Tools for Linux KernelPerformance Analysis Tools for Linux Kernel
Performance Analysis Tools for Linux Kernel
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJava
 
How to cook lettuce @Java casual
How to cook lettuce @Java casualHow to cook lettuce @Java casual
How to cook lettuce @Java casual
 
HBASE Performane Test
HBASE Performane TestHBASE Performane Test
HBASE Performane Test
 
Profiling your Applications using the Linux Perf Tools
Profiling your Applications using the Linux Perf ToolsProfiling your Applications using the Linux Perf Tools
Profiling your Applications using the Linux Perf Tools
 
BKK16-104 sched-freq
BKK16-104 sched-freqBKK16-104 sched-freq
BKK16-104 sched-freq
 
PostgreSQL Streaming Replication Cheatsheet
PostgreSQL Streaming Replication CheatsheetPostgreSQL Streaming Replication Cheatsheet
PostgreSQL Streaming Replication Cheatsheet
 

Similar to QA Fest 2019. Антон Молдован. Load testing which you always wanted

Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"Fwdays
 
"Load Testing Distributed Systems with NBomber 4.0", Anton Moldovan
"Load Testing Distributed Systems with NBomber 4.0",  Anton Moldovan"Load Testing Distributed Systems with NBomber 4.0",  Anton Moldovan
"Load Testing Distributed Systems with NBomber 4.0", Anton MoldovanFwdays
 
MongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-esMongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-esMongoDB
 
How to build a Citrix infrastructure on AWS
How to build a Citrix infrastructure on AWSHow to build a Citrix infrastructure on AWS
How to build a Citrix infrastructure on AWSDenis Gundarev
 
Azure SQL Database - Connectivity Best Practices
Azure SQL Database - Connectivity Best PracticesAzure SQL Database - Connectivity Best Practices
Azure SQL Database - Connectivity Best PracticesJose Manuel Jurado Diaz
 
Structured Testing Framework
Structured Testing FrameworkStructured Testing Framework
Structured Testing Frameworkserzar
 
RestMQ - HTTP/Redis based Message Queue
RestMQ - HTTP/Redis based Message QueueRestMQ - HTTP/Redis based Message Queue
RestMQ - HTTP/Redis based Message QueueGleicon Moraes
 
Load Testing with RedLine13: Or getting paid to DoS your own systems
Load Testing with RedLine13: Or getting paid to DoS your own systemsLoad Testing with RedLine13: Or getting paid to DoS your own systems
Load Testing with RedLine13: Or getting paid to DoS your own systemsJason Lotito
 
Integration tests: use the containers, Luke!
Integration tests: use the containers, Luke!Integration tests: use the containers, Luke!
Integration tests: use the containers, Luke!Roberto Franchini
 
Automated acceptance test
Automated acceptance testAutomated acceptance test
Automated acceptance testBryan Liu
 
Binary Studio Academy: Concurrency in C# 5.0
Binary Studio Academy: Concurrency in C# 5.0Binary Studio Academy: Concurrency in C# 5.0
Binary Studio Academy: Concurrency in C# 5.0Binary Studio
 
OB1K - New, Better, Faster, Devops Friendly Java container by Outbrain
OB1K - New, Better, Faster, Devops Friendly Java container by OutbrainOB1K - New, Better, Faster, Devops Friendly Java container by Outbrain
OB1K - New, Better, Faster, Devops Friendly Java container by OutbrainEran Harel
 
Test strategy for web development
Test strategy for web developmentTest strategy for web development
Test strategy for web developmentalice yang
 
Future Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETFuture Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETGianluca Carucci
 
Continuous Application with Structured Streaming 2.0
Continuous Application with Structured Streaming 2.0Continuous Application with Structured Streaming 2.0
Continuous Application with Structured Streaming 2.0Anyscale
 
Flink Streaming Hadoop Summit San Jose
Flink Streaming Hadoop Summit San JoseFlink Streaming Hadoop Summit San Jose
Flink Streaming Hadoop Summit San JoseKostas Tzoumas
 
Server side JavaScript: going all the way
Server side JavaScript: going all the wayServer side JavaScript: going all the way
Server side JavaScript: going all the wayOleg Podsechin
 
Monitoring Cassandra at Scale (Jason Cacciatore, Netflix) | C* Summit 2016
Monitoring Cassandra at Scale (Jason Cacciatore, Netflix) | C* Summit 2016Monitoring Cassandra at Scale (Jason Cacciatore, Netflix) | C* Summit 2016
Monitoring Cassandra at Scale (Jason Cacciatore, Netflix) | C* Summit 2016DataStax
 

Similar to QA Fest 2019. Антон Молдован. Load testing which you always wanted (20)

Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"
 
"Load Testing Distributed Systems with NBomber 4.0", Anton Moldovan
"Load Testing Distributed Systems with NBomber 4.0",  Anton Moldovan"Load Testing Distributed Systems with NBomber 4.0",  Anton Moldovan
"Load Testing Distributed Systems with NBomber 4.0", Anton Moldovan
 
MongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-esMongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-es
 
How to build a Citrix infrastructure on AWS
How to build a Citrix infrastructure on AWSHow to build a Citrix infrastructure on AWS
How to build a Citrix infrastructure on AWS
 
Azure SQL Database - Connectivity Best Practices
Azure SQL Database - Connectivity Best PracticesAzure SQL Database - Connectivity Best Practices
Azure SQL Database - Connectivity Best Practices
 
Structured Testing Framework
Structured Testing FrameworkStructured Testing Framework
Structured Testing Framework
 
RestMQ - HTTP/Redis based Message Queue
RestMQ - HTTP/Redis based Message QueueRestMQ - HTTP/Redis based Message Queue
RestMQ - HTTP/Redis based Message Queue
 
Load Testing with RedLine13: Or getting paid to DoS your own systems
Load Testing with RedLine13: Or getting paid to DoS your own systemsLoad Testing with RedLine13: Or getting paid to DoS your own systems
Load Testing with RedLine13: Or getting paid to DoS your own systems
 
Integration tests: use the containers, Luke!
Integration tests: use the containers, Luke!Integration tests: use the containers, Luke!
Integration tests: use the containers, Luke!
 
Automated acceptance test
Automated acceptance testAutomated acceptance test
Automated acceptance test
 
Binary Studio Academy: Concurrency in C# 5.0
Binary Studio Academy: Concurrency in C# 5.0Binary Studio Academy: Concurrency in C# 5.0
Binary Studio Academy: Concurrency in C# 5.0
 
OB1K - New, Better, Faster, Devops Friendly Java container by Outbrain
OB1K - New, Better, Faster, Devops Friendly Java container by OutbrainOB1K - New, Better, Faster, Devops Friendly Java container by Outbrain
OB1K - New, Better, Faster, Devops Friendly Java container by Outbrain
 
Test strategy for web development
Test strategy for web developmentTest strategy for web development
Test strategy for web development
 
Future Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETFuture Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NET
 
Load Data Fast!
Load Data Fast!Load Data Fast!
Load Data Fast!
 
Beyond Unit Testing
Beyond Unit TestingBeyond Unit Testing
Beyond Unit Testing
 
Continuous Application with Structured Streaming 2.0
Continuous Application with Structured Streaming 2.0Continuous Application with Structured Streaming 2.0
Continuous Application with Structured Streaming 2.0
 
Flink Streaming Hadoop Summit San Jose
Flink Streaming Hadoop Summit San JoseFlink Streaming Hadoop Summit San Jose
Flink Streaming Hadoop Summit San Jose
 
Server side JavaScript: going all the way
Server side JavaScript: going all the wayServer side JavaScript: going all the way
Server side JavaScript: going all the way
 
Monitoring Cassandra at Scale (Jason Cacciatore, Netflix) | C* Summit 2016
Monitoring Cassandra at Scale (Jason Cacciatore, Netflix) | C* Summit 2016Monitoring Cassandra at Scale (Jason Cacciatore, Netflix) | C* Summit 2016
Monitoring Cassandra at Scale (Jason Cacciatore, Netflix) | C* Summit 2016
 

More from QAFest

QA Fest 2019. Сергій Короленко. Топ веб вразливостей за 40 хвилин
QA Fest 2019. Сергій Короленко. Топ веб вразливостей за 40 хвилинQA Fest 2019. Сергій Короленко. Топ веб вразливостей за 40 хвилин
QA Fest 2019. Сергій Короленко. Топ веб вразливостей за 40 хвилинQAFest
 
QA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The Future
QA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The FutureQA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The Future
QA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The FutureQAFest
 
QA Fest 2019. Doug Sillars. It's just too Slow: Testing Mobile application pe...
QA Fest 2019. Doug Sillars. It's just too Slow: Testing Mobile application pe...QA Fest 2019. Doug Sillars. It's just too Slow: Testing Mobile application pe...
QA Fest 2019. Doug Sillars. It's just too Slow: Testing Mobile application pe...QAFest
 
QA Fest 2019. Катерина Спринсян. Параллельное покрытие автотестами и другие и...
QA Fest 2019. Катерина Спринсян. Параллельное покрытие автотестами и другие и...QA Fest 2019. Катерина Спринсян. Параллельное покрытие автотестами и другие и...
QA Fest 2019. Катерина Спринсян. Параллельное покрытие автотестами и другие и...QAFest
 
QA Fest 2019. Никита Галкин. Как зарабатывать больше
QA Fest 2019. Никита Галкин. Как зарабатывать большеQA Fest 2019. Никита Галкин. Как зарабатывать больше
QA Fest 2019. Никита Галкин. Как зарабатывать большеQAFest
 
QA Fest 2019. Сергей Пирогов. Why everything is spoiled
QA Fest 2019. Сергей Пирогов. Why everything is spoiledQA Fest 2019. Сергей Пирогов. Why everything is spoiled
QA Fest 2019. Сергей Пирогов. Why everything is spoiledQAFest
 
QA Fest 2019. Сергей Новик. Между мотивацией и выгоранием
QA Fest 2019. Сергей Новик. Между мотивацией и выгораниемQA Fest 2019. Сергей Новик. Между мотивацией и выгоранием
QA Fest 2019. Сергей Новик. Между мотивацией и выгораниемQAFest
 
QA Fest 2019. Владимир Никонов. Код Шредингера или зачем и как мы тестируем н...
QA Fest 2019. Владимир Никонов. Код Шредингера или зачем и как мы тестируем н...QA Fest 2019. Владимир Никонов. Код Шредингера или зачем и как мы тестируем н...
QA Fest 2019. Владимир Никонов. Код Шредингера или зачем и как мы тестируем н...QAFest
 
QA Fest 2019. Владимир Трандафилов. GUI automation of WEB application with SV...
QA Fest 2019. Владимир Трандафилов. GUI automation of WEB application with SV...QA Fest 2019. Владимир Трандафилов. GUI automation of WEB application with SV...
QA Fest 2019. Владимир Трандафилов. GUI automation of WEB application with SV...QAFest
 
QA Fest 2019. Иван Крутов. Bulletproof Selenium Cluster
QA Fest 2019. Иван Крутов. Bulletproof Selenium ClusterQA Fest 2019. Иван Крутов. Bulletproof Selenium Cluster
QA Fest 2019. Иван Крутов. Bulletproof Selenium ClusterQAFest
 
QA Fest 2019. Николай Мижигурский. Миссия /*не*/выполнима: гуманитарий собесе...
QA Fest 2019. Николай Мижигурский. Миссия /*не*/выполнима: гуманитарий собесе...QA Fest 2019. Николай Мижигурский. Миссия /*не*/выполнима: гуманитарий собесе...
QA Fest 2019. Николай Мижигурский. Миссия /*не*/выполнима: гуманитарий собесе...QAFest
 
QA Fest 2019. Володимир Стиран. Чим раніше – тим вигідніше, але ніколи не піз...
QA Fest 2019. Володимир Стиран. Чим раніше – тим вигідніше, але ніколи не піз...QA Fest 2019. Володимир Стиран. Чим раніше – тим вигідніше, але ніколи не піз...
QA Fest 2019. Володимир Стиран. Чим раніше – тим вигідніше, але ніколи не піз...QAFest
 
QA Fest 2019. Дмитрий Прокопук. Mocks and network tricks in UI automation
QA Fest 2019. Дмитрий Прокопук. Mocks and network tricks in UI automationQA Fest 2019. Дмитрий Прокопук. Mocks and network tricks in UI automation
QA Fest 2019. Дмитрий Прокопук. Mocks and network tricks in UI automationQAFest
 
QA Fest 2019. Екатерина Дядечко. Тестирование медицинского софта — вызовы и в...
QA Fest 2019. Екатерина Дядечко. Тестирование медицинского софта — вызовы и в...QA Fest 2019. Екатерина Дядечко. Тестирование медицинского софта — вызовы и в...
QA Fest 2019. Екатерина Дядечко. Тестирование медицинского софта — вызовы и в...QAFest
 
QA Fest 2019. Катерина Черникова. Tune your P’s: the pop-art of keeping testa...
QA Fest 2019. Катерина Черникова. Tune your P’s: the pop-art of keeping testa...QA Fest 2019. Катерина Черникова. Tune your P’s: the pop-art of keeping testa...
QA Fest 2019. Катерина Черникова. Tune your P’s: the pop-art of keeping testa...QAFest
 
QA Fest 2019. Алиса Бойко. Какнезапутаться в коммуникативных сетях IT
QA Fest 2019. Алиса Бойко. Какнезапутаться в коммуникативных сетях ITQA Fest 2019. Алиса Бойко. Какнезапутаться в коммуникативных сетях IT
QA Fest 2019. Алиса Бойко. Какнезапутаться в коммуникативных сетях ITQAFest
 
QA Fest 2019. Святослав Логин. Как найти уязвимости в мобильном приложении
QA Fest 2019. Святослав Логин. Как найти уязвимости в мобильном приложенииQA Fest 2019. Святослав Логин. Как найти уязвимости в мобильном приложении
QA Fest 2019. Святослав Логин. Как найти уязвимости в мобильном приложенииQAFest
 
QA Fest 2019. Катерина Шепелєва та Інна Оснач. Що українцям потрібно знати пр...
QA Fest 2019. Катерина Шепелєва та Інна Оснач. Що українцям потрібно знати пр...QA Fest 2019. Катерина Шепелєва та Інна Оснач. Що українцям потрібно знати пр...
QA Fest 2019. Катерина Шепелєва та Інна Оснач. Що українцям потрібно знати пр...QAFest
 
QA Fest 2019. Антон Серпутько. Нагрузочное тестирование распределенных асинхр...
QA Fest 2019. Антон Серпутько. Нагрузочное тестирование распределенных асинхр...QA Fest 2019. Антон Серпутько. Нагрузочное тестирование распределенных асинхр...
QA Fest 2019. Антон Серпутько. Нагрузочное тестирование распределенных асинхр...QAFest
 
QA Fest 2019. Петр Тарасенко. QA Hackathon - The Cookbook 22
QA Fest 2019. Петр Тарасенко. QA Hackathon - The Cookbook 22QA Fest 2019. Петр Тарасенко. QA Hackathon - The Cookbook 22
QA Fest 2019. Петр Тарасенко. QA Hackathon - The Cookbook 22QAFest
 

More from QAFest (20)

QA Fest 2019. Сергій Короленко. Топ веб вразливостей за 40 хвилин
QA Fest 2019. Сергій Короленко. Топ веб вразливостей за 40 хвилинQA Fest 2019. Сергій Короленко. Топ веб вразливостей за 40 хвилин
QA Fest 2019. Сергій Короленко. Топ веб вразливостей за 40 хвилин
 
QA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The Future
QA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The FutureQA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The Future
QA Fest 2019. Анна Чернышова. Self-healing test automation 2.0. The Future
 
QA Fest 2019. Doug Sillars. It's just too Slow: Testing Mobile application pe...
QA Fest 2019. Doug Sillars. It's just too Slow: Testing Mobile application pe...QA Fest 2019. Doug Sillars. It's just too Slow: Testing Mobile application pe...
QA Fest 2019. Doug Sillars. It's just too Slow: Testing Mobile application pe...
 
QA Fest 2019. Катерина Спринсян. Параллельное покрытие автотестами и другие и...
QA Fest 2019. Катерина Спринсян. Параллельное покрытие автотестами и другие и...QA Fest 2019. Катерина Спринсян. Параллельное покрытие автотестами и другие и...
QA Fest 2019. Катерина Спринсян. Параллельное покрытие автотестами и другие и...
 
QA Fest 2019. Никита Галкин. Как зарабатывать больше
QA Fest 2019. Никита Галкин. Как зарабатывать большеQA Fest 2019. Никита Галкин. Как зарабатывать больше
QA Fest 2019. Никита Галкин. Как зарабатывать больше
 
QA Fest 2019. Сергей Пирогов. Why everything is spoiled
QA Fest 2019. Сергей Пирогов. Why everything is spoiledQA Fest 2019. Сергей Пирогов. Why everything is spoiled
QA Fest 2019. Сергей Пирогов. Why everything is spoiled
 
QA Fest 2019. Сергей Новик. Между мотивацией и выгоранием
QA Fest 2019. Сергей Новик. Между мотивацией и выгораниемQA Fest 2019. Сергей Новик. Между мотивацией и выгоранием
QA Fest 2019. Сергей Новик. Между мотивацией и выгоранием
 
QA Fest 2019. Владимир Никонов. Код Шредингера или зачем и как мы тестируем н...
QA Fest 2019. Владимир Никонов. Код Шредингера или зачем и как мы тестируем н...QA Fest 2019. Владимир Никонов. Код Шредингера или зачем и как мы тестируем н...
QA Fest 2019. Владимир Никонов. Код Шредингера или зачем и как мы тестируем н...
 
QA Fest 2019. Владимир Трандафилов. GUI automation of WEB application with SV...
QA Fest 2019. Владимир Трандафилов. GUI automation of WEB application with SV...QA Fest 2019. Владимир Трандафилов. GUI automation of WEB application with SV...
QA Fest 2019. Владимир Трандафилов. GUI automation of WEB application with SV...
 
QA Fest 2019. Иван Крутов. Bulletproof Selenium Cluster
QA Fest 2019. Иван Крутов. Bulletproof Selenium ClusterQA Fest 2019. Иван Крутов. Bulletproof Selenium Cluster
QA Fest 2019. Иван Крутов. Bulletproof Selenium Cluster
 
QA Fest 2019. Николай Мижигурский. Миссия /*не*/выполнима: гуманитарий собесе...
QA Fest 2019. Николай Мижигурский. Миссия /*не*/выполнима: гуманитарий собесе...QA Fest 2019. Николай Мижигурский. Миссия /*не*/выполнима: гуманитарий собесе...
QA Fest 2019. Николай Мижигурский. Миссия /*не*/выполнима: гуманитарий собесе...
 
QA Fest 2019. Володимир Стиран. Чим раніше – тим вигідніше, але ніколи не піз...
QA Fest 2019. Володимир Стиран. Чим раніше – тим вигідніше, але ніколи не піз...QA Fest 2019. Володимир Стиран. Чим раніше – тим вигідніше, але ніколи не піз...
QA Fest 2019. Володимир Стиран. Чим раніше – тим вигідніше, але ніколи не піз...
 
QA Fest 2019. Дмитрий Прокопук. Mocks and network tricks in UI automation
QA Fest 2019. Дмитрий Прокопук. Mocks and network tricks in UI automationQA Fest 2019. Дмитрий Прокопук. Mocks and network tricks in UI automation
QA Fest 2019. Дмитрий Прокопук. Mocks and network tricks in UI automation
 
QA Fest 2019. Екатерина Дядечко. Тестирование медицинского софта — вызовы и в...
QA Fest 2019. Екатерина Дядечко. Тестирование медицинского софта — вызовы и в...QA Fest 2019. Екатерина Дядечко. Тестирование медицинского софта — вызовы и в...
QA Fest 2019. Екатерина Дядечко. Тестирование медицинского софта — вызовы и в...
 
QA Fest 2019. Катерина Черникова. Tune your P’s: the pop-art of keeping testa...
QA Fest 2019. Катерина Черникова. Tune your P’s: the pop-art of keeping testa...QA Fest 2019. Катерина Черникова. Tune your P’s: the pop-art of keeping testa...
QA Fest 2019. Катерина Черникова. Tune your P’s: the pop-art of keeping testa...
 
QA Fest 2019. Алиса Бойко. Какнезапутаться в коммуникативных сетях IT
QA Fest 2019. Алиса Бойко. Какнезапутаться в коммуникативных сетях ITQA Fest 2019. Алиса Бойко. Какнезапутаться в коммуникативных сетях IT
QA Fest 2019. Алиса Бойко. Какнезапутаться в коммуникативных сетях IT
 
QA Fest 2019. Святослав Логин. Как найти уязвимости в мобильном приложении
QA Fest 2019. Святослав Логин. Как найти уязвимости в мобильном приложенииQA Fest 2019. Святослав Логин. Как найти уязвимости в мобильном приложении
QA Fest 2019. Святослав Логин. Как найти уязвимости в мобильном приложении
 
QA Fest 2019. Катерина Шепелєва та Інна Оснач. Що українцям потрібно знати пр...
QA Fest 2019. Катерина Шепелєва та Інна Оснач. Що українцям потрібно знати пр...QA Fest 2019. Катерина Шепелєва та Інна Оснач. Що українцям потрібно знати пр...
QA Fest 2019. Катерина Шепелєва та Інна Оснач. Що українцям потрібно знати пр...
 
QA Fest 2019. Антон Серпутько. Нагрузочное тестирование распределенных асинхр...
QA Fest 2019. Антон Серпутько. Нагрузочное тестирование распределенных асинхр...QA Fest 2019. Антон Серпутько. Нагрузочное тестирование распределенных асинхр...
QA Fest 2019. Антон Серпутько. Нагрузочное тестирование распределенных асинхр...
 
QA Fest 2019. Петр Тарасенко. QA Hackathon - The Cookbook 22
QA Fest 2019. Петр Тарасенко. QA Hackathon - The Cookbook 22QA Fest 2019. Петр Тарасенко. QA Hackathon - The Cookbook 22
QA Fest 2019. Петр Тарасенко. QA Hackathon - The Cookbook 22
 

Recently uploaded

Pharmacognosy Flower 3. Compositae 2023.pdf
Pharmacognosy Flower 3. Compositae 2023.pdfPharmacognosy Flower 3. Compositae 2023.pdf
Pharmacognosy Flower 3. Compositae 2023.pdfMahmoud M. Sallam
 
Final demo Grade 9 for demo Plan dessert.pptx
Final demo Grade 9 for demo Plan dessert.pptxFinal demo Grade 9 for demo Plan dessert.pptx
Final demo Grade 9 for demo Plan dessert.pptxAvyJaneVismanos
 
How to Configure Email Server in Odoo 17
How to Configure Email Server in Odoo 17How to Configure Email Server in Odoo 17
How to Configure Email Server in Odoo 17Celine George
 
Science 7 - LAND and SEA BREEZE and its Characteristics
Science 7 - LAND and SEA BREEZE and its CharacteristicsScience 7 - LAND and SEA BREEZE and its Characteristics
Science 7 - LAND and SEA BREEZE and its CharacteristicsKarinaGenton
 
Paris 2024 Olympic Geographies - an activity
Paris 2024 Olympic Geographies - an activityParis 2024 Olympic Geographies - an activity
Paris 2024 Olympic Geographies - an activityGeoBlogs
 
POINT- BIOCHEMISTRY SEM 2 ENZYMES UNIT 5.pptx
POINT- BIOCHEMISTRY SEM 2 ENZYMES UNIT 5.pptxPOINT- BIOCHEMISTRY SEM 2 ENZYMES UNIT 5.pptx
POINT- BIOCHEMISTRY SEM 2 ENZYMES UNIT 5.pptxSayali Powar
 
EPANDING THE CONTENT OF AN OUTLINE using notes.pptx
EPANDING THE CONTENT OF AN OUTLINE using notes.pptxEPANDING THE CONTENT OF AN OUTLINE using notes.pptx
EPANDING THE CONTENT OF AN OUTLINE using notes.pptxRaymartEstabillo3
 
BASLIQ CURRENT LOOKBOOK LOOKBOOK(1) (1).pdf
BASLIQ CURRENT LOOKBOOK  LOOKBOOK(1) (1).pdfBASLIQ CURRENT LOOKBOOK  LOOKBOOK(1) (1).pdf
BASLIQ CURRENT LOOKBOOK LOOKBOOK(1) (1).pdfSoniaTolstoy
 
Employee wellbeing at the workplace.pptx
Employee wellbeing at the workplace.pptxEmployee wellbeing at the workplace.pptx
Employee wellbeing at the workplace.pptxNirmalaLoungPoorunde1
 
Crayon Activity Handout For the Crayon A
Crayon Activity Handout For the Crayon ACrayon Activity Handout For the Crayon A
Crayon Activity Handout For the Crayon AUnboundStockton
 
History Class XII Ch. 3 Kinship, Caste and Class (1).pptx
History Class XII Ch. 3 Kinship, Caste and Class (1).pptxHistory Class XII Ch. 3 Kinship, Caste and Class (1).pptx
History Class XII Ch. 3 Kinship, Caste and Class (1).pptxsocialsciencegdgrohi
 
Blooming Together_ Growing a Community Garden Worksheet.docx
Blooming Together_ Growing a Community Garden Worksheet.docxBlooming Together_ Growing a Community Garden Worksheet.docx
Blooming Together_ Growing a Community Garden Worksheet.docxUnboundStockton
 
Introduction to ArtificiaI Intelligence in Higher Education
Introduction to ArtificiaI Intelligence in Higher EducationIntroduction to ArtificiaI Intelligence in Higher Education
Introduction to ArtificiaI Intelligence in Higher Educationpboyjonauth
 
Introduction to AI in Higher Education_draft.pptx
Introduction to AI in Higher Education_draft.pptxIntroduction to AI in Higher Education_draft.pptx
Introduction to AI in Higher Education_draft.pptxpboyjonauth
 
Hybridoma Technology ( Production , Purification , and Application )
Hybridoma Technology  ( Production , Purification , and Application  ) Hybridoma Technology  ( Production , Purification , and Application  )
Hybridoma Technology ( Production , Purification , and Application ) Sakshi Ghasle
 
How to Make a Pirate ship Primary Education.pptx
How to Make a Pirate ship Primary Education.pptxHow to Make a Pirate ship Primary Education.pptx
How to Make a Pirate ship Primary Education.pptxmanuelaromero2013
 
Incoming and Outgoing Shipments in 1 STEP Using Odoo 17
Incoming and Outgoing Shipments in 1 STEP Using Odoo 17Incoming and Outgoing Shipments in 1 STEP Using Odoo 17
Incoming and Outgoing Shipments in 1 STEP Using Odoo 17Celine George
 

Recently uploaded (20)

Pharmacognosy Flower 3. Compositae 2023.pdf
Pharmacognosy Flower 3. Compositae 2023.pdfPharmacognosy Flower 3. Compositae 2023.pdf
Pharmacognosy Flower 3. Compositae 2023.pdf
 
Final demo Grade 9 for demo Plan dessert.pptx
Final demo Grade 9 for demo Plan dessert.pptxFinal demo Grade 9 for demo Plan dessert.pptx
Final demo Grade 9 for demo Plan dessert.pptx
 
TataKelola dan KamSiber Kecerdasan Buatan v022.pdf
TataKelola dan KamSiber Kecerdasan Buatan v022.pdfTataKelola dan KamSiber Kecerdasan Buatan v022.pdf
TataKelola dan KamSiber Kecerdasan Buatan v022.pdf
 
How to Configure Email Server in Odoo 17
How to Configure Email Server in Odoo 17How to Configure Email Server in Odoo 17
How to Configure Email Server in Odoo 17
 
Science 7 - LAND and SEA BREEZE and its Characteristics
Science 7 - LAND and SEA BREEZE and its CharacteristicsScience 7 - LAND and SEA BREEZE and its Characteristics
Science 7 - LAND and SEA BREEZE and its Characteristics
 
Paris 2024 Olympic Geographies - an activity
Paris 2024 Olympic Geographies - an activityParis 2024 Olympic Geographies - an activity
Paris 2024 Olympic Geographies - an activity
 
POINT- BIOCHEMISTRY SEM 2 ENZYMES UNIT 5.pptx
POINT- BIOCHEMISTRY SEM 2 ENZYMES UNIT 5.pptxPOINT- BIOCHEMISTRY SEM 2 ENZYMES UNIT 5.pptx
POINT- BIOCHEMISTRY SEM 2 ENZYMES UNIT 5.pptx
 
Model Call Girl in Tilak Nagar Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Tilak Nagar Delhi reach out to us at 🔝9953056974🔝Model Call Girl in Tilak Nagar Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Tilak Nagar Delhi reach out to us at 🔝9953056974🔝
 
EPANDING THE CONTENT OF AN OUTLINE using notes.pptx
EPANDING THE CONTENT OF AN OUTLINE using notes.pptxEPANDING THE CONTENT OF AN OUTLINE using notes.pptx
EPANDING THE CONTENT OF AN OUTLINE using notes.pptx
 
BASLIQ CURRENT LOOKBOOK LOOKBOOK(1) (1).pdf
BASLIQ CURRENT LOOKBOOK  LOOKBOOK(1) (1).pdfBASLIQ CURRENT LOOKBOOK  LOOKBOOK(1) (1).pdf
BASLIQ CURRENT LOOKBOOK LOOKBOOK(1) (1).pdf
 
Employee wellbeing at the workplace.pptx
Employee wellbeing at the workplace.pptxEmployee wellbeing at the workplace.pptx
Employee wellbeing at the workplace.pptx
 
Crayon Activity Handout For the Crayon A
Crayon Activity Handout For the Crayon ACrayon Activity Handout For the Crayon A
Crayon Activity Handout For the Crayon A
 
History Class XII Ch. 3 Kinship, Caste and Class (1).pptx
History Class XII Ch. 3 Kinship, Caste and Class (1).pptxHistory Class XII Ch. 3 Kinship, Caste and Class (1).pptx
History Class XII Ch. 3 Kinship, Caste and Class (1).pptx
 
Blooming Together_ Growing a Community Garden Worksheet.docx
Blooming Together_ Growing a Community Garden Worksheet.docxBlooming Together_ Growing a Community Garden Worksheet.docx
Blooming Together_ Growing a Community Garden Worksheet.docx
 
Introduction to ArtificiaI Intelligence in Higher Education
Introduction to ArtificiaI Intelligence in Higher EducationIntroduction to ArtificiaI Intelligence in Higher Education
Introduction to ArtificiaI Intelligence in Higher Education
 
Introduction to AI in Higher Education_draft.pptx
Introduction to AI in Higher Education_draft.pptxIntroduction to AI in Higher Education_draft.pptx
Introduction to AI in Higher Education_draft.pptx
 
Hybridoma Technology ( Production , Purification , and Application )
Hybridoma Technology  ( Production , Purification , and Application  ) Hybridoma Technology  ( Production , Purification , and Application  )
Hybridoma Technology ( Production , Purification , and Application )
 
How to Make a Pirate ship Primary Education.pptx
How to Make a Pirate ship Primary Education.pptxHow to Make a Pirate ship Primary Education.pptx
How to Make a Pirate ship Primary Education.pptx
 
9953330565 Low Rate Call Girls In Rohini Delhi NCR
9953330565 Low Rate Call Girls In Rohini  Delhi NCR9953330565 Low Rate Call Girls In Rohini  Delhi NCR
9953330565 Low Rate Call Girls In Rohini Delhi NCR
 
Incoming and Outgoing Shipments in 1 STEP Using Odoo 17
Incoming and Outgoing Shipments in 1 STEP Using Odoo 17Incoming and Outgoing Shipments in 1 STEP Using Odoo 17
Incoming and Outgoing Shipments in 1 STEP Using Odoo 17
 

QA Fest 2019. Антон Молдован. Load testing which you always wanted

  • 1. which you always wanted LOAD TESTING by @antyadev
  • 2.
  • 4.
  • 5.
  • 6. select * from Games where isLive = true order by totalBets desc limit 10 PUSH changes
  • 8. • Document size ~15Kb • 5K sport games available for betting • 73K markets (categories of bets) • 500K selections (positions to win an event) • Up to 1M incoming events per minute consumed by one process • 10K outgoing events per second • 10TB of streaming data per day
  • 9. { update } { push } { pull } Data Consistency Problem
  • 10. { update } { push } { pull } Data Propagation Problem DB
  • 11. Agenda - The real need of load testing - Load testing basics - Current state of load testing on 2019 - NBomber – your drug to load testing
  • 12. Do you know how many concurrent requests your service can handle?
  • 13. The real need of Load Testing - Choose technology stack - Prove architecture design (POC) - System regression (CI/CD pipeline) - Explore system limits
  • 14. Load Testing basics - in many cases, you don’t need a cluster - make sure that targeting node is fully loaded (100% CPU) to get max RPS - make sure that you have long running tests - make sure that you have controllability (your test input/output should be consistent)
  • 17. Current state of Load Testing Gatling (open-source, Scala, Akka): - free + commercial version - test as code - very good for HTTP (has API for WebSockets, SSE) - very nice reports - has integration with Grafana, Jenkins - has UI recorder to playback actions - no back pressure - not easy to customize - no cluster in free version
  • 18. class BasicSimulation extends Simulation { val httpConf = http .baseURL("http://computer-database.gatling.io") .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" .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/ val scn = scenario("BasicSimulation") .exec( http("request_1").get("/")) .pause(5) setUp( scn.inject(atOnceUsers(1)) ).protocols(httpConf) }
  • 19. Current state of Load Testing - Easy to cover HTTP only systems - Hard to cover any other Pull/Push systems - Complicated and not flexible API - Limited cluster support (different workloads)
  • 20. Current state of Load Testing - Easy to cover HTTP only systems - Hard to cover any other Pull/Push systems - Complicated and not flexible API - Limited cluster support
  • 21. Batch Update Process 1 Batch Update Process 3 MongoDB Batch Update Process 2 insert read read
  • 24.
  • 27. let start = getCurrentTimer() execFunc() let end = getCurrentTimer() let latency = end - start
  • 28. let start = getCurrentTimer() sendHttpReqeust() let end = getCurrentTimer() let latency = end - start
  • 29. let start = getCurrentTimer() queryMongoDb() let end = getCurrentTimer() let latency = end - start
  • 30. let start = getCurrentTimer() publishToKafka() let end = getCurrentTimer() let latency = end - start
  • 31. let start = getCurrentTimer() let! response = websockets.ReceivePush() let end = getCurrentTimer() let latency = end - start
  • 32. Load test any system https://nbomber.com PM> Install-Package NBomber
  • 33. Why another {x} framework for load testing? The main reasons are: - To be technology agnostic as much as possible (no dependency on any protocol: HTTP, WebSockets, SSE etc). - To be able to test .NET implementation of specific driver. During testing, it was identified many times that the performance could be slightly different because of the virtual machine(.NET, Java, PHP, Js, Erlang, different settings for GC) or just quality of drivers. For example there were cases that drivers written in C++ and invoked from NodeJs app worked faster than drivers written in C#/.NET. Therefore, it does make sense to load test your app using your concrete driver and runtime.
  • 34. - Technology agnostic (no dependency on HTTP, WebSockets, SSE) - Very simple API (to test Pull and Push scenarios) - CI/CD integration
  • 35. Pull and Push Scenarios xUnit/NUnit integration Sequential flow ReportingDistributed clusterPlugins Features
  • 36. type Scenario = { ScenarioName: string TestInit: (ScenarioContext -> Task) option TestClean: (ScenarioContext -> Task) option Steps: Step[] // these steps will be executed sequentially Assertions: Assertion[] ConcurrentCopies: int WarmupDuration: TimeSpan Duration: TimeSpan } type Step = { StepName: string Execute: StepContext -> Task<Response> } Very simple API
  • 37. Very simple API Step.Create("step", () => {...}) ScenarioBuilder .CreateScenario("scenario", step1, step2) .WithConcurrentCopies(10) .WithDuration(TimeSpan.FromSeconds(60)) NBomberRunner.RegisterScenarios(scenario) .RunInConsole(); Step.create("step", fun () -> {...}) Scenario.create("scenario", [step1; step2]) |> Scenario.withConcurrentCopies(10) |> Scenario.withDuration(TimeSpan.FromSeconds(60)) NBomberRunner.registerScenario(scenario) |> NBomberRunner.runInConsole
  • 40. Scenario Step 3Step 1 Step 2 } while true {
  • 41. var scenario = ScenarioBuilder .CreateScenario("Hello World from NBomber!", step) .WithConcurrentCopies(10) .WithDuration(TimeSpan.FromSeconds(10)); var step = Step.Create("simple step", async context => { // you can do any logic here: go to http, websocket etc await Task.Delay(TimeSpan.FromSeconds(0.1)); return Response.Ok(); }); NBomberRunner.RegisterScenarios(scenario) .RunInConsole();
  • 42. let step = Step.create("simple step", fun context -> task { // you can do any logic here: go to http, websocket etc do! Task.Delay(TimeSpan.FromSeconds(0.1)) return Response.Ok() }) Scenario.create("Hello World from NBomber!", [step]) |> Scenario.withConcurrentCopies(10) |> Scenario.withDuration(TimeSpan.FromSeconds(10.0)) |> NBomberRunner.registerScenario |> NBomberRunner.runInConsole
  • 45. var client = new HttpClient(); var step1 = Step.Create("GET html", async context => { var request = new HttpRequestMessage(HttpMethod.Get, "https://nbomber.com"); var response = await client.SendAsync(request); return response.IsSuccessStatusCode ? Response.Ok() : Response.Fail(); }); var scenario = ScenarioBuilder.CreateScenario("test_nbomber", step1); NBomberRunner.RegisterScenarios(scenario) .RunInConsole(); Http example
  • 46. Assertions[Test] public void Test() { var assertions = new[] { Assertion.ForStep("simple step", stats => stats.OkCount > 2), Assertion.ForStep("simple step", stats => stats.RPS > 8), Assertion.ForStep("simple step", stats => stats.Min > 8), Assertion.ForStep("simple step", stats => stats.Max > 8), Assertion.ForStep("simple step", stats => stats.Percent95 >= 102), Assertion.ForStep("simple step", stats => stats.DataMinKb == 1.0), Assertion.ForStep("simple step", stats => stats.AllDataMB >= 0.01) }; var scenario = BuildScenario() .WithConcurrentCopies(1) .WithWarmUpDuration(TimeSpan.FromSeconds(0)) .WithDuration(TimeSpan.FromSeconds(2)) .WithAssertions(assertions); NBomberRunner.RegisterScenarios(scenario) .RunTest(); }
  • 48. var client = new HttpClient(); var step1 = Step.Create("GET html", async context => { var request = new HttpRequestMessage(HttpMethod.Get, "https://nbomber.com"); var response = await client.SendAsync(request); return response.IsSuccessStatusCode ? Response.Ok() : Response.Fail(); }); var scenario = ScenarioBuilder.CreateScenario("test_nbomber", step1); NBomberRunner.RegisterScenarios(scenario) .RunInConsole(); Http example
  • 49. var step1 = HttpStep.Create("simple step", async (context) => Http.CreateRequest("GET", "https://nbomber.com") .WithHeader("accept", "application/json")); var scenario = ScenarioBuilder.CreateScenario("test_nbomber", step1); NBomberRunner.RegisterScenarios(scenario) .RunInConsole(); Nbomber.Http
  • 50.
  • 51.
  • 52.
  • 54. Batch Update Process 1 Batch Update Process 3 MongoDB Batch Update Process 2 write read read
  • 55. var insertStep = Step.Create("insert", async context => { await mongoCollection.InsertManyAsync { ... }; }); var pause_200 = Step.Create("pause 200", async context => { await Task.Delay(TimeSpan.FromMilliseconds(200)); }); var readStep = HttpStep.Create("TOP 100 games", async (context) => Http.CreateRequest("GET", "https://sbtech/games?top=100") .WithHeader("accept", "application/json")); // insert scenario: batch insert per 200 ms var insertScenario = ScenarioBuilder.CreateScenario("mongo", insertStep, pause_200); // read scenario: in parallel, we want to read data var readScenario = ScenarioBuilder.CreateScenario("http", readStep); NBomberRunner.RegisterScenarios(insertScenario, readScenario) .RunInConsole();
  • 62. { "ClusterSettings": { "Agent": { "ClusterId": "test_cluster", "TargetGroup": "group_1", "MqttServer": "104.155.3.33" } } } Agent Agent Agent Config
  • 63. Coordinator Config { "ClusterSettings": { "Coordinator": { "ClusterId": "test_cluster", "TargetScenarios": [ "mongo_insert" ] "Agents": [ { "TargetGroup": "group_1", "TargetScenarios": [ "mongo_read" ] } ] }, } } Coordinator
  • 65. var url = "ws://localhost:53231"; var webSocketsPool = ConnectionPool.Create("webSocketsPool", openConnection: () => { var ws = new ClientWebSocket(); ws.ConnectAsync(new Uri(url), CancellationToken.None).Wait(); return ws; }); var pingStep = Step.Create("ping", webSocketsPool, async context => { var msg = new WebSocketRequest { CorrelationId = context.CorrelationId, RequestType = RequestType.Ping }; await context.Connection.SendAsync(msg, WebSocketMessageType.Text); return Response.Ok(); });
  • 66. var pingStep = Step.Create("ping", webSocketsPool, async context => { var msg = new WebSocketRequest { CorrelationId = context.CorrelationId, RequestType = RequestType.Ping }; await context.Connection.SendAsync(msg, WebSocketMessageType.Text); return Response.Ok(); }); var pongStep = Step.Create("pong", webSocketsPool, async context => { while (true) { var message = await context.Connection.ReceiveMessage(); if (msg.CorrelationId == context.CorrelationId) { return Response.Ok(msg); } } });
  • 69. let run (dep: Dependency, context: NBomberContext) = asyncResult { let! ctx = Validation.validateContext(context) let! nodeStats = NBomberContext.tryGetClusterSettings(ctx) |> Option.map(function | Coordinator c -> runClusterCoordinator(dep, ctx, c) | Agent a -> runClusterAgent(dep, ctx, a)) |> Option.orElseWith(fun _ -> runSingleNode(dep, ctx)) |> Option.get return nodeStats |> calcStatistics(dep, ctx) |> saveStatistics(ctx) |> applyAsserts(ctx) |> buildReport(dep) |> saveReport(dep, ctx) } |> AsyncResult.mapError(handleError(dep)) |> Async.RunSynchronously |> ignore
  • 71. type Result<TOk, TError> = <!> <*> >>= >=>
  • 72. module ScenarioValidation = let validate (context: NBomberContext) = context.Scenarios |> checkEmptyName >>= checkDuplicateName >>= checkEmptyStepName >>= checkDuplicateStepName >>= checkDuration >>= checkConcurrentCopies >>= fun _ -> Ok context
  • 73. module GlobalSettingsValidation = let validate (context: NBomberContext) = context.NBomberConfig |> Option.bind(fun x -> x.GlobalSettings) |> Option.map(fun glSettings -> glSettings |> checkEmptyTarget >>= checkAvailableTarget >>= checkDuration >>= checkConcurrentCopies >>= checkEmptyReportName >>= fun _ -> Ok context ) |> Option.defaultValue(Ok context)
  • 74. module ScenarioValidation = let validate (context) = ... module GlobalSettingsValidation = let validate (context) = ... module Validation = let validate = ScenarioValidation.validate >=> GlobalSettingsValidation.validate
  • 76. type IClusterCoordinator = abstract StartNewSession: ScenarioSetting[] -> Task<Result<unit,Error>> abstract WaitOnAllAgentsReady: unit -> Task<Result<unit,Error>> abstract StartWarmUp: unit -> Task<Result<unit,Error>> abstract StartBombing: unit -> Task<Result<unit,Error>> abstract GetStatistics: unit -> Task<Result<NodeStats[],Error>>
  • 77. let runCoordinator (cluster: IClusterCoordinator, localHost: IScenariosHost, settings: ScenarioSetting[], targetScns: string[]) = asyncResult { do! cluster.SendStartNewSession(settings) do! localHost.InitScenarios(settings, targetScns) do! cluster.WaitOnAllAgentsReady() do! cluster.SendStartWarmUp() do! localHost.WarmUpScenarios() do! cluster.WaitOnAllAgentsReady() do! cluster.SendStartBombing() // Task<Result<unit,Error>> do! localHost.StartBombing() do! cluster.WaitOnAllAgentsReady() let localStats = localHost.GetStatistics() let! agentsStats = cluster.GetStatistics() let allStats = Array.append [|localStats|] agentsStats localHost.StopScenarios() return allStats }
  • 78. - (2663) LOC - (6) OOP objects - (~160) functions Summary
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.