Сколько RAM нужно для EasyAppointments
EasyAppointments — лёгкая open-source система онлайн-записи для услуг и специалистов: салоны, клиники, репетиторы, консультанты. Ставится за десять минут и на бумаге не требует почти ничего, поэтому многие берут сервер «с запасом в один клик» — минимальный тариф хостера — и потом удивляются, почему при пяти одновременных бронированиях сайт подвисает, а письма клиентам уходят с задержкой. Разберём, из чего реально складывается потребление памяти у EasyAppointments и сколько RAM закладывать под конкретное число специалистов и поток записей.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Из чего складывается потребление RAM у EasyAppointments
EasyAppointments — классическое PHP-приложение на CodeIgniter с MySQL/MariaDB в качестве хранилища и jQuery-фронтендом, который отдаётся статикой. Сама по себе логика простая: календарь, слоты, формы бронирования, — но вокруг неё есть несколько компонентов, которые вместе и формируют аппетит по памяти:
- Операционная система и базовые сервисы — 300-500 МБ на Ubuntu/Debian с nginx или Apache, systemd, ssh, минимальным набором пакетов.
- MySQL/MariaDB — хранит специалистов, услуги, рабочие часы, клиентов и сами записи. Нагрузка растёт не столько от объёма данных (таблицы у EasyAppointments небольшие), сколько от частоты запросов при проверке доступных слотов — это происходит при каждом открытии формы бронирования.
- PHP-FPM (или mod_php под Apache) — каждый воркер держит 20-35 МБ. Число одновременных воркеров определяется тем, сколько посетителей одновременно смотрят календарь и оформляют запись, плюс административная панель для специалистов.
- Синхронизация с Google Calendar и отправка email — по умолчанию EasyAppointments отправляет письмо клиенту и специалисту синхронно при создании записи (через PHPMailer/SMTP), а при включённой интеграции с Google Calendar каждое бронирование или изменение слота — это ещё один исходящий запрос к Google API. Каждый такой процесс недолго живёт, но при всплеске записей (например, после рассылки клиентам о новой услуге) это заметно нагружает PHP-FPM.
Само приложение лёгкое, и на статике (просмотр календаря без записи) почти не потребляет памяти сверх базового PHP-воркера. Узкое место почти всегда — MySQL при частых проверках занятости слотов и PHP-FPM в момент одновременного оформления нескольких броней.
Сколько RAM нужно для разных сценариев
Цифры ниже — ориентир по опыту эксплуатации похожих LAMP/LEMP-стеков с похожей структурой нагрузки (частые короткие запросы, лёгкая бизнес-логика). Точный расход зависит от числа специалистов, услуг с индивидуальными рабочими часами, того, включена ли синхронизация с Google Calendar, и от объёма истории записей.
| Сценарий | Специалистов | Записей/день | RAM | vCPU | Диск |
|---|---|---|---|---|---|
| Тест/пилот, один мастер | 1 | до 10 | 1 ГБ | 1 | 15-20 ГБ SSD |
| Малый бизнес (салон, кабинет) | 2-5 | 10-40 | 2 ГБ | 1-2 | 25-30 ГБ SSD |
| Сеть из нескольких точек | 5-15 | 40-150 | 4 ГБ | 2 | 40-60 ГБ SSD |
| Крупная сеть, Google Calendar sync у всех | 15-30 | 150-400 | 8 ГБ | 4 | 80-100 ГБ NVMe |
| Франшиза/агрегатор нескольких компаний | 30+ | 400+ | 16 ГБ | 4-8 | 120+ ГБ NVMe |
На 1 ГБ EasyAppointments запускается и нормально работает для одного специалиста без интеграций — это честный вариант для теста или очень маленького бизнеса с редкими записями. Но как только специалистов становится 3-5 и включается синхронизация с Google Calendar (а её обычно включают почти сразу, чтобы не вести два календаря), запас памяти на 1 ГБ исчезает быстро: MySQL и PHP-FPM начинают конкурировать за одни и те же 700-800 МБ, оставшиеся после системы. Практический минимум для рабочего использования — 2 ГБ.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНастройка PHP-FPM под доступную память
По умолчанию пул PHP-FPM почти никогда не настроен под конкретный сервер — либо простаивают ресурсы, либо в пик записи (например, утром в понедельник, когда клиенты массово бронируют на неделю) OOM killer начинает убивать процессы. Формула: возьмите объём RAM, который можно отдать под PHP (обычно 40-50% от общей, остальное — MySQL и система), и разделите на средний вес воркера.
Воркер EasyAppointments без тяжёлых кастомизаций занимает около 25-30 МБ. Для сервера на 4 ГБ, где под PHP выделено ~1.6 ГБ:
; /etc/php/8.3/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 6
pm.max_spare_servers = 20
pm.max_requests = 500
Расчёт: 1600 МБ / 30 МБ ≈ 53, берём с небольшим запасом вниз — 50. Если в логах journalctl -u php8.3-fpm или systemctl status php8.3-fpm видно частое сообщение WARNING: [pool www] server reached pm.max_children, это сигнал, что либо лимит занижен, либо памяти физически не хватает под текущую нагрузку.
Фактическое потребление одного воркера проверяется так:
ps --no-headers -o rss -C php-fpm8.3 | awk '{sum+=$1; n++} END {print sum/n/1024 " MB avg"}'
Настройка MySQL/MariaDB под память сервера
InnoDB buffer pool — главный рычаг производительности для EasyAppointments, потому что почти каждое действие пользователя (открытие календаря, проверка занятости слота, оформление записи) — это чтение из базы. Для сервера, где MySQL — основная нагрузка помимо PHP, ориентир — 40-50% от общей RAM.
# /etc/mysql/mariadb.conf.d/50-server.cnf
[mysqld]
innodb_buffer_pool_size = 1500M # для сервера с 4 ГБ RAM
innodb_buffer_pool_instances = 1
innodb_log_file_size = 96M
max_connections = 60
tmp_table_size = 32M
max_heap_table_size = 32M
query_cache_type = 0
На серверах с 1-2 ГБ буфер приходится держать скромным (128-256 МБ) — здесь пригодится статья про оптимизацию MySQL под ограниченную память, там разобраны компромиссы, когда буфера физически не хватает на весь рабочий набор данных. Если сомневаетесь между MySQL и MariaDB для нового сервера, разница по памяти для нагрузки такого типа несущественна — обзор в статье про выбор между MariaDB и MySQL.
Проверить, достаточно ли буфера, можно по коэффициенту попаданий:
SHOW STATUS LIKE 'Innodb_buffer_pool_read%';
Если Innodb_buffer_pool_reads (физические чтения с диска) растёт быстрее Innodb_buffer_pool_read_requests (логические чтения), буфер мал относительно рабочего набора — по мере роста истории записей и клиентской базы это стоит пересчитывать.
Google Calendar и email-уведомления: скрытая нагрузка
Многие считают только веб-интерфейс и упускают из виду фоновую интеграционную нагрузку. При включённой синхронизации с Google Calendar каждое создание, изменение или отмена записи — это отдельный HTTP-запрос к Google API, который выполняется синхронно в рамках того же PHP-процесса, что обрабатывает бронирование. Пока запрос к Google не завершится, воркер PHP-FPM занят — при нескольких одновременных клиентах, бронирующих слоты, это может ощутимо удлинить время ответа на слабом сервере.
То же самое с email: письма клиенту и специалисту о новой записи отправляются синхронно через SMTP в момент подтверждения брони. Если почтовый сервер отвечает медленно (типично для бесплатных SMTP-релеев или перегруженного почтовика), это тоже держит PHP-воркер занятым дольше обычного. При всплеске записей — например, после того как клиника разослала клиентам напоминание о доступности записи на следующую неделю, — десятки почти одновременных броней могут на короткое время исчерпать пул PHP-FPM, если он не рассчитан с запасом.
Держите это в уме при расчёте: для сценариев с активной синхронизацией Google Calendar у нескольких специалистов закладывайте на 20-30% больше PHP-воркеров, чем для чистого сценария без интеграций, — именно на случай, когда внешние запросы (к Google, к SMTP) задерживаются дольше обычного.
Диагностика нехватки RAM
Признаки, что памяти не хватает, обычно видны раньше, чем сервер отваливается целиком:
free -h # своп начал заполняться — тревожный знак
vmstat 1 5 # столбец si/so показывает активный своп
dmesg | grep -i "out of memory" # OOM killer уже вмешивался
top -o %MEM # кто именно ест память прямо сейчас
Если free -h показывает, что available меньше 10-15% от общей памяти в обычные рабочие часы (не в пик), а swap used растёт день ото дня — это сигнал переезжать на тариф с большим объёмом RAM или пересчитывать буферы MySQL и лимиты PHP-FPM. Своп для EasyAppointments особенно неприятен именно из-за синхронной работы с внешними сервисами: форма бронирования, которая обычно отвечает за 200-400 мс, при активном свопе может «зависать» на секунды, а клиент, не дождавшись ответа, просто закрывает вкладку и уходит к конкуренту.
Для постоянного слежения за памятью на проде пригодится статья про мониторинг диска на VPS — те же принципы (пороги, алерты) применимы и к оперативной памяти, отличается только источник метрик. А регулярные фоновые задачи (например, если вы добавите свой cron-скрипт для напоминаний клиентам за день до визита) стоит настраивать по общим правилам из статьи про настройку cron-задач на VPS, чтобы они не пересекались по времени с пиком записи.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Хватит ли 1 ГБ RAM для EasyAppointments?
Для одного специалиста без синхронизации с Google Calendar и с редкими записями — да, запустится и будет работать стабильно. Как только специалистов становится несколько и подключаются интеграции, 1 ГБ быстро становится тесным — закладывайте от 2 ГБ.
Что сильнее нагружает сервер — сама EasyAppointments или интеграция с Google Calendar?
Сама логика приложения лёгкая. Основную нагрузку в пике создают синхронные внешние запросы — к Google Calendar API и к SMTP-серверу при отправке писем, — они держат PHP-воркер занятым дольше, чем обычная работа с базой.
Нужен ли отдельный сервер под MySQL, если специалистов много?
Для большинства сценариев из таблицы выше — нет, MySQL и PHP спокойно живут на одном сервере при правильно посчитанных буферах. Отдельная база имеет смысл только при десятках специалистов и активном API-доступе извне (агрегаторы, мобильные приложения).
Сильно ли влияет число клиентов в базе на потребление RAM?
Напрямую — не сильно, таблицы EasyAppointments компактные даже при десятках тысяч клиентов. Влияние идёт косвенно, через размер InnoDB buffer pool, который нужен, чтобы горячие данные (специалисты, услуги, ближайшие записи) помещались в память, а не читались с диска на каждый запрос.
Как понять, что пора расширять сервер, а не оптимизировать конфиг?
Если после настройки innodb_buffer_pool_size и pm.max_children по формулам выше своп всё равно растёт в рабочие часы, а форма бронирования продолжает подтормаживать в пике записи — это уже вопрос физического объёма памяти под текущее число специалистов, а не тонкой настройки.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →