Статьи

Развертывание приложения Spring Boot в Cloud Foundry с помощью Spring-Cloud

У меня есть небольшое  приложение  ,  основанное на  загрузке Spring, которое использует базу данных Postgres в качестве хранилища данных. Я хотел задокументировать действия по развертыванию этого примера приложения в  Cloud FoundryНекоторые из  шагов  описаны в справочном руководстве по Spring Boot, однако в руководствах недостаточно разъясняется, как интегрироваться с хранилищем данных, предоставляемым в облачной среде. Spring-cloud  обеспечивает связь между приложениями Spring, развернутыми в облаке, для обнаружения и подключения к связанным службам, поэтому первым шагом является включение библиотек Spring-cloud в проект со следующими записями pom:

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-spring-service-connector</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cloudfoundry-connector</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>

Как только эта зависимость установлена, подключение к связанному сервису становится простым, просто определите конфигурацию по следующим направлениям:

@Configuration
public class PostgresCloudConfig extends AbstractCloudConfig {

@Bean
public DataSource dataSource() {
  return connectionFactory().dataSource();
}

}
Spring-Cloud понимает, что приложение развертывается в определенном облаке (в настоящее время Cloud Foundry и Heroku ищут определенные характеристики развернутой платформы Cloud), обнаруживает связанные службы, распознает, что существует связанная служба, с помощью которой источник данных на основе Postgres может быть создан и возвращает источник данных как бин Spring.

Это приложение теперь может быть развернуто в облаке на основе Cloud Foundry. Пример приложения может быть опробованы в версии Cloud Foundry развернуты с  заплечиков-лайт , это как шаги в моей машине выглядит как раз Cloud Foundry это и работает с заплечиков-лайт:

Следующая команда создает при условии пользователя службы в Cloud Foundry:

cf create-user-provided-service psgservice -p '{"uri":"postgres://postgres:[email protected]:5432/hotelsdb"}'
Теперь нажмите приложение, но не запускайте его. Мы можем сделать это, как только вышеуказанный сервис привязан к приложению:

cf push spring-boot-mvc-test -p target/spring-boot-mvc-test-1.0.0-SNAPSHOT.war --no-start

Свяжите сервис с приложением и перезапустите приложение:

cf bind-service spring-boot-mvc-test psgservice
cf restart spring-boot-mvc-test

По сути, Spring Cloud в идеале должен взять на себя управление и аккуратно проанализировать учетные данные связанной службы, которая в Cloud Foundry преобразуется в переменную среды VCAP_SERVICES, и создать из нее источник данных.

Однако в этом подходе есть проблема: после создания bean-компонента источника данных с использованием весенне-облачного подхода он больше не работает в локальной среде. 

Потенциальным решением этой проблемы является использование профилей Spring, если предположить, что в облачной среде имеется другой «облачный» профиль Spring, в который возвращается источник данных на основе облака:

@Profile("cloud")
@Configuration
public class PostgresCloudConfig extends AbstractCloudConfig {

@Bean
public DataSource dataSource() {
return connectionFactory().dataSource();
}
}

и пусть автоконфигурация Spring-boot создаст источник данных в локальной среде по умолчанию, таким образом, конфигурация работает как локально, так и в облаке. Откуда этот «облачный» профиль, он может быть создан с помощью  ApplicationContextInitializer и выглядит следующим образом:

public class SampleWebApplicationInitializer implementsApplicationContextInitializer<AnnotationConfigEmbeddedWebApplicationContext> {

private static final Log logger = LogFactory.getLog(SampleWebApplicationInitializer.class);

@Override
public void initialize(AnnotationConfigEmbeddedWebApplicationContext applicationContext) {
Cloud cloud = getCloud();
ConfigurableEnvironment appEnvironment = applicationContext.getEnvironment();
if (cloud!=null) {
appEnvironment.addActiveProfile("cloud");
}
logger.info("Cloud profile active");
}

private Cloud getCloud() {
try {
CloudFactory cloudFactory = new CloudFactory();
return cloudFactory.getCloud();
} catch (CloudException ce) {
return null;
}
}
}

Этот инициализатор использует возможности сканирования Spring-cloud для активации «облачного» профиля.

И последнее, что я хотел попробовать, — это заставить мой локальный объект вести себя как облако по крайней мере в глазах Spring-Cloud, и это можно сделать, добавив некоторые переменные окружения, с помощью которых Spring-Cloud определяет тип облака, в котором приложение развернуто, ниже приведен мой сценарий запуска на локальном компьютере, чтобы приложение притворилось, будто оно развернуто в Cloud Foundry:

read -r -d '' VCAP_APPLICATION <<'ENDOFVAR'
{"application_version":"1","application_name":"spring-boot-mvc-test","application_uris":[""],"version":"1.0","name":"spring-boot-mvc-test","instance_id":"abcd","instance_index":0,"host":"0.0.0.0","port":61008}
ENDOFVAR

export VCAP_APPLICATION=$VCAP_APPLICATION

read -r -d '' VCAP_SERVICES <<'ENDOFVAR'
{"postgres":[{"name":"psgservice","label":"postgresql","tags":["postgresql"],"plan":"Standard","credentials":{"uri":"postgres://postgres:[email protected]:5432/hotelsdb"}}]}
ENDOFVAR

export VCAP_SERVICES=$VCAP_SERVICES

mvn spring-boot:run

Весь этот образец доступен в  этом  GitHub месте: https://github.com/bijukunjummen/spring-boot-mvc-test

Вывод

Spring Boot вместе с проектом Spring-Cloud теперь предоставляют отличный набор инструментов для создания облачных приложений, готовых к работе на платформе Spring, и, надеюсь, эти заметки полезны для интеграции Spring Boot с Spring-Cloud и использования их для бесшовных локальных и облачных развертываний.