Java development 2.0: Вторая волна разработки Java-приложений: Развертывание приложений Java с помощью PaaS от Heroku

Heroku поддерживает связь с Ruby для обеспечения масштабируемости приложений Java

Heroku представляет собой разновидность PaaS, которая привносит существенные новшества в методы разработки на языке Java™— отчасти благодаря тому, что его родным языком (и философией) является Ruby. Heroku объединяет свойственный Ruby гибкий и непринужденный подход к разработке приложений с реализованной в Git интеллектуальной распределенной моделью развертывания, открывая доступ к ним для разработчиков на языке Java через знакомые библиотеки Java. В этом выпуске Java development 2.0 Эндрю Гловер создает новую инкарнацию своего приложения для слежения за местоположением мобильных устройств с помощью Apache Wink, Jetty и Maven; а затем развертывает его в Heroku, используя высокоэффективную масштабируемую инфраструктуру Git.

Эндрю Гловер, президент компании, Stelligent Incorporated

Эндрю ГловерЭндрю Гловер является президентом компании Stelligent Incorporated , которая помогает другим фирмам решать проблемы качества программного обеспечения. Для этого используются эффективные стратегии тестирования и технологии непрерывной интеграции, которые позволяют коллективам разработчиков постоянно контролировать качество кода, начиная с ранних стадий разработки. Просмотрите блог Энди , там можно найти список его публикаций.



16.08.2012

IBM в облаке

Чтобы узнать больше о присутствии IBM в облаке, достаточно взглянуть на Прикладные службы IBM SmartCloud, облачную платформу приложений, предоставляемую как услуга. Здесь вы найдете подробное описание следующих аспектов:

  • Сервисы приложений: готовые сервисы уровня предприятия для совместной работы, анализа и управления бизнес-процессами
  • Жизненный цикл приложений: технологии, создающие основу для совместной работы и автоматизации разработки приложений, одновременно обеспечивая прозрачность на протяжении всего жизненного цикла приложения
  • Услуги интеграции: простая и хорошо защищенная интеграция данных, приложений и услуг в облачной среде, дополненная единым уровнем управления услугами
  • Услуги по распределению нагрузки: услуги оптимизации производительности (от приложений до схем распределения нагрузки), помогающие обеспечить качество обслуживания и доступность, одновременно поддерживая работу в режиме коллективной аренды и мобильное распределение нагрузки по облакам

Также не забудьте посетить пути обучения облачным технологиям на developerWorks, где вы найдете много полезной информации.

Недавние статьи из серии Java development 2.0 были посвящены возможностям применения подхода PaaS (платформа как услуга) для разработки на языке Java. На этот раз я предлагаю вашему вниманию Heroku, еще одну популярную систему PaaS, теперь также поддерживающую приложения Java.

Heroku, ведущая свою родословную от Ruby, подходит к разработке и развертыванию приложений Java совершенно иначе, чем знакомые вам другие разновидности Java PaaS, такие как Amazon Elastic Beanstalk и Google App Engine (GAE). Прежде чем начать практическое знакомство с Heroku, полезно узнать, что общего она имеет с этими двумя платформами и в чем от них отличается.

GAE и Beanstalk: два разных тяжеловеса

Как мы уже узнали из предыдущих статей этой серии, Google App Engine и Amazon Elastic Beanstalk являются полными противоположностями в смысле гибкости. В то время как крайне строгий GAE требует, чтобы вы играли по его правилам или не играли вообще, Elastic Beanstalk допускает полную настройку: PaaS от Amazon позволяет исполнять все, что работает на JVM. GAE ограничивает выбор библиотек Java и контролирует способы масштабирования вашего приложения. На практике развертывание приложения в GAE напоминает игру в угадайку: вы не знаете, где живет ваше приложение и даже сколько экземпляров приложения одновременно существует. Положительный момент здесь в том, что Google выполняет за вас все масштабирование, и, само собой разумеется, что приложения GAE масштабируются очень хорошо. Передавая управление. GAE, вы можете практически ни о чем не беспокоиться, кроме написания максимально надежного кода.

Об этой серии

С момента первого появления технологии Java™ принципы разработки ПО на этом языке претерпели значительные изменения. Благодаря появлению мощных систем с открытым исходным кодом и надежных инфраструктур для предоставления средств разработки в аренду стало возможным быстро и дешево транслировать, тестировать, исполнять и поддерживать приложения Java. В данной серии статейЭндрю Гловер описывает широкий спектр средств и технологий, благодаря которым стала возможной эта новая парадигма разработки на языке Java.

Amazon's Elastic Beanstalk находится по другую сторону зеркала. Он не только предоставляет вам богатый набор инструментов, но и в большой степени позволяет контролировать способ масштабирования приложения. Недостаток этого подхода очевиден: без вашего личного вмешательства Amazon почти ничего делать не будет. И все же если вы хотите тонко настроить развертывание своего приложения и хотите иметь хорошо масштабируемую инфраструктуру, Amazon Elastic Beanstalk — очень хороший выбор.

Если бы мне предложили оценить простоту масштабирования (в смысле написания кода и развертывания) по десятибалльной шкале (10 —очень сложно, 0 —без усилий), я бы дал GAE 4 балла, а Elastic Beanstalk — 6. GAE позволяет без проблем выполнять скрипты и загружать файлы, но ограниченный диапазон совместимых средств разработки несколько противоречит моему стилю. В отличие от этого, Elastic Beanstalk позволяет использовать любые библиотеки, но путь к развертыванию оказывается дольше и, зачастую, утомительней; приходится жертвовать простотой ради большего контроля.

Heroku бросает вызов

Подобно GAE и Elastic Beanstalk, Heroku рассчитана на горизонтальное масштабирование. Вы развертываете свой код в то, что в Heroku называется dyno; в сущности, это веб-контейнеры. Если вы хотите расширить систему, нужно просто добавить больше dyno, позволив Heroku обрабатывать больше одновременных веб-запросов. Эта концепция очень проста и предоставляет больше контроля, чем GAE, без конфигурационных требований Elastic Beanstalk.

Ruby и Heroku

Хотя Heroku начала свою работу, ориентируясь на сообщество Ruby — его головная компания даже приняла на работу создателя Ruby! — недавно в нее была добавлена поддержка Clojure, Node.js и Java. И хотя подход Heroku, ставящий Ruby на первое место (и использующий командную строку Ruby), может оттолкнуть некоторых пишущих на Java разработчиков, я считаю, что это внесло приятное разнообразие. В частности, модель развертывания в Heroku, основанная на Git, позволяет очень просто и легко создавать и масштабировать облачные веб-приложения.

В Heroku конвейером развертывания является Git — а не Ant и не Maven. Когда вы развертываете свое приложение, вы делаете это через Git push, что мы подробнее обсудим позже в этой статье.

Если сравнить Heroku с GAE и Elastic Beanstalk по легкости масштабирования, то я бы поставил ему 2, что означает, что он практически не требует усилий. В плане разнообразия инструментов Heroku предлагает большую гибкость, и я могу выбрать наиболее эффективный инструмент для любой конкретной работы. В плане конфигурирования Heroku дает больше контроля, чем GAE, но меньше, чем Elastic Beanstalk — и иногда это именно то, что нужно. К тому же приложение, построенное на Heroku, можно легко перенести на Elastic Beanstalk: если вдруг мне понадобится более тонкое управление масштабированием приложения, я знаю, что всегда могу это сделать.


Начинаем работать с Heroku

Чтобы начать работу с Heroku, нужно установить и настроить следующие компоненты:

Заметьте, что Maven для Heroku не нужен, просто я использую его как средство сборки. Документация Java в Heroku тоже опирается на Maven.

Сборка и запуск приложения

Установив все необходимые компоненты, выберите директорию, в которой будете работать, и запустите следующую команду Maven (код разбит на строки в соответствии с шириной страницы):

mvn archetype:generate -DarchetypeGroupId=org.mortbay.jetty.archetype 
  -DarchetypeArtifactId=jetty-archetype-assembler -DarchetypeVersion=7.5.0.RC0

Создание конечных точек REST

Одной из немногих библиотек, доступных для создания приложений RESTful, является Wink. В предыдущих статьях я создавал такие приложения с помощью Play и Gretty, которые в большей степени, чем Wink, упрощают процесс создания конечных точек RESTful. Я выбрал Wink, потому что Play является полностековой системой, которая в данном случае избыточна. А Gretty слишком легковесен и не может дать всего, что я хочу. В Wink нет контейнера сервлетов и системы ORM — он просто создает ресурсы RESTful. В данном случае я решил, что такая специализация вполне меня устраивает.

