MAATRIX / Блог / Сколько RAM нужно для EasyAppointments

Сколько RAM нужно для EasyAppointments

MAATRIX

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, и от объёма истории записей.

СценарийСпециалистовЗаписей/деньRAMvCPUДиск
Тест/пилот, один мастер1до 101 ГБ115-20 ГБ SSD
Малый бизнес (салон, кабинет)2-510-402 ГБ1-225-30 ГБ SSD
Сеть из нескольких точек5-1540-1504 ГБ240-60 ГБ SSD
Крупная сеть, Google Calendar sync у всех15-30150-4008 ГБ480-100 ГБ NVMe
Франшиза/агрегатор нескольких компаний30+400+16 ГБ4-8120+ ГБ 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 ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →