Skip to content

Instantly share code, notes, and snippets.

@gunesmes
Last active September 4, 2023 00:03
Show Gist options
  • Save gunesmes/5ca7b25162ccddcf8d1bc0aa6b454a4c to your computer and use it in GitHub Desktop.
Save gunesmes/5ca7b25162ccddcf8d1bc0aa6b454a4c to your computer and use it in GitHub Desktop.
Run Locust in Dockers for performance testing.
docker run --rm --name locust -v $PWD:/locust gunesmes/docker-locust -f /locust/run.py --host=http://www.github.com --num-request=100 --clients=10 --hatch-rate=1 --only-summary --no-web
Unable to find image 'gunesmes/docker-locust:latest' locally
latest: Pulling from gunesmes/docker-locust
ff3a5c916c92: Already exists
471170bb1257: Already exists
a92899abaf42: Already exists
2699438859de: Already exists
d278818cf042: Pull complete
8259ad31f34c: Pull complete
c046ad017283: Pull complete
598e142854cf: Pull complete
8436236c1a7a: Pull complete
Digest: sha256:971a3c4967ba2cc02822e4aa305be7d806f8758760fcb7d8fd18d19529a40171
Status: Downloaded newer image for gunesmes/docker-locust:latest
[2018-05-31 22:53:12,324] 98f362038086/INFO/locust.main: Starting Locust 0.8.1
[2018-05-31 22:53:12,324] 98f362038086/INFO/locust.runners: Hatching and swarming 10 clients at the rate 1 clients/s...
[2018-05-31 22:53:22,354] 98f362038086/INFO/locust.runners: All locusts hatched: User: 10
[2018-05-31 22:53:22,354] 98f362038086/INFO/locust.runners: Resetting stats
[2018-05-31 22:53:50,986] 98f362038086/INFO/locust.runners: All locusts dead
[2018-05-31 22:53:50,987] 98f362038086/INFO/locust.main: Shutting down (exit code 0), bye.
Name # reqs # fails Avg Min Max | Median req/s
--------------------------------------------------------------------------------------------------------------------------------------------
GET / 13 0(0.00%) 1406 605 4334 | 680 0.20
GET /about/careers 1 0(0.00%) 1611 1611 1611 | 1600 0.00
GET /about/leadership 3 0(0.00%) 765 636 863 | 800 0.00
GET /about/press 3 0(0.00%) 754 736 783 | 740 0.00
GET /business 7 0(0.00%) 872 624 1259 | 760 0.30
GET /business/customers 3 0(0.00%) 701 656 778 | 670 0.00
GET /business/customers/mapbox 2 0(0.00%) 957 827 1087 | 830 0.10
GET /explore 2 0(0.00%) 1386 1221 1551 | 1200 0.00
GET /features 12 0(0.00%) 773 566 1059 | 770 0.40
GET /features/code-review 4 0(0.00%) 940 647 1124 | 880 0.20
GET /features/integrations 5 0(0.00%) 927 692 1678 | 750 0.10
GET /features/project-management 2 0(0.00%) 984 942 1026 | 940 0.10
GET /join?plan=business&setup_organization=true&source=business-page 5 0(0.00%) 690 621 738 | 720 0.30
GET /join?source=button-home 3 0(0.00%) 963 676 1533 | 680 0.20
GET /join?source=header-home 6 0(0.00%) 755 596 1095 | 700 0.20
GET /marketplace 2 0(0.00%) 1192 1146 1239 | 1100 0.00
GET /open-source 8 0(0.00%) 1032 666 1721 | 780 0.00
GET /open-source/stories/ariya 3 0(0.00%) 1470 826 2622 | 960 0.20
GET /open-source/stories/freakboy3742 3 0(0.00%) 1213 682 2260 | 700 0.20
GET /open-source/stories/jessfraz 5 0(0.00%) 1206 706 1591 | 1400 0.10
GET /open-source/stories/kris-nova 2 0(0.00%) 858 645 1071 | 640 0.20
GET /open-source/stories/yyx990803 2 0(0.00%) 762 703 822 | 700 0.00
GET /personal 8 0(0.00%) 788 612 1092 | 720 0.30
GET /pricing 1 0(0.00%) 601 601 601 | 600 0.10
GET /site/privacy 2 0(0.00%) 1199 1190 1208 | 1200 0.00
GET /site/terms 1 0(0.00%) 1286 1286 1286 | 1300 0.00
GET /ten 1 0(0.00%) 1095 1095 1095 | 1100 0.10
--------------------------------------------------------------------------------------------------------------------------------------------
Total 109 0(0.00%) 3.30
Percentage of the requests completed within given times
Name # reqs 50% 66% 75% 80% 90% 95% 98% 99% 100%
--------------------------------------------------------------------------------------------------------------------------------------------
GET / 13 680 710 1700 3000 3300 4300 4300 4300 4334
GET /about/careers 1 1600 1600 1600 1600 1600 1600 1600 1600 1611
GET /about/leadership 3 800 800 860 860 860 860 860 860 863
GET /about/press 3 740 740 780 780 780 780 780 780 783
GET /business 7 760 1000 1100 1100 1300 1300 1300 1300 1259
GET /business/customers 3 670 670 780 780 780 780 780 780 778
GET /business/customers/mapbox 2 1100 1100 1100 1100 1100 1100 1100 1100 1087
GET /explore 2 1600 1600 1600 1600 1600 1600 1600 1600 1551
GET /features 12 770 780 840 840 1000 1100 1100 1100 1059
GET /features/code-review 4 1100 1100 1100 1100 1100 1100 1100 1100 1124
GET /features/integrations 5 750 780 780 1700 1700 1700 1700 1700 1678
GET /features/project-management 2 1000 1000 1000 1000 1000 1000 1000 1000 1026
GET /join?plan=business&setup_organization=true&source=business-page 5 720 730 730 740 740 740 740 740 738
GET /join?source=button-home 3 680 680 1500 1500 1500 1500 1500 1500 1533
GET /join?source=header-home 6 720 720 810 810 1100 1100 1100 1100 1095
GET /marketplace 2 1200 1200 1200 1200 1200 1200 1200 1200 1239
GET /open-source 8 1000 1100 1600 1600 1700 1700 1700 1700 1721
GET /open-source/stories/ariya 3 960 960 2600 2600 2600 2600 2600 2600 2622
GET /open-source/stories/freakboy3742 3 700 700 2300 2300 2300 2300 2300 2300 2260
GET /open-source/stories/jessfraz 5 1400 1500 1500 1600 1600 1600 1600 1600 1591
GET /open-source/stories/kris-nova 2 1100 1100 1100 1100 1100 1100 1100 1100 1071
GET /open-source/stories/yyx990803 2 820 820 820 820 820 820 820 820 822
GET /personal 8 720 720 1100 1100 1100 1100 1100 1100 1092
GET /pricing 1 600 600 600 600 600 600 600 600 601
GET /site/privacy 2 1200 1200 1200 1200 1200 1200 1200 1200 1208
GET /site/terms 1 1300 1300 1300 1300 1300 1300 1300 1300 1286
GET /ten 1 1100 1100 1100 1100 1100 1100 1100 1100 1095
--------------------------------------------------------------------------------------------------------------------------------------------
FROM python:alpine3.7
RUN apk -U add ca-certificates python python-dev py-pip build-base && \
pip install --upgrade pip && \
pip install locustio pyzmq && \
apk del python-dev && \
rm -r /var/cache/apk/* && \
mkdir /locust
WORKDIR /locust
ADD . /locust
RUN apk add --update --no-cache g++ gcc libxslt-dev
RUN test -f requirements.txt && pip install -r requirements.txt; exit 0
EXPOSE 8089 5557 5558
ENTRYPOINT [ "/usr/local/bin/locust" ]
~/d/locust-docker-github (master ⚡=) locust --help
Usage: locust [options] [LocustClass [LocustClass2 ... ]]
Options:
-h, --help show this help message and exit
-H HOST, --host=HOST Host to load test in the following format:
http://10.21.32.33
--web-host=WEB_HOST Host to bind the web interface to. Defaults to '' (all
interfaces)
-P PORT, --port=PORT, --web-port=PORT
Port on which to run web host
-f LOCUSTFILE, --locustfile=LOCUSTFILE
Python module file to import, e.g. '../other.py'.
Default: locustfile
--csv=CSVFILEBASE, --csv-base-name=CSVFILEBASE
Store current request stats to files in CSV format.
--master Set locust to run in distributed mode with this
process as master
--slave Set locust to run in distributed mode with this
process as slave
--master-host=MASTER_HOST
Host or IP address of locust master for distributed
load testing. Only used when running with --slave.
Defaults to 127.0.0.1.
--master-port=MASTER_PORT
The port to connect to that is used by the locust
master for distributed load testing. Only used when
running with --slave. Defaults to 5557. Note that
slaves will also connect to the master node on this
port + 1.
--master-bind-host=MASTER_BIND_HOST
Interfaces (hostname, ip) that locust master should
bind to. Only used when running with --master.
Defaults to * (all available interfaces).
--master-bind-port=MASTER_BIND_PORT
Port that locust master should bind to. Only used when
running with --master. Defaults to 5557. Note that
Locust will also use this port + 1, so by default the
master node will bind to 5557 and 5558.
--expect-slaves=EXPECT_SLAVES
How many slaves master should expect to connect before
starting the test (only when --no-web used).
--no-web Disable the web interface, and instead start running
the test immediately. Requires -c and -r to be
specified.
-c NUM_CLIENTS, --clients=NUM_CLIENTS
Number of concurrent clients. Only used together with
--no-web
-r HATCH_RATE, --hatch-rate=HATCH_RATE
The rate per second in which clients are spawned. Only
used together with --no-web
-n NUM_REQUESTS, --num-request=NUM_REQUESTS
Number of requests to perform. Only used together with
--no-web
-L LOGLEVEL, --loglevel=LOGLEVEL
Choose between DEBUG/INFO/WARNING/ERROR/CRITICAL.
Default is INFO.
--logfile=LOGFILE Path to log file. If not set, log will go to
stdout/stderr
--print-stats Print stats in the console
--only-summary Only print the summary stats
--no-reset-stats Do not reset statistics once hatching has been
completed
-l, --list Show list of possible locust classes and exit
--show-task-ratio print table of the locust classes' task execution
ratio
--show-task-ratio-json
print json data of the locust classes' task execution
ratio
-V, --version show program's version number and exit
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
from locust import HttpLocust, TaskSet, task
from pyquery import PyQuery
from locust import events
from locust.stats import *
import random
import requests
import sys
# sys.settrace
sys.setrecursionlimit(10000000)
class UserBehaviour(TaskSet):
user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36'
links = []
def get_urls(self, url, locator, key):
re = self.client.get("/", headers = { 'User-Agent': self.user_agent })
# will parse the html and get the valid and host specific links
pq = PyQuery(re.content)
link_elements = pq(locator)
for link in link_elements:
if key in link.attrib and "http" not in link.attrib[key] and "javascript" not in link.attrib[key] and "/detay" not in link.attrib[key]:
self.links.append(link.attrib[key].strip(" "))
return self.links
def on_start(self):
self.links = self.get_urls("/", "a", "href")
@task(1)
def test_links(self):
# this is a task to run performance testing
# we will send http request to the url taken from the main page of you provided as host
try:
url = random.choice(self.links)
self.client.get(url,
headers = { "User-Agent": self.user_agent},
name = url.split("=")[0].split("?")[0]
)
except IndexError:
pass
def on_stop(self):
del links
class User(HttpLocust):
task_set = UserBehaviour
# for user behaviour
# we can assume that they wait 0.5 to 3 seconds on a page
min_wait = 500
max_wait = 3000
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment