#php #mysql #docker #nginx #docker-compose
#php #mysql #docker #nginx #docker-compose
Вопрос:
Что я сделал, так это перевел проект на работу с контейнерами docker. Проект довольно большой, и в итоге у меня получилось около 12 контейнеров.
И теперь на данный момент есть 2 идентичных сервера под управлением Ubuntu 18.04.
- На первом сервере проект развертывается как обычно: запускаются Nginx, PHP7.2-fpm, MySQL5.7 и другие сервисы.
- На втором сервере проект был поднят на docker
Суть проблемы в том, что при тестировании скорости обработки нескольких запросов на обоих серверах сервер в docker показывает гораздо худшую производительность.
Вот проект на исходном сервере (тест с ApacheBench n100 c100):
Server Software: nginx
Server Hostname: test.com
Server Port: 443
SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES128-GCM-SHA256,2048,128
TLS Server Name: test.com
Document Path: /
Document Length: 119121 bytes
Concurrency Level: 100
Time taken for tests: 1.827 seconds
Complete requests: 100
Failed requests: 0
Total transferred: 12038500 bytes
HTML transferred: 11912100 bytes
Requests per second: 54.74 [#/sec] (mean)
Time per request: 1826.828 [ms] (mean)
Time per request: 18.268 [ms] (mean, across all concurrent requests)
Transfer rate: 6435.39 [Kbytes/sec] received
Connection Times (ms)
min mean[ /-sd] median max
Connect: 144 152 4.4 152 160
Processing: 50 899 469.8 938 1660
Waiting: 48 896 469.7 936 1658
Total: 203 1051 473.8 1090 1819
Percentage of the requests served within a certain time (ms)
50% 1090
66% 1330
75% 1458
80% 1550
90% 1702
95% 1770
98% 1815
99% 1819
100% 1819 (longest request)
Вот проект docker (тест с ApacheBench n100 c100):
Server Software: nginx/1.19.1
Server Hostname: test-dev.com
Server Port: 443
SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES128-GCM-SHA256,2048,128
TLS Server Name: test-dev.com
Document Path: /
Document Length: 724822 bytes
Concurrency Level: 100
Time taken for tests: 12.573 seconds
Complete requests: 100
Failed requests: 99
(Connect: 0, Receive: 0, Length: 99, Exceptions: 0)
Non-2xx responses: 100
Total transferred: 72592310 bytes
HTML transferred: 72476910 bytes
Requests per second: 7.95 [#/sec] (mean)
Time per request: 12572.860 [ms] (mean)
Time per request: 125.729 [ms] (mean, across all concurrent requests)
Transfer rate: 5638.41 [Kbytes/sec] received
Connection Times (ms)
min mean[ /-sd] median max
Connect: 135 140 3.4 140 146
Processing: 1351 8110 3454.4 10254 12421
Waiting: 1338 8066 3443.4 10211 12416
Total: 1486 8250 3457.5 10397 12566
Percentage of the requests served within a certain time (ms)
50% 10397
66% 10789
75% 11078
80% 11260
90% 11801
95% 12334
98% 12519
99% 12566
100% 12566 (longest request)
Я уже просмотрел множество руководств, статей и прочего. Перепробовал много советов. Ничего не помогает.
- Переделка новой работы в docker
- Отключен отладчик в php
- Использовались разные версии docker-compose
- Правила настройки docker deamon
Все действия привели к достаточно хорошей скорости для одного пользователя. Но под нагрузкой docker работает просто ужасно медленно.
Вот docker-compose.yml (PHP, Mysql, Nginx расположены в задней части):
version: '3'
volumes:
dump:
services:
# ------------- Front --------------
# project base ------------------------------------
bb_base:
build:
context: ../front/project-base
dockerfile: Dockerfile
args:
- WORKDIR=${BB_BASE_WORKDIR}
container_name: ${BB_BASE_WORKDIR}
restart: always
working_dir: /var/www/${BB_BASE_WORKDIR}
volumes:
- ../front/project-base:/var/www/${BB_BASE_WORKDIR}
# project ui-kit ----------------------------------
bb_ui-kit:
build:
context: ../front/project-ui-kit
dockerfile: Dockerfile
args:
- WORKDIR=${BB_UI_KIT_WORKDIR}
container_name: ${BB_UI_KIT_WORKDIR}
restart: always
working_dir: /var/www/${BB_UI_KIT_WORKDIR}
volumes:
- ../front/project-ui-kit:/var/www/${BB_UI_KIT_WORKDIR}
- ../front/project-base:/var/www/${BB_BASE_WORKDIR}
command: sh /var/www/${BB_UI_KIT_WORKDIR}/entrypoint.sh
depends_on:
- bb_base
# project auth ----------------------------------
bb_auth:
build:
context: ../front/project-auth
dockerfile: Dockerfile
args:
- WORKDIR=${BB_AUTH_WORKDIR}
container_name: ${BB_AUTH_WORKDIR}
restart: always
working_dir: /var/www/${BB_AUTH_WORKDIR}
volumes:
- ../front/project-auth:/var/www/${BB_AUTH_WORKDIR}
- ../front/project-base:/var/www/${BB_BASE_WORKDIR}
- ../front/project-ui-kit:/var/www/${BB_UI_KIT_WORKDIR}
command: sh /var/www/${BB_AUTH_WORKDIR}/entrypoint.sh
depends_on:
- bb_ui-kit
# project crm ----------------------------------
bb_crm:
build:
context: ../front/project-crm
dockerfile: Dockerfile
args:
- WORKDIR=${BB_CRM_WORKDIR}
container_name: ${BB_CRM_WORKDIR}
restart: always
working_dir: /var/www/${BB_CRM_WORKDIR}
volumes:
- ../front/project-crm:/var/www/${BB_CRM_WORKDIR}
- ../front/project-base:/var/www/${BB_BASE_WORKDIR}
- ../front/project-ui-kit:/var/www/${BB_UI_KIT_WORKDIR}
command: sh /var/www/${BB_CRM_WORKDIR}/entrypoint.sh
depends_on:
- bb_ui-kit
# project link ----------------------------------
bb_link:
build:
context: ../front/project-link
dockerfile: Dockerfile
args:
- WORKDIR=${BB_LINK_WORKDIR}
container_name: ${BB_LINK_WORKDIR}
restart: always
working_dir: /var/www/${BB_LINK_WORKDIR}
volumes:
- ../front/project-link:/var/www/${BB_LINK_WORKDIR}
- ../front/project-base:/var/www/${BB_BASE_WORKDIR}
- ../front/project-ui-kit:/var/www/${BB_UI_KIT_WORKDIR}
command: sh /var/www/${BB_LINK_WORKDIR}/entrypoint.sh
depends_on:
- bb_ui-kit
# --------------- Back ----------------
# PHP -----------------------------------------------
bb_php:
user: "${USER_ID}:1000"
build:
context: ../back/project-back/images/php
dockerfile: Dockerfile
args:
- DOMAIN=${DOMAIN}
- ENV=${DOCKER_ENV}
container_name: ${BB_PHP_WORKDIR}
restart: always
# ports:
# - "${PORT_PHP}:9000"
working_dir: /var/www/${BB_PHP_WORKDIR}
volumes:
- ../back/project-back:/var/www/${BB_PHP_WORKDIR}
#- photos:/var/www/${BB_PHP_WORKDIR}/storage/app/photos-mount
depends_on:
- bb_mysql
# Nginx -----------------------------------------------
bb_nginx:
build:
context: ../back/project-back/images/nginx
dockerfile: Dockerfile
args:
- DOMAIN=${DOMAIN}
- ENV=${DOCKER_ENV}
- BACK_DIR=${BB_PHP_WORKDIR}
- LOCAL_DIR=${BB_NGINX_WORKDIR}
- LINK_DIR=${BB_LINK_WORKDIR}
- AUTH_DIR=${BB_AUTH_WORKDIR}
- CRM_DIR=${BB_CRM_WORKDIR}
container_name: ${BB_NGINX_WORKDIR}
restart: always
ports:
- "${PORT_HTTP}:80"
- "${PORT_HTTPS}:443"
working_dir: /var/www/${BB_NGINX_WORKDIR}
volumes:
- ../back/project-back:/var/www/${BB_NGINX_WORKDIR}
- ../front/project-crm:/var/www/${BB_CRM_WORKDIR}
- ../front/project-auth:/var/www/${BB_AUTH_WORKDIR}
- ../front/project-link:/var/www/${BB_LINK_WORKDIR}
depends_on:
- bb_php
# MySQL -------------------------------------------------
bb_mysql:
image: gitlab.project.ru:5050/project/backend/project/mysql:1.0
container_name: ${BB_MYSQL_WORKDIR}
restart: always
tty: true
ports:
- "${PORT_MYSQL}:3306"
volumes:
- dump:/var/lib/mysql
- ../back/project-back/images/mysql/mysql.cnf:/etc/mysql/conf.d/mysql.cnf
- ../back/project-back/images/mysql/mysqldump.cnf:/etc/mysql/conf.d/mysqldump.cnf
- ../back/project-back/images/mysql/optimize.cnf:/etc/mysql/conf.d/optimize.cnf
env_file:
- ../back/project-back/.env
# Redis -------------------------------------------------
bb_redis:
image: redis:6-alpine
container_name: ${BB_REDIS_WORKDIR}
restart: always
# ports:
# - "${PORT_REDIS}:6379"
volumes:
- ../back/project-back/images/redis/redis.conf:/redis.conf
depends_on:
- bb_php
- bb_mysql
command: [ "redis-server", "/redis.conf" ]
# Mysql-cron-backup --------------------------------------
bb_mysql_cron_backup:
build:
context: ../back/project-back/images/mysql-cron-backup
dockerfile: Dockerfile
container_name: ${BB_MYSQL_CRON_BACKUP}
restart: always
volumes:
- ${VOLUME_PATH}/backup:/backup
environment:
- MAX_BACKUPS=${MAX_BACKUPS}
- INIT_BACKUP=0
- CRON_TIME=*/15 * * * *
- GZIP_LEVEL=9
depends_on:
- bb_mysql
env_file:
- ../back/project-back/.env
# --------------- Services -------------
# Socket -----------------------------------------------
bb_socket:
build:
context: ../back/project-services/project-sockets
dockerfile: Dockerfile
container_name: ${BB_SOCKETS_WORKDIR}
restart: always
working_dir: /var/www/${BB_SOCKETS_WORKDIR}
volumes:
- ../back/project-services/project-sockets:/var/www/${BB_SOCKETS_WORKDIR}
# Recommend products ------------------------------------
bb_recommend:
image: prod_rec:latest
build:
context: ../back/project-services/project-recommendation
dockerfile: Dockerfile
container_name: ${BB_RECCOMEND_WORKDIR}
restart: always
ports:
- "${PORT_RP}:5000"
environment:
- FLASK_APP=${FLASK_APP}
- FLASK_DEBUG=${FLASK_DEBUG}
- SECRET_KEY=${SECRET_KEY}
- DATABASE_URL_APP=${DATABASE_URL_APP}
- DATABASE_URL_PROD=${DATABASE_URL_PROD}
volumes:
- ../back/project-services/project-recommendation/config.py:/home/prod_rec/config.py
- ../back/project-services/project-recommendation/app.py:/home/prod_rec/app.py
- ../back/project-services/project-recommendation/app:/home/prod_rec/app
- ../back/project-services/project-recommendation/migrations:/home/prod_rec/migrations
depends_on:
- bb_recommend_mysql
links:
- bb_recommend_mysql:dbserver
# Recommend products MySQL ------------------------------------
bb_recommend_mysql:
image: mysql/mysql-server:5.7
container_name: ${BB_RECCOMEND_MYSQL_WORKDIR}
restart: always
environment:
- MYSQL_ROOT_PASSWORD=${RP_MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=${RP_MYSQL_DATABASE}
- MYSQL_USER=${RP_MYSQL_USER}
- MYSQL_PASSWORD=${RP_MYSQL_MYSQL_PASSWORD}
volumes:
- ../back/project-services/project-recommendation/my.cnf:/etc/my.cnf:ro
# Cdek ----------------------------------------------
bb_cdek:
image: cdek:latest
build:
context: ../back/project-services/project-cdek
dockerfile: Dockerfile
container_name: ${BB_CDEK_WORKDIR}
restart: always
ports:
- "${PORT_CDEK}:8080"
env_file:
- ../back/project-services/project-cdek/.env
environment:
- DEBUG_VALUE=FALSE
volumes:
- ../back/project-services/project-cdek/flask_api.py:/home/cdek/cdek/flask_api.py
- ../back/project-services/project-cdek/boot.sh:/home/cdek/cdek/boot.sh
# MoySklad -----------------------------------------------
bb_moysklad:
image: moysklad:latest
build:
context: ../back/project-services/project-moysklad
dockerfile: Dockerfile
container_name: ${BB_MOYSKLAD_WORKDIR}
restart: always
ports:
- "${PORT_MOYSKLAD}:5000"
environment:
- QUART_APP=${QUART_APP}
- QUART_DEBUG=${QUART_DEBUG}
- SECRET_KEY=${MS_SECRET_KEY}
- ENV=${MS_ENV}
volumes:
- ../back/project-services/project-moysklad/app.py:/home/moysklad/app.py
- ../back/project-services/project-moysklad/webhook.log:/home/moysklad/webhook.log
- ../back/project-services/project-moysklad/async_file.py:/home/moysklad/async_file.py
- ../back/project-services/project-moysklad/config.py:/home/moysklad/config.py
- ../back/project-services/project-moysklad/start.py:/home/moysklad/start.py
Ну, в этом-то и проблема. Как решить проблему в скорости при высокой нагрузке на проект? Почему docker работает так медленно под нагрузкой? Есть идеи?
Если вам нужны дополнительные данные, я приложу их.
Комментарии:
1. Какого облачного провайдера вы используете? Используете ли вы VPS, управляемый самостоятельно?
2. Ограничивает ли ваш драйвер cgroup ресурсы контейнера? Вы можете запустить
docker stats
, чтобы увидеть показатели времени выполнения и, если настроено, ограничения ресурсов. Для лучшего мониторинга вы можете использовать cAdvisor для сбора статистики использования Prometheus из ваших контейнеров Docker. Кроме того, вы можете использовать Prometheus exporters для Nginx и MySQL, чтобы увидеть их поведение при запуске в разных средах.3. Похоже, вы пытаетесь использовать гибридную настройку, в которой вы переместили интерпретатор PHP внутрь уровня изоляции Docker, но все еще пытаетесь использовать свой хост-код. Удаляет ли большую часть
volumes:
справочной производительности? (Есть похожие вопросы, особенно о производительности PHP как на macOS, так и на WSL.)