Есть веб-api, непрерывно принимающее события (ограничимся 10000 событий) для группы аккаунтов (1000 аккаунтов) и складывающее их в очередь. Каждое событие связано с определённым аккаунтом и важно, чтобы события аккаунта обрабатывались в том же порядке, в котором поступили в очередь. Обработка события занимает 1 секунду (эмулировать с помощью sleep). Сделать обработку очереди событий максимально быстрой на данной конкретной машине. Код писать на PHP. Можно использовать фреймворки и инструменты такие как RabbitMQ, Redis, MySQL и т.д.
Задача решена посредством шардирования очереди, при помощи обменника (exchanger) с типом Consistent Hash. Особенность его в том, что он всегда будет отправлять сообщение с одним и тем же routing_key (в контексте задачи - это client_id) в ту же самую очередь. Таким образом, гарантируется порядок обработки сообщений для каждого клиента, при наличии только одного получателя на каждой очереди. Вместе с этим, за счёт разделения всех сообщений на отдельные очереди, достигается приемлемая скорость выполнения, но с сохранением консистентности данных.
# Склонировать репозиторий
git clone git@github.com:Subb98/BotHelp-Test-Task.git
# Перейти в директорию проекта
cd BotHelp-Test-Task
# Выдать доступ на выполнение для файлов в директории bin
chmod -R a+x bin/
# Запустить сборку проекта
docker compose up --build -d
# Примечание: если у вас старая версия Docker Compose, используйте команду с разделителем '-', docker-compose
# Проверить, что сборка успешна и контейнеры запущены
docker compose ps
# Дальнейшие команды выполнять из контейнера, для удобства, можно просто войти в него
docker exec -it bothelp-test-task.php sh
# Запустить генерирование клиентских сообщений:
./bin/console app:generate-client-messages 'data/client_messages.csv'
# Запустить отправку сгенерированных сообщений на Websocket server:
./bin/console app:send-client-messages 'data/client_messages.csv' start
# Запустить супервизор, который, в свою очередь, запустит получателей сообщений:
./bin/supervisor
# Логи работы супервизора будут находиться в data/supervisor.log, по ним можно будет проверить,
# выполняется ли порядок обработки событий для каждого конкретного клиента
В качестве Websocket-клиента для тестирования вручную можно использовать websocat.
Для подключения к серверу с SSL и самоподписным сертификатом необходимо использовать опцию --insecure
, пример:
websocat wss://0.0.0.0:8000 --insecure
Пример генерирования нового самоподписанного сертификата:
openssl req -newkey rsa:4096 \
-x509 \
-sha256 \
-days 3650 \
-nodes \
-out localhost.crt \
-keyout localhost.key \
-subj "/C=RU/ST=Perm Krai/L=Perm/O=OpenSSL/OU=0.0.0.0/CN=localhost"