Меня зовут Аксёнов Вячеслав, я старший бэкенд Java/Kotlin разработчик в крупном энтерпрайзе. Однажды я попал на проект, полный микросервисов, в котором за конфигурацию отвечала такая штука как Spring Cloud. Чтобы разобраться как именно это работает я исследовал и прикрутил этот диковенный элемент к одному своему пет проекту. И в этой статье я пошагово покажу как я это сделал. А если точнее - как настроить Spring Cloud сервер конфигурации.

Немного вводных данных

В наше время программирование переросло из чего-то магического и таинственного в довольно прозаичное занятие. Построение бэкенд приложения перестало напоминать построение монолита с местными прикладными решениями разной степени понятности и магии. Место постройки собственных велосипедов заняло использование уже готовых решений, подходящих для конкретных задач. 

Для бэкеда крупных систем прямо сейчас в преимуществе используется Java/Kotlin в качестве основного языка программирования. А там где есть Java и энтрпрайз, там рука об руку идет Spring Framework. И так как строить монолиты сейчас не модно, выбор делается в сторону микросервисов. (мое мнение, что делать микросервисы совсем уж микро  не стоит. Каждый сервис должен отвечать отдельной бизнес задаче. Но об этом я напишу в отдельной статье) И вот есть зоопарк сервисов - у каждого есть свои конфиги. И их нужно как-то менеджить. Вопрос - как это сделать?

Итак, какую проблему решает Spring Cloud? Представим, что у вас есть 5 приложений на Java/Spring, каждое при старте подгружает разные конфиги (пароли/адреса для базы, внешних апи и тд). Есть разные окружения - test, dev, prod, stage и тд. Spring Cloud позволяет хранить все конфигурации для разных приложений и разных окружений в одном месте.

Как же запускать?

Давайте разбираться как запускать эту систему на простом примере.

Есть несложное приложение на Spring, которое нужно научить ходить в клауд за конфигами. В моем случае этим является бот для логирования рабочего времени в телеграме, который я написал для личных целей - whid (what have I done). Но код открытый - кому интересно можете пользоваться моим, либо запустить для себя. На бизнес логику можно не обращать внимания, нас интересует только конфигурация для работы с Spring Cloud.

Настройка стороны сервиса:

Для этого в список зависимостей нужно добавить spring-cloud-starter-config и spring-cloud-starter-bootstrap:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-config</artifactId>
  <version>3.0.5</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
  <version>3.0.4</version>
</dependency>

Версии зависимостей можно брать актуальные с https://search.maven.org/

Пример в pom.xml: https://github.com/v-aksenov/whid-bot/blob/master/pom.xml#L35-L44

Также application.properties заменяется на bootstrap.yml, в которой нужно указать название текущего приложения и адрес для подключения к спринг клауду.

spring:
	application:
  	name: whid-bot
  config:
  	import: http://localhost:8888/

В данном случае название приложения whid-bot, а адрес для клауда http://localhost:8888/

Этого достаточно - стартеры для spring-cloud уже включают в себя нужные настройки, которые позволят сервису при запуске правильно понять, что используется spring cloud и правильно сходить к нему по настройкам, используемым в bootstrap.yml. 

Настройка на стороне spring cloud:

Сам сервис конфигурации является отдельным спринг бут приложением. Для построения такого приложения требуются зависимость spring-cloud-config-server:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
    <version>3.0.5</version>
</dependency>

А также остальные зависимости, которые потребуются для работы spring boot приложения, как пример мой pom.xml: https://github.com/v-aksenov/spring-cloud-public/blob/master/pom.xml

Самое интересное начинается в конфигурации этого приложения.

spring.application.name=spring-cloud-name
server.port=8888
spring.cloud.config.server.git.uri=https://github.com/user/repo.git
spring.cloud.config.server.git.username=git_user
spring.cloud.config.server.git.password=*******
spring.cloud.config.server.git.searchPaths={application}

Что значит каждый параметр по порядку:

server.port=8888 - указывает порт, на котором будет запущен клауд. Если не конкретизироваться, то поднимется на дефолтном спринговом 8080

spring.cloud.config.server.git.uri=https://github.com/user/repo.git - так как клауд удобнее всего использовать с конфигами, хранящимися в гите, то конечно ссылка на репозиторий с вашими конфигами, может быть как github, так gitlab, stash и тд.

spring.cloud.config.server.git.username=v-aksenov

spring.cloud.config.server.git.password=password

spring.cloud.config.server.git.username, spring.cloud.config.server.git.password=password- соответственно логин и пароль для подключения к репозиторию с конфигами.

spring.cloud.config.server.git.searchPaths={application} - это указатель того, что для поиска параметров будет использоваться значение из spring.application.name у приложения, которое обращается к клауду.

Стоит держать в голове, что для разных профилей конфигурации нужно хранить в разных файлах. Например для профиля test - whid-bot-test.yml - для тестового окружения и для профиля prod - whid-bot-prod.yml для продового.

Примеры файлов конфигурации

Внутри моего приватного репозитория, где я храню конфиги для своих пет проектов лежит файлик с конфигурацией моего бота. Файл хранит в себе ровно то, что вы бы хранили в application.properties внутри основного приложения.

whid.yml:

bot:
  username: whiddy_bot
  token: *******
  active: true

