Кастомное автоматическое обновление конфигураций клиентов Spring Cloud Config Server. Часть 1: настройка клиента

—

от автора

Рассмотрим техническое задание, которое включает в себя три основных пункта:

  1. настроить базовое автообновление конфигураций клиентов Spring Cloud Config Server.

  2. на сервере настроить принудительное обновление конфигураций клиентов, если состав хранимой на сервере конфигурации изменится каким-либо образом.

  3. при этом запрещается использовать технологию Spring Cloud Bus и связанную с ней передачу команд на обновление через Kafka или RabbitMQ.

Если вас удивил пункт 3 этого ТЗ, то вы не одиноки — меня он тоже очень удивил. Но это был реальный заказчик, очень негибкий, требовательный к условиям ТЗ и не склонный к переговорам. Учитывая степень его платежеспособности, спорить не хотелось, и иные варианты даже не обсуждались — словом, любой каприз за ваши деньги.

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

Итак, у нас есть клиент, обновлять его мы будем, используя возможности Spring Actuator, его использовать не запрещалось, тем более, что он может выполнять и прямые свои обязанности — сбор метрик, что также было нужно в проекте, как бывает и во многих других проектах. Чтобы это заработало, добавим в pom.xml проекта на Maven следующие зависимости:

        <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-security</artifactId>         </dependency>          <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-actuator</artifactId>         </dependency>          <dependency>             <groupId>org.springframework.cloud</groupId>             <artifactId>spring-cloud-starter-config</artifactId>         </dependency>          <dependency>             <groupId>org.springframework.cloud</groupId>             <artifactId>spring-cloud-starter-bootstrap</artifactId>         </dependency> 

Здесь все понятно — защита Spring Boot приложения, сам Actuator, две зависимости для Spring Cloud Server клиента.

В клиенте нам нужен файл bootstrap.yml, который будет лежать в ресурсах:

spring:     application:         name: pyramid     config:         import: optional:configserver:http://localhost:8800     profiles:         active: local     cloud:         config:             fail-fast: true             enabled: true             username: configserver             password: configserver     security:       user:           name: actuator           password: actuator           roles: ACTUATOR_ADMIN server:     port: 8082   #минимальная настройка Spring Actuator - ее нельзя переносить в  config-server, потому что мы нуждаемся в обновлении через него по умолчанию management:   endpoints:       enabled-by-default: true       web:         exposure:             include: "*" 

Здесь я привожу настройку для случая локального dev стенда, на котором сервер и клиент лежат на localhost, для переноса на сервер следует внести собственные правки адресов, портов и credentials. Секцию management вы также можете изменить под собственные нужды, добавив или более точно и безопасно перенастроив endpoints, для демонстрации я просто открыл все endpoints и опубликовал web, чтобы не возиться. В продуктовом приложении эта секция была настроена под нужды приложения, подробности которого здесь не обсуждаются. Фактически, данная настройка делает две вещи — предоставляет настройки для подключения к серверу Spring Cloud Config Server и предоставляет Spring Actuator с включенной примитивной авторизацией для того, чтобы использовать его для автообновления конфигураций.

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

@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter {      @Override     protected void configure(HttpSecurity http) throws Exception {         http                 .csrf().disable()                 .authorizeRequests()                 .requestMatchers(EndpointRequest.toAnyEndpoint())                 .hasRole("ACTUATOR_ADMIN")                 .requestMatchers(PathRequest.toStaticResources().atCommonLocations())                 .permitAll()                 .antMatchers("/")                 .permitAll()                 .antMatchers("/**")                 .authenticated()                 .and()                 .httpBasic()                 .and()                 .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);     }  } 

Ну вот, в общем-то и все самое главное о клиенте. Осталось добавить, что нужно разметить ваше приложение в нужных местах аннотациями @RefreshScope для передачи properties из конфигурации в код приложения там, где это вам нужно. Как это сделать, опять же можно посмотреть в статье, на которую я выше уже ссылался, или на мою статью, где этот вопрос также отчасти затронут для более редкого особенного случая. Полный код демо приложения можно посмотреть на github, в нем много не имеющего прямого отношения к данной статье (детали приложения с его специфическими нуждами), но все, что я здесь описал, вы найдете на своих местах.

Самое главное, что мы должны понять — без применения какого-либо механизма автообновления данный клиент будет забирать конфигурацию с сервера только при его загрузке или при кастомной инициации обновления. Если хранимая на сервере конфигурация будет изменена, клиент об этом ничего не узнает и будет использовать старые подгруженные значения до тех пор, пока мы не инициируем вручную запрос к клиенту на обновление конфигурации, в нашем случае мы используем для этого обращение к Spring Actuator, установленному на клиенте, по адресу https://client_url/actuator/refresh. Теоретически можно сделать и на самом клиенте bean с аннотацией @Scheduled, который будет опрашивать этот адрес с каким-то периодом, но это было бы совсем топорно, например, конфигурация будет загружаться заново независимо от того, были в ней обновления или нет, и клиент будет вхолостую выполнять массу совершенно не нужной работы в каждом периоде. Однако, если реализовать обращение к адресу Spring Actuator со стороны сервера и только при определенных условиях, то мы получим то, что требуется от нас в ТЗ. Поэтому так и поступим.

Во второй части статьи мы рассмотрим один из вариантов настройки сервера, продолжение в следующей статье.

Также хочу пригласить всех желающих на бесплатный урок от OTUS, в рамках которого будут рассмотрены аспекты — что это и зачем нужно. Как создавать аспекты в Java используя разные технологии, и как они используются в Spring. Регистрация доступна по ссылке.


ссылка на оригинал статьи https://habr.com/ru/company/otus/blog/681214/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *