-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: add performance test script (#84)
- Loading branch information
Showing
15 changed files
with
378 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,9 @@ | ||
.DS_Store | ||
|
||
.env | ||
*.pem | ||
|
||
src/performanceTest/results/* | ||
jacocoReport/ | ||
|
||
HELP.md | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# PerforanceTest | ||
|
||
You can refer to the [k6 documentation](https://k6.io/) for additional information. | ||
|
||
## Getting Started | ||
|
||
This performance test runs on Docker Engine. | ||
|
||
### 1. Start Docker Engine on your host | ||
|
||
### 2. Copy the `bastion.pem` File | ||
|
||
Copy the `bastion.pem` file to the `/src/performanceTest/initdb` directory. | ||
|
||
This file is a public key used to access AWS RDS for database initialization. | ||
|
||
### Configure Environment Variables | ||
|
||
Set the required environment variables, or create a `.env` file within the `/src/performanceTest/` directory. | ||
|
||
Here is an example `.env` file with placeholders: | ||
|
||
```dotenv | ||
MYSQL_HOST= | ||
MYSQL_PORT= | ||
MYSQL_USERNAME= | ||
MYSQL_PASSWORD= | ||
MYSQL_SCHEMA= | ||
BASTION_HOST= | ||
BASTION_USERNAME= | ||
HOST= | ||
# Monitoring Configuration (Optional) | ||
GRAFANA_HOST= | ||
K6_PROMETHEUS_RW_SERVER_URL= | ||
K6_PROMETHEUS_RW_USERNAME= | ||
K6_PROMETHEUS_RW_PASSWORD= | ||
``` | ||
|
||
### 4. Run the following commands | ||
|
||
|
||
Move to the `src/performanceTest` directory | ||
|
||
You can change the `ENTRYPOINT` variable to run different test files: | ||
|
||
|
||
```shell | ||
# To run the `a_test.js` file | ||
ENTRYPOINT=a_test.js docker-compose up | ||
|
||
# To run the `b_test.js` file | ||
ENTRYPOINT=b_test.js docker-compose up | ||
``` | ||
|
||
|
||
## Running K6 Scripts Independently | ||
|
||
If you want to run a K6 script **without Docker** and **without initializing the database**, you can use the following command: | ||
|
||
|
||
```sh | ||
# Install k6 on your host | ||
|
||
HOST=http://... k6 run scripts/healthCheck.js | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
version: '3' | ||
services: | ||
initdb: | ||
build: | ||
context: . | ||
dockerfile: ./initdb/Dockerfile | ||
volumes: | ||
- ./initdb/initdb.sh:/initdb.sh | ||
- ./initdb/sqls:/sqls | ||
- ./initdb/bastion.pem:/bastion.pem | ||
environment: | ||
MYSQL_HOST: ${MYSQL_HOST} | ||
MYSQL_PORT: ${MYSQL_PORT} | ||
MYSQL_USERNAME: ${MYSQL_USERNAME} | ||
MYSQL_PASSWORD: ${MYSQL_PASSWORD} | ||
MYSQL_SCHEMA: ${MYSQL_SCHEMA} | ||
BASTION_HOST: ${BASTION_HOST} | ||
BASTION_USERNAME: ${BASTION_USERNAME} | ||
|
||
k6: | ||
depends_on: | ||
initdb: | ||
condition: service_completed_successfully | ||
image: grafana/k6:latest | ||
volumes: | ||
- ./scripts:/scripts | ||
- ./results:/results | ||
environment: | ||
HOST: ${HOST} | ||
GRAFANA_HOST: ${GRAFANA_HOST} | ||
K6_PROMETHEUS_RW_SERVER_URL: ${K6_PROMETHEUS_RW_SERVER_URL} | ||
K6_PROMETHEUS_RW_USERNAME: ${K6_PROMETHEUS_RW_USERNAME} | ||
K6_PROMETHEUS_RW_PASSWORD: ${K6_PROMETHEUS_RW_PASSWORD} | ||
K6_PROMETHEUS_RW_TREND_AS_NATIVE_HISTOGRAM: true | ||
OUTPUT_HTML_DIR: "/results" | ||
command: run /scripts/${ENTRYPOINT} -o experimental-prometheus-rw | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
FROM ubuntu:22.04 | ||
|
||
# 패키지 설치 및 스크립트 복사 | ||
RUN apt-get update -y | ||
RUN apt-get install -y openssh-client mysql-client | ||
# RUN chmod 600 /bastion.pem | ||
|
||
# 스크립트 실행 | ||
CMD ["/bin/bash", "/initdb.sh"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#!/bin/bash | ||
|
||
MYSQL_HOST="$MYSQL_HOST" | ||
MYSQL_PORT="$MYSQL_PORT" | ||
MYSQL_USERNAME="$MYSQL_USERNAME" | ||
MYSQL_PASSWORD="$MYSQL_PASSWORD" | ||
MYSQL_SCHEMA="$MYSQL_SCHEMA" | ||
BASTION_HOST="$BASTION_HOST" | ||
BASTION_USERNAME="$BASTION_USERNAME" | ||
TUNNELING_PORT=30010 | ||
|
||
echo "Running initdb.sh" | ||
|
||
chmod 600 /bastion.pem | ||
ssh -i bastion.pem -CNf -L $TUNNELING_PORT:$MYSQL_HOST:$MYSQL_PORT $BASTION_USERNAME@$BASTION_HOST -o StrictHostKeyChecking=no | ||
|
||
mysql -h 127.0.0.1 -P $TUNNELING_PORT -u $MYSQL_USERNAME -p$MYSQL_PASSWORD -D $MYSQL_SCHEMA < /sqls/cleanup.sql | ||
mysql -h 127.0.0.1 -P $TUNNELING_PORT -u $MYSQL_USERNAME -p$MYSQL_PASSWORD -D $MYSQL_SCHEMA < /sqls/initdata.sql |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
USE ticketingdb; | ||
|
||
SET foreign_key_checks = 0; | ||
|
||
TRUNCATE user; | ||
TRUNCATE event; | ||
TRUNCATE bookmark; | ||
TRUNCATE reservation; | ||
|
||
SET foreign_key_checks = 1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
USE ticketingdb; | ||
|
||
INSERT INTO event (title, date, reservation_start_time, reservation_end_time, max_attendees, current_reservation_count) VALUES ('Concert', NOW(), NOW(), NOW(), 10, 0); | ||
INSERT INTO event (title, date, reservation_start_time, reservation_end_time, max_attendees, current_reservation_count) VALUES ('Concert', NOW(), NOW(), NOW(), 10, 0); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { check } from "k6"; | ||
import Request from "./lib/request.js"; | ||
import hooks from "./lib/hooks.js"; | ||
|
||
export const handleSummary = hooks.handleSummary | ||
|
||
export const options = { | ||
vus: 10, | ||
duration: '5s', | ||
}; | ||
|
||
export default function () { | ||
const req = new Request() | ||
const res = req.helthCheck() | ||
check(res, { "status == 200": (r) => r.status == 200 }); | ||
check(res, { "body == OK": (r) => r.body == "OK" }); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
const removeLastSlash = (str) => { | ||
if (str) { | ||
return str[str.length - 1] == "/" ? str.slice(0, -1) : str | ||
} | ||
return str | ||
} | ||
export default { | ||
START: new Date().valueOf(), | ||
HOST: removeLastSlash(__ENV.HOST), | ||
GRAFANA_HOST: removeLastSlash(__ENV.GRAFANA_HOST), | ||
OUTPUT_HTML_DIR: __ENV.OUTPUT_HTML_DIR || './results', | ||
DASHBOARD_DELAY: 1000 * 30 // 30 SEC | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
|
||
function uuid() { | ||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { | ||
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); | ||
return v.toString(16); | ||
}); | ||
} | ||
|
||
const getPrefix = () => { | ||
return `K6-${uuid().substring(0, 10)}`; | ||
} | ||
|
||
const User = () => ({ | ||
name: `${getPrefix()}-name`, | ||
email: `${getPrefix()}@email.com`, | ||
password: `${getPrefix()}-password`, | ||
}); | ||
|
||
export default { | ||
User | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
const getRandomByRange = (max) => Math.floor(Math.random() * max); | ||
|
||
export const getOneFromList = (list) => list[getRandomByRange(list.length)]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { htmlReport } from "https://raw.githubusercontent.com/benc-uk/k6-reporter/main/dist/bundle.js"; | ||
import { textSummary } from "https://jslib.k6.io/k6-summary/0.0.1/index.js"; | ||
import config from "./config.js"; | ||
|
||
export default { | ||
handleSummary: function(data) { | ||
const htmlPath = `${config.OUTPUT_HTML_DIR}/result.html` | ||
|
||
|
||
let Dahboard = '' | ||
if (config.GRAFANA_HOST) { | ||
const timeRange = `from=${config.START - config.DASHBOARD_DELAY}&to=${new Date().valueOf() + config.DASHBOARD_DELAY}` | ||
const query = `&orgId=1&refresh=10s&${timeRange}` | ||
Dahboard = ` | ||
------------------------DASHBOARD---------------------------- | ||
HTML : ${htmlPath} | ||
K6 : ${config.GRAFANA_HOST}/d/01npcT44k/official-k6-test-result?${query} | ||
CLUSTER: ${config.GRAFANA_HOST}/d/85a562078cdf77779eaa1add43ccec1e/kubernetes-compute-resources-namespace-pods?${query}&var-datasource=default&var-cluster=&var-namespace=default | ||
SPRING : ${config.GRAFANA_HOST}/d/OS7-NUiGz/spring-boot-statistics?${query} | ||
MYSQL : ${config.GRAFANA_HOST}/d/549c2bf8936f7767ea6ac47c47b00f2a/mysql-exporter?${query} | ||
------------------------------------------------------------- | ||
` | ||
} | ||
return { | ||
[htmlPath]: htmlReport(data), | ||
stdout: ` | ||
${Dahboard} | ||
${textSummary(data, { indent: " ", enableColors: true })} | ||
`, | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import http from "k6/http"; | ||
import { sleep } from "k6"; | ||
import config from "./config.js"; | ||
|
||
export default class Request { | ||
constructor(baseURL = config.HOST) { | ||
this.baseURL = baseURL | ||
this.Token = null | ||
this.SLEEP = 2 | ||
} | ||
|
||
beforeHook() { | ||
// do nothing | ||
} | ||
|
||
afterHook() { | ||
sleep(this.SLEEP) | ||
} | ||
|
||
setToken(token) { | ||
if (token.substring(0, 7) === 'Bearer '){ | ||
// set this.token = token without 'Bearer ' | ||
this.Token = token.substring(7); | ||
} | ||
else { | ||
this.Token = token; | ||
} | ||
} | ||
getToken() { | ||
return this.Token; | ||
} | ||
|
||
getHeaders() { | ||
const headers = { | ||
'Content-Type': 'application/json', | ||
} | ||
if (this.getToken() != null) { | ||
headers['Authorization'] = `Bearer ${this.getToken()}`; | ||
} | ||
return headers | ||
} | ||
|
||
getParams() { | ||
return { | ||
headers: this.getHeaders(), | ||
} | ||
} | ||
|
||
|
||
helthCheck() { | ||
this.beforeHook() | ||
const res= http.get(this.baseURL, this.getParams()) | ||
this.afterHook() | ||
return res | ||
} | ||
|
||
getEvents() { | ||
this.beforeHook() | ||
const res = http.get(`${this.baseURL}/events/`); | ||
this.afterHook() | ||
return res | ||
} | ||
signup(body) { | ||
this.beforeHook() | ||
const res = http.post(`${this.baseURL}/users/signup`, JSON.stringify(body), this.getParams()); | ||
this.afterHook() | ||
return res | ||
} | ||
signin(body) { | ||
this.beforeHook() | ||
const res = http.post(`${this.baseURL}/users/signin`, JSON.stringify({ email: body.email, password: body.password }), this.getParams()); | ||
this.setToken(res.json()['Authorization']) | ||
this.afterHook() | ||
return res | ||
} | ||
signout() { | ||
this.setToken(null) | ||
} | ||
access_token_info() { | ||
this.beforeHook() | ||
const res = http.get(`${this.baseURL}/users/access_token_info`, this.getParams()); | ||
this.afterHook() | ||
return res | ||
} | ||
createReservation(body) { | ||
this.beforeHook() | ||
const res = http.post(`${this.baseURL}/reservations`, JSON.stringify(body), this.getParams()); | ||
this.afterHook() | ||
return res | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { check } from "k6"; | ||
import Request from "./lib/request.js"; | ||
import generator from "./lib/generator.js"; | ||
import hooks from "./lib/hooks.js"; | ||
import { getOneFromList } from "./lib/helpers.js"; | ||
|
||
|
||
export const handleSummary = hooks.handleSummary | ||
|
||
export default function () { | ||
const req = new Request() | ||
|
||
const user = generator.User() | ||
req.signup(user) | ||
req.signin(user) | ||
|
||
const event = getOneFromList(req.getEvents().json()) | ||
|
||
const res = req.createReservation({ eventId: event.id }) | ||
check(res, { "status == 200": (r) => r.status == 200 }); | ||
check(res, { "created.eventId == event.id": (r) => r.json().eventId == event.id }); | ||
} |
Oops, something went wrong.