spring:
  datasource:
    url: jdbc:h2:file:./h2-data/whid-bot
    username: *******
    password: *******
    driverClassName: org.h2.Driver
  jpa:
    spring.jpa.database-platform: org.hibernate.dialect.H2Dialect
    hibernate.ddl-auto: update
  h2:
    console:
      enabled: true
      path: /h2-console

logging:
  level:
    root: INFO
  file:
    name: ./logs/whid-bot-logs.log

Итог

Всего вышеописанного достаточно для того, чтобы запустить собственный сервис конфигурации spring cloud и настроить ваш сервис для хождения за конфигами в него. Эта статья была написана как для тех, кто только разбирается с разными элементами инфраструктуры, которые позволяет наворотить Spring Framework, а также для лично меня, который сейчас разобрался в теме и в будущем обязательно забудет, но сможет посмотреть здесь.

Ссылки на проект бота

Ссылка на проект кладуа

Надеюсь, статья была для вас полезна, буду рад вашим комментариям о том как кто-то из вас готовит архитектуру собственных пет проектов. Будет здорово, если каждый сможет узнать для себя что-то новое.

Всем чистого кода и хорошего дня :)

Фото обложки от: https://unsplash.com@pericakalimerica

Комментарии (13)


  1. dissdoc
    02.02.2022 17:55
    +6

    Будет статья о том, как запустить Spring Boot приложение?


    1. v-aksenov Автор
      02.02.2022 18:37

      Думаю, что нет. Их и так достаточно :)


  1. GaDzik
    02.02.2022 19:19
    +2

    Что узнал. Главное понял что может и сам смогу. Есть пет, есть REST, нет мотивации.


    1. v-aksenov Автор
      02.02.2022 19:58
      +1

      Как минимум для себя разобраться и живьем попробовать я бы рекомендовал. Хуже точно не будет :)


  1. amarkevich
    02.02.2022 19:24
    +2

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

    Как синхронизировать конфиг в процессе разработки, запускать тесты?
    Логика настроек по итогу раздваивается. как обстоят дела с версионностью? (ок, в application можно версию суффиксом).


    1. taluyev
      02.02.2022 20:02

      За версионностью следит стстема контроля версий.

      В тестах свои пропертис отдельные

      идея такого подхода держать настройки в одном месте для разных инстансов


    1. v-aksenov Автор
      02.02.2022 20:04

      О да! Для маленьких проектов он однозначно заставит задуматься о тех вопросах, которые появляются во взрослых проектах. Пришлось протестировать различные схемы.
      Для работы gitlab-ci тестов в изолированном окружении я понял, что проще всего будет хранить конфиги для тестов прямо в приложении. Но когда в твоем окружении есть доступ к всегда запущенному клауду, а параметров для разных контуров становится слишком много - вот тут клауд очень помогает!

      По поводу версионности - сразу приходит на ум через суффикс в application, да. Но версионность - весьма редкая схема для конфигов все же, как мне кажется.


    1. soir
      02.02.2022 23:45
      +1

      Spring Cloud Config не нужно использовать на dev среде, т.е. на компьютере разработчика. На компьютере разработчика удобно хранить конфигурацию в файле application-dev.yml

      Spring Cloud Config удобен для хранения настроек на серверах, в облаке. Версионность конфигурации реализуется подключение к нему репозитория в GIT в качестве источника данных


  1. nbog
    02.02.2022 19:57
    +3

    Хотел бы отметить, что то, что вы описали - это только Spring Cloud Config Server и его использование. Это очень небольшая часть Spring Cloud, куда входит куча всего.

    Например service discovery, routing, load balancing, circuit breakers и прочие штуки от Netflix.

    https://spring.io/projects/spring-cloud - вот тут много


    1. v-aksenov Автор
      02.02.2022 20:08
      +1

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

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


      1. nbog
        02.02.2022 23:08
        +2

        Мы используем Spring Cloud уже несколько лет, 100+ микросервисов, много разных environments, включая production. Прошли от Unix -> PCF ->K8S, довольно стабильна эта часть Spring Cloud.

        Ещё момент ... конфигурации (через spring profiles) можно хранить в ОДНОМ (для одного приложения) yaml файле. Это удобнее, ИМХО, для сопровождения. Кроме того можно сделать shared секцию, куда попадают общие настройки для все spring profiles.


        1. v-aksenov Автор
          03.02.2022 20:46

          Да, кстати. Поиск конфигурации идет по порядку service-profile.yml -> service.yml -> application.yml

          Можно хранить общие для сервисов конфигри на самом низком уровне


  1. chemtech
    03.02.2022 07:59

    Спасибо за пост. Подскажите, пожалуйста, если знаете. Есть проект https://github.com/spring-petclinic/spring-petclinic-cloud

    Я пытаюсь запустить spring-petclinic-cloud в kubernetes. Получаю ошибку java.net.UnknownHostException: wavefront-proxy

    Issue есть https://github.com/spring-petclinic/spring-petclinic-cloud/issues/39

    Разработчики хотят обновить Spring Cloud и убрать Spring Cloud's bootstrap context.

    Можете помочь с тестированием https://github.com/spring-petclinic/spring-petclinic-cloud/pull/43 ?

    Спасибо.