Maven предложит вам ввести идентификаторы groupId и artifactId. Обычно для groupId я использую имя своего пакета, а для artifactId— имя своего проекта. Затем Maven создаст структуру проекта, позволяющую собирать и запускать веб-приложения поверх Jetty. Таким образом, за один шаг вы создаете костяк веб-приложения, готовый к развертыванию в инфраструктуру облака Heroku. При этом, хотя Jetty является прототипом Maven, Heroku не поддерживает Jetty на стороне веб-сервера. На самом деле Heroku даже не знает о Jetty — да и ему все равно.

Предыдущая команда Maven создает очередное простейшее приложение типа "Hello World". Если войти в директорию src этого приложения и затем в main—>webapp, можно увидеть файл index.html. Запустите приложение, и этот файл (как вы, наверно, уже догадались) напечатает текст "hello world".

Запустить приложение тоже просто. Если подать команду mvn install в директории вновь созданного проекта (который носит имя, присвоенное идентификатору artifactId), будет создан скрипт командного процессора для нужной вам операционной системы (в моем случае это OSX). Просто наберите $>sh target/bin/webapp, затем перейдите по адресу http://localhost:8080 в своем любимом браузере и получите приветствие.


Heroku в реальном мире

С помощью Heroku можно развернуть любую нужную вам библиотеку Java. Для примера (и по традиции — по крайней мере для тех, кто читает эту серию), я собираюсь создать еще одну инкарнацию моего мобильного веб-сервиса Magnus, собирающего информацию о местоположениях, который дебютировал в моем введении в Amazon Elastic Beanstalk (см. Ресурсы). В качестве библиотеки RESTful я собираюсь использовать Apache Wink, который представляет собой реализацию спецификации JAX-RS. Моя реализация веб-сервиса предоставит конечную точку PUT, которая принимает JSON и вставляет полученные из документа соответствующие данные в экземпляр MongoDB. Он, в свою очередь, будет размещен в MongoHQ с помощью Morphia (см. Ресурсы).

Первое, что нужно сделать, — это добавить в Maven-файл pom.xml в Magnus новые зависимости для Wink и Morphia, как показано в листинге 1:

Листинг 1. Добавление Wink и Morphia в Maven POM
<dependency>
 <groupId>org.apache.wink</groupId>
 <artifactId>wink-server</artifactId>
 <version>1.1.3-incubating</version>
</dependency>

<dependency>
 <groupId>org.apache.wink</groupId>
 <artifactId>wink-json-provider</artifactId>
 <version>1.1.3-incubating</version>
</dependency>

<dependency>
 <groupId>com.google.code.morphia</groupId>
 <artifactId>morphia</artifactId>
 <version>0.99</version>
</dependency>

Заметьте, что я также изменил свой файл POM в хранилище Morphia Maven и получил версию 0.99:

Листинг 2. Добавление нового хранилища в Maven POM
<repositories>
 <repository>
  <id>morphia repository</id>
  <url>http://morphia.googlecode.com/svn/mavenrepo/</url>
 </repository>
</repositories>

Затем я создаю ресурс местоположений — конечную точку Wink, которая будет представлять местоположения пользователя:

Листинг 3. Создание ресурса местоположений Wink
@Path("/location")
public class LocationResource {

 @PUT
 @Consumes(MediaType.APPLICATION_JSON)
 @Path("{id}")
 public String updateAccountLocation(@PathParam("id") int accountId, JSONObject 
  requestJSON) {
  try{

   double latitude = Double.parseDouble(requestJSON.get("latitude").toString());
   double longitude = Double.parseDouble(requestJSON.get("longitude").toString());

   SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm");
   Date dt = formatter.parse(requestJSON.get("timestamp").toString());

   new Location(accountId, dt, latitude, longitude).save();
   return new JSONObject().put("status", "success").toString();
  }catch(Exception e){
   return "failure with " + requestJSON;
  }
 } 
}

