Данная статья является частью статей об использование Spring Cloud #Про Spring Cloud.
Немного теории
Проект Spring Cloud Config предназначен для управления конфигурациями в облачном решении. Проект предлагает централизованное хранилище конфигураций приложений, которое легко может масштабироваться горизонтально. В качестве источника конфигураций используется файловая система, GIT, SVN, Hashicorp Vault, JDBC Backend. Также можно использовать композитные источники данных. В данной статье мы будем использовать файловую систему.
По умолчанию Spring Cloud Config отдает файлы, соответствующие имени запрашивающего Spring приложения. Также могут учитываться активные Spring profiles и свойства label проекта (параметр spring.cloud.config.label в конфигурации проекта).
Имя приложения указывает в параметре spring.application.name. Как правило, в проектах указывается одно имя приложения в этом параметре. НО, запрета на использования нескольких имен для данного параметра нет и Spring Cloud Config Server умеет работать с несколькими именами, записанными через запятую (например, spring.application.name = a,b,c). Данную возможность можно использовать для подгрузки конфигурации из нескольких файлов одновременно. Аналогично данное утверждение применимо для профайлов (параметр spring.profiles.active)
Для конфигурирования приложения могут использоваться файлы: .properties, .yml, .yaml. Порядок формирования конфигурации (по увеличению приоритета параметров):
- application.yml
- application-{profile}.yml
- {application.name}.yml
- {application.name}-{profile}.yml
- {label}/application.yml
- {label}/application-{profile}.yml
- {label}/{application.name}-{profile}.yml
Встраивание Spring Cloud Config в любое приложение можно разделить на два основных подхода: Config First Bootstrap или Discovery First Bootstrap. В первом случае инициализация идет через сервер управления конфигурациями, таким образом приложению необходимо знать где расположен Spring Cloud Config Server (параметр spring.cloud.config.url, по умолчанию поиск идет по адресу http://config:8888) и данные для аутентификации, если они применяются. Во втором случае доступ к Spring Cloud Config Server осуществляется через Service Discovery, который имеет данные о местоположении сервиса конфигурации. Им может выступать Eureka Service Discovery или Hashicorp Consul. Для защиты точек доступа Spring Cloud Config Server может применяться Spring Security, поэтому мы не ограничены в механизме защиты точек доступа.
В реальной жизни при старте микросервисной инфраструктуры Spring Cloud Config Server может быть запущен позже других сервисов, поэтому рекомендуется настроить механизм повтора запроса конфигурации в случае неуспешного первого обращения. Для этого необходимо подключить две зависимости spring-retry и spring-boot-starter-aop и установить параметр spring.cloud.config.fail-fast=true. Настройки механизма повтора находятся в разделе spring.cloud.config.retry.*
Создание сервера конфигурации
Первым шагом необходимо создать новый модуль в gradle в директории ./backend с именем config-server
Настроим содержимое файла gradle.build следующим образом. Напоминаю, что переменные версий (такие как bootGradlePlugin или springCloudConfig) вынесены в базовый build.gradle в директории ./backend
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${bootGradlePlugin}")
}
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-config:${springCloudConfig}"
}
}
bootJar {
baseName = 'ac-config-server'
}
dependencies {
compile 'org.springframework.cloud:spring-cloud-config-server'
}
Также необходимо создать базовый класс ConfigServerApplication.java для запуска Spring Boot приложения. Для создания встроенного (embedded) Config Server необходиом добавить аннотацию @EnableConfigServer
package com.balynsky.ac.config.server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
Так же необходимо настроить параметры приложение, указав активный профайд “native”, чтобы поиск конфигурации осуществлялся в файловой системе (по умолчанию источником конфигураций используется GIT репозиторий). Для этого в каталоге resources необходимо создать файл bootstrap.yml следующего содержимого:
spring:
cloud:
config:
server:
bootstrap: true
profiles:
include: native
application:
name: config-server
Мы задали параметр spring.cloud.config.bootstrap = true, чтобы Config Server также инициировал свои настройки из конфигурационного хранилища (в нашем случае - файловой системе)
Чтобы указать где расположено конфигурационное хранилище, используется параметр spring.cloud.config.native.searchLocations. Если параметр не задан, поиск осуществляется в дефолтных: classpath:/, classpath:/config/, file:./, file:./config/
В реальных проектах не рекомендуется помещать конфигурации внутрь jar приложения, но для тестового стенда, в нашем случае мы поместим конфигурации в classpath:/config/. Для этого в каталоге resources проекта config-server создадим каталог config, в котором создадим следующие файлы:
- application.yml
- config-server.yml
- backup-service.yml
- storage-service.yml
- user-service.yml
При запуске проекта мы имеем ошибку java.lang.IllegalStateException: You need to configure a uri for the git repository из за включенного параметра bootstrap = true, которая описана в Issue. Поэтому временно применим обходное решение из данного тикета (используем профайл composite), для этого изменим bootstrap.yml
spring:
cloud:
config:
server:
composite:
- type: native
bootstrap: true
profiles:
include: composite
application:
name: config-server
В файле настройки config-server.yml укажем порт, на котором должен запуститься сервис (по умолчанию идет запуск на 8080):
server:
port: 8888
Подключение к Spring Config Server
Опишем подключение к конфигурационному серверу для проекта storage-service, остальные проекты подключаются аналогичным образом. Само подключение конфигурации начнем с добавления необходимых зависимостей:
dependencies {
// ...
compile("org.springframework.retry:spring-retry:${springRetry}")
compile("org.springframework.boot:spring-boot-starter-aop")
compile 'org.springframework.cloud:spring-cloud-starter-config'
// ...
}
Как описывалось ранее зависимости spring-retry и spring-boot-starter-aop необходимы для обеспечения механизма повтора запроса конфигурации с сервера, если при первом обращении была получена ошибка (например, сервер не был инициирован)
Следующий шаг, мы переносим содержимое файла backup-service/…/resources/application.yml в файл backup-service.yml в проекте config-server. Вместо него необходимо создать файл bootstrap.yml, в котором укажем данные для подключения к конфигурационному серверу. Содержимое файла bootstrap.yml:
spring:
cloud:
config:
fail-fast: true
uri: http://localhost:8888
application:
name: backup-service
После запуска приложения в логах можно увидеть записи подключения к конфигурационному серверу и получения конфигурации:
c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://localhost:8888
c.c.c.ConfigServicePropertySourceLocator : Located environment: name=backup-service, profiles=[default], label=null, version=null, state=null
b.c.PropertySourceBootstrapConfiguration : Located property source: CompositePropertySource {name='configService', propertySources=[MapPropertySource {name='classpath:/config/backup-service.yml'}]}
Аналогичным образом изменяем два оставшихся приложения: storage-service и user-service.
Итоги:
В рамках этой статьи, мы научили наши приложения получать конфигурацию с внешнего источника (Spring Config Server),и у нас получилась следующая архитектура нашего проекта:
Проект опубликован в репозитории на GitHub