В качестве среды исполнения Java-приложений обычно используются серверы, у которых минимум 2 Гб оперативной памяти (не считая выделенной под ОС). Рассмотрим вариант запуска Java-приложения с базой данных MySQL на VDS-сервере «Danny» от Timeweb (1 Гб ОЗУ) без получения хорошо известной каждому «джависту» ошибки «Out of memory». Весь процесс от регистрации до запуска работающего Java-приложения с базой данных займет не более 15 минут!
Первым делом создаем VDS.
Выбираем конфигурацию ПО сервера – в нашем случае ОС Ubuntu (можно любую другую из предложенных) и «Docker».
Выбираем конфигурацию сервера «Danny» (2.8 ГГц CPU, 1Гб ОЗУ, 10Гб дискового пространства), которая является на момент написания статьи самым бюджетным вариантом.
Итак, мы создали сервер с установленным ПО «Docker».
Теперь нам необходима среда исполнения для нашего Java-приложения. Думали, дальше будет «оченьмноготекста» по установке и настройке Apache Tomcat? Нет. Думаю, на просторах интернета предостаточно материалов на данную тему, поэтому, чтобы не тратить время на полную установку Apache Tomcat, мы используем spring boot с embedded tomcat.
Далее нам необходима установленная версия Java для запуска приложения. Но мы, все по тем же причинам в духе «у меня нет времени, клиенты ждут работающий сайт еще до того как придумали Java как можно скорее», не будем устанавливать Java. Мы создадим docker-образ с нашим Java-приложением на основе docker-образа с уже установленной Java Runtime Environment 11 (JRE-11). Также такой подход делает наше приложение максимально портативным и хорошо масштабируемым.
Создаем простейший Dockerfile:
В данном файле описаны:
-
Родительский docker-образ.
-
Копирование в docker-образ нашего приложения demo-1.0.war.
-
Установка рабочей директории «/usr/app».
-
Публикация порта 8080.
-
Команда, которая выполнится при запуске docker-контейнера.
Собираем docker-образ с помощью команды docker build и публикуем в своем репозитории.
Для разворачивания БД MySQL будем использовать официальный docker-образ «mysql:8.0.21».
Таким образом, у нас имеется:
-
Docker-образ нашего Java-приложения.
-
Docker-образ MySQL БД.
Теперь заходим удаленно (например, через Putty) на созданный VDS. С помощью команды docker pull загружаем docker-образы:
docker pull username/demo:1.0 docker pull mysql:8.0.21
Вместо username необходимо написать свой docker-аккаунт.
Теперь запускаем docker-контейнеры (предварительно заменив some_name_mysql/some_password_mysql/some_name_java/username на свои значения):
docker run -p 3306:3306 --name some_name_mysql -e MYSQL_ROOT_PASSWORD=some_password_mysql -d mysql:8.0.21 docker run -p 8181:8080 --name some_name_java -d username/demo:1.0
Проверяем (IP-адрес берем из панели управления сервером):
Ура! Работает! Но где же «java.lang.OutOfMemoryError: Java heap space»?
Приведу скриншот показателей загрузки, полученных командой htop:
Для большей практической ценности показатели взяты с сервера, на котором установлено функционирующее боевое приложение (достаточно небольшое, но все же активно используемое). Как видите, суммарное потребление оперативной памяти превышает 1Гб, хотя на старте приложения это значение было ~800Мб. Повышение потребления ОЗУ в ходе эксплуатации произошло в связи с созданием множества необходимых объектов и постоянным хранением их в памяти в целях оптимизации. Все это приводило к достижению лимита heap size и ошибке «Out of memory». Решение, как вы видите, состоит в подключении swap-пространства. Для этого выполните набор следующих команд:
sudo fallocate -l 1G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile sudo cp /etc/fstab /etc/fstab.bak echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Подведем итог. Мы получили работающее Java-приложение с базой данных MySQL на сервере Danny менее чем за 30 минут! И никаких непредвиденных «OutOfMemory».
Стоит добавить, что самое лучшее решение с точки зрения оптимизации – повышение конфигурации сервера до «Scarlett», на котором и дискового пространства в 3 раза больше (30Гб), и ОЗУ в 2 раза больше (2Гб), чего должно хватить для большинства небольших проектов.
Но с целью апробации услуг VDS, предоставляемых компанией Timeweb, временное решение, описанное в данной статье, более чем актуально даже для владельцев крупных enterprise-приложений (при необходимости можно увеличить размер swap-файла).
Комментарии