Начало работы с Heroku на языке Java
Облака – популярная штука, ворвавшаяся и в сферу хостинга. Скажем НЕТ DevOps-ам! Будем сами себе DevOps-ами и поработаем с Heroku на языке Java.
Heroku – очень крутая штука! Тебе не нужно заморачиваться с настройкой железа, балансирования, маршрутизации и прочими радостями воздвижения нового сервиса, т. к. все за тебя сделали (и будут делать) разработчики. Тебе дается уже готовый сервак – бери и ваяй свое приложение.
Самое начало
Это руководство поможет развернуть Java-приложение за считанные минуты.
Предполагается, что у тебя уже:
Если ты больше любишь Gradle, то тебе в раздел официального хелпа.
Установка
Для Heroku CLI требуется система контроля версий Git. Если она у тебя еще не установлена, выполни следующие действия:
CLI используется для управления и масштабирования приложений, подготовки модулей, просмотра журналов и т. д.
Загрузи и запусти нужный установщик: Mac, Win32, Win64, Linux (sudo snap install heroku
--classic
).
После установки уже можно вводить команды с помощью директивы heroku
в любимом терминале.
Используй команду heroku login
для входа в Heroku CLI
(может ругнуться фаервол – все разрешаем):
$ heroku login heroku: Press any key to open up the browser to login or q to exit › Warning: If browser does not open, visit › https://cli-auth.heroku.com/auth/browser/*** heroku: Waiting for login... Logging in... done Logged in as me@example.com
Эта команда откроет страницу Heroku – нажми там кнопку Войти
.
Аутентификация требуется для правильной связки heroku
и git
.
Подготовка приложения
Чтобы создать локальную копию приложения, которую можно развернуть в Heroku, выполни следующие команды в терминале:
$ git clone https://github.com/heroku/java-getting-started $ cd java-getting-started
Теперь у тебя есть рабочий репозиторий. Приложение включает в себя файл pom.xml, используемый менеджером Maven.
Развертывание приложения
На этом шаге ты развернешь приложение в Heroku.
Первым делом подготовим Heroku к получению исходного кода:
$ heroku create Creating app... done, floating-ocean-97551 https://floating-ocean-97551.herokuapp.com/ | https://git.heroku.com/floating-ocean-97551.git
На этом шаге создается удаленный репозиторий (с именем heroku) и связывается с локальным.
По дефолту Heroku генерирует случайное имя для приложения, но можно указать и свое.
Теперь давай развернем код:
$ git push heroku master remote: Compressing source files... done. remote: Building source: remote: remote: -----> Java app detected remote: -----> Installing JDK 1.8... done remote: -----> Executing: ./mvnw -DskipTests clean dependency:list install ... remote: [INFO] ------------------------------------------------------------------------ remote: [INFO] BUILD SUCCESS remote: [INFO] ------------------------------------------------------------------------ remote: [INFO] Total time: 15.870 s remote: [INFO] Finished at: 2019-07-08T22:42:35Z remote: [INFO] ------------------------------------------------------------------------ remote: -----> Discovering process types remote: Procfile declares types -> web remote: remote: -----> Compressing... remote: Done: 70M remote: -----> Launching... remote: Released v5 remote: https://floating-ocean-97551.herokuapp.com/ deployed to Heroku remote: remote: Verifying deploy... done. To https://git.heroku.com/floating-ocean-97551.git * [new branch] master -> master
Готово. Убедись, что хотя бы один экземпляр приложения запущен:
$ heroku ps:scale web=1
Теперь перейди в приложение по ссылке, созданной из его имени, или поступи следующим образом:
$ heroku open
Логи
Heroku собирает события со всех выходных потоков приложения и компонентов платформы в единый журнал, упорядоченный по времени.
Чтобы посмотреть логи запущенного приложения, воспользуйся командой heroku logs --tail
:
heroku logs --tail 2019-07-08T22:43:04.169634+00:00 app[web.1]: 2019-07-08 22:43:04.169 INFO 4 --- [io-28914-exec-3] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet' 2019-07-08T22:43:04.169767+00:00 app[web.1]: 2019-07-08 22:43:04.169 INFO 4 --- [io-28914-exec-3] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet' 2019-07-08T22:43:04.180097+00:00 app[web.1]: 2019-07-08 22:43:04.179 INFO 4 --- [io-28914-exec-3] o.s.web.servlet.DispatcherServlet : Completed initialization in 10 ms
Объявление Procfile
Heroku использует специальный текстовый файл Procfile
(мини-конфиг) для
явного указания директив запуска приложения.
Procfile в развернутом приложении выглядит примерно так:
web: java -jar target/java-getting-started-1.0.jar
Здесь объявляется тип процесса web и команда, необходимая для его запуска. Web указывает на то, что этот тип процесса будет прикреплен к стеку маршрутизации Heroku для получения трафика.
Масштабирование приложения
Сейчас приложение работает на одном dyno-процессе. Dyno
– это
легковесный контейнер Linux, запускаемый по команде из Procfile.
Проверить, сколько dyno сейчас запущено, можно так:
$ heroku ps Free dyno hours quota remaining this month: 987h 28m (98%) Free dyno usage for this app: 0h 0m (0%) For more information on dyno sleeping and how to upgrade, see: https://devcenter.heroku.com/articles/dyno-sleeping === web (Free): java -jar target/java-getting-started-1.0.jar (1) web.1: up 2019/07/08 17:42:57 -0500 (~ 7s ago)
По умолчанию приложение деплоится в свободном dyno. Свободными они становятся (засыпают) после тридцати минут бездействия (т. е. если они не получают никакого трафика). Это поведение вызывает задержку в несколько секунд при первом запросе “пробуждения”. Последующие запросы будут выполняться нормально.
Чтобы избежать спящего режима dyno, можно обновить тип dyno на хобби или профи. Например, если ты мигрируешь свое приложение на профи уровень, можно легко масштабировать его, попросив Heroku подготовить определенное количество dyno.
Масштабирование приложения в Heroku эквивалентно изменению количества запущенных dyno.
Установить ненулевое количество веб dyno можно так:
$ heroku ps:scale web=1
Объявление зависимостей
Heroku автоматически определяет Java-приложение, если оно содержит файлик
pom.xml
в корневом каталоге. Ты
можешь создать pom.xml для других приложений с помощью команды mvn archetype: create
.
В развернутой демке приложения уже имеется pom.xml
с такой начинкой:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
В этом файлике указаны зависимости, требуемые для работы приложения. При
развертывании Heroku прочитает файл и все установит, запустив mvn clean install
.
В папке есть еще один файл, system.properties
,
указывающий на версию Java. Содержимое этого необязательного файла ниже:
java.runtime.version=1.8
Запусти mvn
clean install
в локальном каталоге, чтобы установить зависимости и
подготовить систему к локальному запуску приложения. Обрати внимание, что
приложению требуется Java 8, но ты можешь запушить другие приложения с
поддержкой другой версии Java.
$ mvn clean install ... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 14.266 s [INFO] Finished at: 2019-07-08T17:43:29-05:00 [INFO] Final Memory: 37M/331M [INFO] ------------------------------------------------------------------------
Если Maven не
установлен
или
появляется
ошибка, например, mvn is not recognized as an internal or external command
, используй команду-обертку: запустив mvnw clean install
на
Windows или ./ mvnw clean install
на
Mac и Linux. Это одновременно
устанавливает и запускает Maven.
Процесс Maven скомпилит и создаст JAR с зависимостями, помещая его в корневой каталог приложения. Этим процессом рулит spring-boot-maven-plugin из pom.xml.
Если ты не юзаешь Spring в pom.xml, можно указать иной плагин:
Локальный запуск приложения
Запусти приложение с помощью команды heroku
:
$ heroku local web ... 7:06:33 PM web.1 | 2019-04-04 19:06:33.539 INFO 97226 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 7:06:33 PM web.1 | 2019-04-04 19:06:33.783 INFO 97226 --- [ main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index 7:06:33 PM web.1 | 2019-04-04 19:06:33.949 INFO 97226 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 2 endpoint(s) beneath base path '/actuator' 7:06:34 PM web.1 | 2019-04-04 19:06:34.047 INFO 97226 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 5000 (http) with context path ''
Открой в браузере http://localhost:5000
– ты должен увидеть свое
приложение.
Для остановки приложения вернись в окно терминала и нажми CTRL+C
.
Внесение локальных изменений
На этом шаге ты узнаешь, как внести локальные изменения и развернуть их в Heroku. В качестве примера мы добавим зависимость и некоторый код.
Измени pom.xml,
добавив зависимости для jscience
в блок dependencies
:
В 28 строке добавь:
<dependency> <groupId>org.jscience</groupId> <artifactId>jscience</artifactId> <version>4.3.1</version> </dependency>
Теперь добавь следующие
объекты
в 19 строку файла src/main/java/com/example/Main.java
:
import static javax.measure.unit.SI.KILOGRAM; import javax.measure.quantity.Mass; import org.jscience.physics.model.RelativisticModel; import org.jscience.physics.amount.Amount;
Добавь метод hello в 59 строку src/main/java/com/example/Main.java
:
@RequestMapping("/hello") String hello(Map<String, Object> model) { RelativisticModel.select(); Amount<Mass> m = Amount.valueOf("12 GeV").to(KILOGRAM); model.put("science", "E=mc^2: 12 GeV = " + m.toString()); return "hello"; }
Создай src/main/resources/templates/hello.html
с таким содержимым:
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" th:replace="~{fragments/layout :: layout (~{::body},'hello')}"> <body> <div class="container"> <p th:text="${science}"/> </div> </body> </html>
Проверь изменения:
$ mvn clean install ... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 6.400 s [INFO] Finished at: 2019-07-08T17:43:38-05:00 [INFO] Final Memory: 37M/328M [INFO] ------------------------------------------------------------------------ $ heroku local web ... 5:43:53 PM web.1 | 2019-07-08 17:43:53.079 INFO 39652 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 5:43:53 PM web.1 | 2019-07-08 17:43:53.693 INFO 39652 --- [ main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index 5:43:54 PM web.1 | 2019-07-08 17:43:54.097 INFO 39652 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 2 endpoint(s) beneath base path '/actuator' 5:43:54 PM web.1 | 2019-07-08 17:43:54.321 INFO 39652 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 5000 (http) with context path ''
По адресу http://localhost:5000/hello
ты должен увидеть следующее:
E=mc^2: 12 GeV = (2.139194076302506E-26 ± 1.4E-42) kg
Можно деплоить:
$ git add . $ git commit -m "Demo" $ git push heroku master $ heroku open hello
Использование БД
Heroku предоставляет поддержку Postgres, Redis, MongoDB и MySQL.
На этом шаге ты узнаешь о дополнении Heroku Postgres
, поставляемом
при развертывании всех приложений Java.
Heroku Postgres сама по себе является надстройкой,
поэтому для обзора БД можно использовать команду heroku addons
:
heroku addons Add-on Plan Price State ───────────────────────────────────────────── ───────── ───── ─────── heroku-postgresql (postgresql-slippery-51080) hobby-dev free created └─ as DATABASE papertrail (papertrail-concentric-67589) choklad free created └─ as PAPERTRAIL The table above shows add-ons and the attachments to the current app (floating-ocean-97551) or other apps.
Чтобы узнать DATABASE_URL
, используется команда:
$ heroku config === floating-ocean-97551 Config Vars DATABASE_URL: postgres://kwzrfqexkujliv:3581c21827af4db24c7cfcf0876bd9edf42c7ec3b5bb289fb1253c8089a328d3@ec2-54-243-47-196.compute-1.amazonaws.com:5432/dfdjtejhj2mtcr ENERGY: 20 GeV PAPERTRAIL_API_TOKEN: D8ZHH05QpTlY5R8oFHJ
Команда heroku pg
предоставляет более подробную информацию о БД:
$ heroku pg === DATABASE_URL Plan: Hobby-dev Status: Available Connections: 10/20 PG Version: 11.3 Created: 2019-07-08 22:42 UTC Data Size: 7.7 MB Tables: 0 Rows: 0/10000 (In compliance) Fork/Follow: Unsupported Rollback: Unsupported Continuous Protection: Off Add-on: postgresql-slippery-51080
Дальнейшие действия
Вот инфа для изучения, чтобы продолжить свое путешествие с Heroku:
- как работает Heroku – дополнительные материалы по настройке, развертыванию и запуску;
- категория Java предоставляет более подробную информацию о развертывании Java- приложений;
- категория развертывание предоставляет множество фич для упрощения развертывания.