Wink позволяет описать мой сервис RESTful посредством трех аннотаций: одной для метода HTTP (PUT), другой для предполагаемого типа запроса (JSON) и последней для указания того, что конечная точка приняла параметр (в данном случае location/:accountId).

Этот класс Location является тем же поддерживаемым в Morphia объектом, который был представлен в моем введении в Elastic Beanstalk. Он просто создает в MongoHQ документ, представляющий местоположение для данной учетной записи. Это местоположение (теоретически полученное от мобильного устройства) представлено параметром конечной точки RESTful.

Wink и Jetty

Теперь я хочу связать Wink с Jetty. Для этого мне нужно проделать две вещи: создать класс Application и настроить файл web.xml.

Класс Wink Application (показанный в листинге 4) предназначен для загрузки соответствующих классов ресурсов:

Листинг 4. Класс Application в Wink
public class MarmarisApplication extends Application {
 @Override
 public Set<Class<?>> getClasses() {
  Set<Class<?>> classes = new HashSet<Class<?>>();
  classes.add(LocationResource.class);
  return classes;
 }
}

В листинге 5 я изменил файл web.xml своего приложения, добавив специфические для Wink атрибуты, такие как указатель на мой класс Application и нужный мне URL, который в данном случае такой /service/resource:

Листинг 5. Подключение Wink через web.xml
<servlet>
 <servlet-name>MarmarisApp</servlet-name>
 <servlet-class>org.apache.wink.server.internal.servlet.RestServlet</servlet-class>
 <init-param>
  <param-name>javax.ws.rs.Application</param-name>
  <param-value>com.b50.marmaris.MarmarisApplication</param-value>
 </init-param>
 <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
 <servlet-name>MarmarisApp</servlet-name>
 <url-pattern>/service/*</url-pattern>
</servlet-mapping>

Для проверки попробуйте еще раз выполнить команду mvn install и запустить приложение (в данном случае Magnus) локально. При этом вы должны суметь передать документ JSON (показанный в листинге 6) в конечную точку http://localhost:8080/service/location/{account_id}, где account_id является числом.

Листинг 6. Документ JSON, представляющий местоположение
{
 "name":"location payload",
 "latitude":"46.49",
 "longitude":"71.11",
 "timestamp":"09-02-2011 14:43"
}

Таким образом, мы без труда написали приложение, и теперь готовы перейти к еще более простой части: развернуть его в облаке Heroku!


Heroku и Git

Развертывание в Heroku выполняется через Git, что потребует от вас некоторой адаптации, если вы не знакомы с распределенными системами управления версиями. Развертывание в Heroku (через Git) подобно фиксации в Subversion в другую ветвь, отличную от основной линии разработки. Но в данном случае Heroku не является основным репозиторием кода; она лишь выступает в роли альтернативного удаленного хранилища. Для развертывания приложения вы выполняете операцию push для его исходного кода через Git.

Заметьте, что Heroku развертывает проект не через файлы WAR, а «как есть». Как вы увидите, когда мы начнем создавать Procfile, для нашего приложения, Heroku – это просто JVM, ищущая код, который можно исполнить. (Чтобы убедиться в этом прямо сейчас, загляните в файл Main.java, созданный в структуре пакета вашего проекта, и сопоставьте его содержимое со своим POM.)

Совет

Если вы знакомы с Github, вы можете представить себе Heroku как дополнительный репозиторий, в который вы переводите нужные ветви своего кода, — например, ветвь разработки, ветвь контроля качества или промежуточного развертывания.

Хотя модель развертывания Heroku может показаться неочевидной, она становится понятной, как только вы начнете ею пользоваться. Более того, тесная интеграция Heroku с Git позволяет быстро и без проблем перемещать разные ветви в разные среды.

Двухэтапное развертывание

Развертывание выполняется в два этапа. Сначала вам нужно создать свой код и передать его в локальный репозиторий Git. Это можно сделать в корневой директории вашего проекта, набрав в терминале команды, приведенные в листинге 7:

Листинг 7. Инициализация и передача в Git
$> git init
$> git add .
$> git commit -m "начальная передача до развертывания в Heroku"

Теперь в локальном хранилище Git находится снимок вашего кода (т.е. создана его версия).

Затем нужно создать приложение в Heroku. Я сделал это в листинге 8 через клиент командной строки heroku (вот здесь важно, чтобы у вас были установлены Ruby и RubyGems):

Листинг 8. Создание приложения Heroku
$> heroku create marmaris --stack cedar

Команда heroku create в листинге 8 создает приложение с именем "marmaris" на стеке Cedar. Заметьте, что вам придется выбрать для приложения другое имя, поскольку это уже занято. Вы также можете предоставить выбор имени Heroku, и она сама создаст для вас уникальное имя.

Heroku имеет несколько стеков. Cedar поддерживает Java и Node.js, тогда как другие (например, Bamboo) поддерживают новые версии Ruby. Когда вы исполните команду heroku create, она обновит вашу конфигурацию Git и добавит дубликат удаленного хранилища heroku.

Файл Procfile в Heroku

Перед развертыванием своего кода в Heroku вы должны сообщить ей, как следует исполнять ваше приложение. Это легко делается с помощью Procfile, который является простым текстовым файлом с командой. Показанный ниже мой вариант Procfile указывает на скрипт командного процессора webapp в моей директории target.

Листинг 9. Создание Procfile
$> echo 'web: sh target/bin/webapp' > Procfile

После создания нового файла важно уведомить об этом Git; в противном случае Heroku не будет знать о его существовании при развертывании приложения через Git push.

Листинг 10. Уведомление Git
$> git add Profile
$> git commit -m "включение моего Profile"

И, наконец, чтобы развернуть приложение, вы просто подаете команду Git push в удаленный репозиторий heroku, как показано в листинге 11:

Листинг 11. Развертывание в Heroku
$> git push heroku

Вы должны увидеть несколько сообщений, поступивших от heroku; обратите внимание на то из них, которое имеет вид:

http://your_app_name.herokuapp.com deployed to Heroku

Введите этот адрес в свой любимый браузер (при условии, что вы оставили в директории проекта стандартный файл index.html), и вы увидите сообщение "Hello World!".

Конечно, всегда интересно читать сообщение "Hello World!", но цель моего приложения — принимать информацию о местоположении через HTTP PUT. Поэтому, используя RESTClient от WizTools.org, я могу подать команду HTTP PUT в мою конечную точку RESTful, создав документ JSON, и — вуаля! — я послал замечательный ответ JSON с прекрасным словом success (успех).


Масштабирование и обслуживание Heroku

По умолчанию Heroku запускает ваше приложение в одном контейнере (dyno). Этот бесплатный dyno отключается при отсутствии активности и включается снова при поступлении запроса. Если вам нужно расширить свое приложение, вы добавляете больше dyno, что можно сделать командой heroku scale:

Листинг 12. Масштабирование приложения
$> heroku scale web=2

При необходимости вы можете масштабировать приложение обратно, уменьшив число запрошенных dyno. Например, в данном случае я масштабируюсь обратно к размеру web=1. Обе эти операции можно выполнить и через веб-интерфейс Heroku.

Кроме того, в Heroku можно просматривать журналы с помощью команды heroku logs, как показано в листинге 13:

Листинг 13. Просмотр журналов в Heroku в реальном времени
$> heroku logs -t

Клиент командной строи heroku поддерживает множество функций масштабирования, мониторинга и управления вашим приложением; подробная документация приведена в Ресурсах . Кроме того, помимо стандартного хранилища Heroku поддерживает многие дополнительные компоненты сторонних поставщиков. Рекомендую ознакомиться с поддержкой Heroku для MongoHQ и PostgreSQL.


Заключение

Подкаст: Адам Уиггинс (Adam Wiggins) и Йеспер Йоргенсен (Jesper Joergensen) о системе Heroku

Этот подкаст расскажет вам о возникновении Heroku, о поддержке в ней нескольких языков и о том, как начать с ней работать.

Тесная интеграция Heroku с Git открывает новые пути развертывания и масштабирования приложений Java в облачной среде и при этом делает этот процесс чрезвычайно легким и эффективным. Лично меня привлекает свобода использования любых библиотек Java и развертывание созданных приложений практически без усилий.

Ресурсы

Научиться

Получить продукты и технологии

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Технология Java
ArticleID=830740
ArticleTitle=Java development 2.0: Вторая волна разработки Java-приложений: Развертывание приложений Java с помощью PaaS от Heroku
publish-date=08162012