Skip to content

Commit

Permalink
Add stack files and load test scenario
Browse files Browse the repository at this point in the history
* The stack is deployed with docker swarm.
* The test scenarios are running with k6.
* Remove old load script bin/createLoad.
* Remove endpoints used exclusively by the old script.
  • Loading branch information
marein committed Sep 20, 2024
1 parent 099ff43 commit 6867dd2
Show file tree
Hide file tree
Showing 30 changed files with 737 additions and 274 deletions.
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,21 +307,23 @@ Sharding is done at the application level, more specifically in the
[repository](/src/ConnectFour/Port/Adapter/Persistence/Repository/DoctrineJsonGameRepository.php).
The application uses schema-based sharding and is aware of all existing logical shards,
while it's only aware of one physical connection. To actually forward queries to separate physical shards,
a proxy such as ProxySQL can be used. An example will be added with
[#118](https://github.com/marein/php-gaming-website/issues/118).
the application aims to use ProxySQL as a sidecar. An example can be found in the
[load test environment](/deploy/load-test).
__Example for chat__: Currently there shouldn't be queries that span multiple chats.
To invoke a chat operation (either writing or reading) we exclusively need a chat id.
As in connect four context, we can use
[sharding](https://en.wikipedia.org/wiki/Shard_(database_architecture))
for the chat context, where the chat id is the sharding key.

You may have seen that all contexts uses only one MySQL and one Redis instance.
This could be different for the production environment depending on the scale.
For this reason, different databases can be configured for the different contexts. Have a look at the
[configuration file](/.env).
We can split this even further.
For example, we can create a Redis instance per query model in the "Connect Four" context.
Of course, the code must be adapted. Whether it's worth it depends also on the scale.
In development, all contexts use only one MySQL and one Redis instance.
That is adjustable via environment variables, see
[here](/.env).
The
[load test environment](/deploy/load-test)
separates those storages. Even though in this example the MySQL servers point to the same host,
each context still uses a separate MySQL server. This works because the application itself talks to a
[ProxySQL sidecar](/deploy/load-test/stack/proxysql-sidecar.yml),
which forwards the queries to the MySQL server of the respective context.

## Chosen technologies

Expand Down
252 changes: 0 additions & 252 deletions bin/createLoad

This file was deleted.

6 changes: 0 additions & 6 deletions config/web-interface/routing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,3 @@ move:
methods: [POST]
controller: web-interface.connect-four-controller::moveAction
defaults: { _format: json }

game_json:
path: /api/connect-four/games/{gameId}
methods: [GET]
controller: web-interface.connect-four-controller::showAction
defaults: { _format: json }
48 changes: 48 additions & 0 deletions deploy/load-test/scenario/play-connect-four.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import http from 'k6/http';

const baseUrl = __ENV.BASE_URL;
const headers = {'Origin': baseUrl};
const jarPlayerOne = new http.CookieJar();
const jarPlayerTwo = new http.CookieJar();

export default function () {
const gameId = open(jarPlayerOne);
join(jarPlayerTwo, gameId);
move(jarPlayerOne, gameId, 1);
move(jarPlayerTwo, gameId, 2);
move(jarPlayerOne, gameId, 3);
move(jarPlayerTwo, gameId, 4);
move(jarPlayerOne, gameId, 5);
move(jarPlayerTwo, gameId, 6);
move(jarPlayerOne, gameId, 7);
move(jarPlayerTwo, gameId, 1);
move(jarPlayerOne, gameId, 2);
move(jarPlayerTwo, gameId, 3);
move(jarPlayerOne, gameId, 4);
move(jarPlayerTwo, gameId, 5);
move(jarPlayerOne, gameId, 6);
move(jarPlayerTwo, gameId, 7);
move(jarPlayerOne, gameId, 1);
move(jarPlayerTwo, gameId, 2);
move(jarPlayerOne, gameId, 3);
move(jarPlayerTwo, gameId, 4);
move(jarPlayerOne, gameId, 5);
move(jarPlayerTwo, gameId, 6);
move(jarPlayerOne, gameId, 7);
move(jarPlayerTwo, gameId, 1);
}

function open(jar) {
let url = `${baseUrl}/api/connect-four/games/open`;
return http.post(url, {}, {jar, headers}).json().gameId;
}

function join(jar, gameId) {
let url = `${baseUrl}/api/connect-four/games/${gameId}/join`;
return http.post(url, {}, {jar, headers});
}

function move(jar, gameId, column) {
let url = `${baseUrl}/api/connect-four/games/${gameId}/move`;
return http.post(url, {column}, {jar, headers});
}
24 changes: 24 additions & 0 deletions deploy/load-test/stack/app.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
APP_ENVIRONMENT=prod
APP_KERNEL_SECRET=ThisTokenIsNotSoSecretChangeIt
APP_WAIT_FOR=unix:///var/run/proxysql/proxysql.sock,chat-mysql:3306,connect-four-mysql-1:3306,connect-four-mysql-2:3306,connect-four-mysql-3:3306,connect-four-mysql-4:3306,connect-four-mysql-5:3306,identity-mysql:3306,chat-redis:6379,connect-four-redis:6379,web-interface-redis:6379,rabbitmq:5672,nchan:81
APP_RABBIT_MQ_DSN=amqp://guest:guest@rabbitmq:5672?heartbeat=60&prefetchCount=30

APP_CHAT_DOCTRINE_DBAL_URL=mysqli://root:password@localhost/chat?persistent=1&unix_socket=/var/run/proxysql/proxysql.sock
APP_CHAT_RUN_MIGRATIONS=1
APP_CHAT_PREDIS_CLIENT_URL=redis://chat-redis:6379?persistent=1

APP_CONNECT_FOUR_DOCTRINE_DBAL_URL=mysqli://root:password@localhost/%env(APP_CONNECT_FOUR_DOCTRINE_DBAL_DATABASE)%?persistent=1&unix_socket=/var/run/proxysql/proxysql.sock
APP_CONNECT_FOUR_DOCTRINE_DBAL_DATABASE=connect-four-1
APP_CONNECT_FOUR_DOCTRINE_DBAL_SHARDS=connect-four-1,connect-four-2,connect-four-3,connect-four-4,connect-four-5
APP_CONNECT_FOUR_RUN_MIGRATIONS=1
APP_CONNECT_FOUR_PREDIS_CLIENT_URL=redis://connect-four-redis:6379?persistent=1

APP_IDENTITY_DOCTRINE_DBAL_URL=mysqli://root:password@localhost/identity?persistent=1&unix_socket=/var/run/proxysql/proxysql.sock
APP_IDENTITY_RUN_MIGRATIONS=1

APP_WEB_INTERFACE_PREDIS_CLIENT_URL=redis://web-interface-redis:6379?persistent=1
APP_WEB_INTERFACE_NCHAN_BASE_URL=http://nchan:81
APP_WEB_INTERFACE_PUBLISH_TO_BROWSER_SHARDS=5

PHP_FPM_PM=static
PHP_FPM_PM_MAX_CHILDREN=96
27 changes: 27 additions & 0 deletions deploy/load-test/stack/chat/app.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
version: '3.4'

services:
chat-follow-event-store:
image: marein/php-gaming-website:php-fpm
command: bin/console chat:follow-event-store pointer all
env_file: ../app.env
volumes:
- proxysql.sock:/var/run/proxysql
deploy:
placement:
constraints:
- "node.labels.long-running==1"
chat-command:
image: marein/php-gaming-website:php-fpm
command: bin/console gaming:consume-messages chat.command -r 3
env_file: ../app.env
volumes:
- proxysql.sock:/var/run/proxysql
deploy:
replicas: 5
placement:
constraints:
- "node.labels.long-running==1"

volumes:
proxysql.sock:
Loading

0 comments on commit 6867dd2

Please sign in to comment.