Используйте Spring Cloud Config для единообразного управления конфигурацией, прекратите размещать файлы конфигурации повсюду

Spring Boot Java Spring Spring Cloud Docker Kubernetes

1. Введение

Добро пожаловать в гостиМедленный разговор тыквы www.pkslow.comПолучайте больше отличных статей!

Настраиваемость — это функция, которую должна предоставлять зрелая программная система, а управление конфигурацией очень важно для больших систем, особенно для микросервисных систем с несколькими приложениями. самое замечательное,SpringПредоставляет нам хорошее управление конфигурацией, напримерSpringbootконфигурация очень мощная. заSpring Cloud, есть сильнаяSpring Cloud Config, который обеспечивает управление конфигурацией вне приложения, например файлами илиGitРепозитории очень полезны для управления конфигурацией распределенных систем.

2 Быстрый опыт

Spring Cloud ConfigСервер представляет собойSpringbootПрименение, запуск и развертывание очень просты.

Общая структура показана на следующем рисунке:

2.1 Сервер представляет собой Springboot

существуетSpringbootДобавьте зависимости следующим образом:

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

Все, что вам нужно, это один, он уже содержитwebиactuator.

Добавить кJavaОсновной класс:

package com.pkslow.config;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@SpringBootApplication
@EnableConfigServer
public class ConfigServer {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServer.class,args);
    }
}

с обычнымSpringbootПо сравнению с приложением только на одну аннотацию больше@EnableConfigServerВот и все.

2.2 Настройка склада

Через мы будем управлять конфигурацией через контроль версий, обычно используемGitСклад, используйте локальный склад для простой демонстрации следующим образом:

# 创建目录
mkdir git-repo

# 初始化一个git目录
git init

# 新建文件
touch application.properties

# 添加变更
git add .

# 提交变更
git commit -m "init"

настроить проектapplication.properties, Обратите внимание, чтоConfig Serverпроект, не вgit-repoв каталоге:

server.port=8888
spring.application.name=config-server
spring.cloud.config.server.git.uri=/Users/pkslow/IdeaProjects/pkslow-modules/config-server/git-repo

Тогда вы можете начатьConfig Server.

ноgitВ конфигурационном файле на складе ничего нет.Добавляем следующий контент и отправляем (он должен быть отправлен, иначе его нельзя получить).

pkslow.webSite=www.pkslow.com
pkslow.age=18
pkslow.email=admin@pkslow.com

2.3 Соответствие пути конфигурации

Так как же нам получить эти конфигурации? посредством следующихURLЧитать:

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
  • labelОтносится к ветвям кода, таким какmaster,feature-1Ждать.

  • applicationИмя приложения, которое будет использоваться клиентом в дальнейшем.

  • profileОбычно используется для указания среды, напримерprod,dev,uatЖдать.

Итак, мы можем использовать следующиеURLЧтобы получить информацию о конфигурации, которую мы только что добавили:

http://localhost:8888/application/default
http://localhost:8888/application/default/master
http://localhost:8888/master/application.properties
http://localhost:8888/application-default.properties

Доступ следующим образом:

$ curl http://localhost:8888/application/default/master
{"name":"application","profiles":["default"],"label":"master","version":"8796f39b35095f6e9b7176457eb03dd6d62b1783","state":null,"propertySources":[{"name":"/Users/pkslow/IdeaProjects/pkslow-modules/config-server/git-repo/application.properties","source":{"pkslow.webSite":"www.pkslow.com","pkslow.age":"18","pkslow.email":"admin@pkslow.com"}}]}

последний адрес/{label}/{application}-{profile}.propertiesФормат возвращаемого результата отличается, а содержимое файла конфигурации возвращается напрямую:

$ curl http://localhost:8888/application-default.properties
pkslow.age: 18
pkslow.email: admin@pkslow.com
pkslow.webSite: www.pkslow.com

Если мы сначала создадим веткуrelease-20200809и изменитьageфактический возраст9, то следующим образом:

$ curl http://localhost:8888/application/default/release-20200809
{"name":"application","profiles":["default"],"label":"release-20200809","version":"7e27e6972ed31ee1a51e9277a2f5c0a628cec67a","state":null,"propertySources":[{"name":"/Users/pkslow/IdeaProjects/pkslow-modules/config-server/git-repo/application.properties","source":{"pkslow.webSite":"www.pkslow.com","pkslow.age":"9","pkslow.email":"admin@pkslow.com"}}]}

можно увидеть соответствующийpkslow.ageстал9, но доступ/application/default/masterвсе еще18, ветви не влияют друг на друга.

2.4 Удаленный склад

Локальный склад предназначен только для простого отображения, в реальных проектах обычно используются удаленные склады.GitHubСоздайте новый репозиторий следующим образом:

специально созданныйprivateчтобы проверить правильность последующей аутентификации.

Адрес перенастроенного репозитория следующий:

spring.cloud.config.server.git.uri=https://github.com/pkslow/pkslow-config
spring.cloud.config.server.git.username=admin@pkslow.com
spring.cloud.config.server.git.password=***
spring.cloud.config.server.git.default-label=master
spring.cloud.config.server.git.search-paths=demo

Создаватьdemoкаталог для размещения конфигурации, поэтомуsearch-pathsнастроен какdemo. После завершения настройки и перезапуска сервера конфигурация удаленного хранилища может нормально читаться.

2.5 Несколько репозиториев конфигурации кода

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

  • (1) Обнаружение службы: обнаружение, кодовая база pkslow-discovery-service
  • (2) Шлюз API: шлюз, кодовая база pkslow-gateway-service
  • (3) Услуга заказа: заказ, кодовая база pkslow-order-service

Соответствующие файлы конфигурации размещены в соответствующих базах кода, поэтому необходимо настроить несколько баз кода. Также настраиваем еще одну библиотеку конфигурации по умолчанию pkslow-default, если она не совпадает, будет выбрана конфигурация библиотеки кода по умолчанию. Конкретная конфигурация выглядит следующим образом:

server:
  port: 8888
spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: /Users/pkslow/multiple-repos/pkslow-default
          repos:
            pkslow-discovery-service:
              pattern: pkslow-discovery-*
              cloneOnStart: true
              uri: /Users/pkslow/multiple-repos/pkslow-discovery-service
              search-paths: config
            pkslow-gateway-service:
              pattern: pkslow-gateway-*/dev
              cloneOnStart: true
              uri: /Users/pkslow/multiple-repos/pkslow-gateway-service
              search-paths: config
            pkslow-order-service:
              pattern: pkslow-order-*
              cloneOnStart: true
              uri: /Users/pkslow/IdeaProjects/pkslow-order-service
              search-paths: config

Каталог, в который можно поместить каждый пользовательский файл конфигурации.search-paths, если он не настроен, по умолчанию используется корневой каталог.

здесьpatternПравило конфигурации{application}/{profile}, поддерживает обычные символы*. Обратите внимание, что соответствует только один результат, если все удовлетворены, берется только первый соответствующий склад.

После запуска посмотрим на результаты настройки:

# 默认profile和label,正确匹配
$ curl http://localhost:8888/pkslow-order-service/default/master
{"name":"pkslow-order-service","profiles":["default"],"label":"master","version":"9d86e5d11974f0a0e7c20cd53d8f062755193e70","state":null,"propertySources":[{"name":"/Users/pkslow/IdeaProjects/pkslow-modules/config-server/multiple-repos/pkslow-order-service/config/application.properties","source":{"pkslow.webSite":"www.pkslow.com","pkslow.app.name":"order-service"}}]}

# 正确匹配,但不存在的Label,配置库没有对应代码分支,404
$ curl http://localhost:8888/pkslow-order-service/default/release
{"timestamp":"2020-08-13T06:58:38.722+0000","status":404,"error":"Not Found","message":"No such label: release","path":"/pkslow-order-service/default/release"}

# profile为dev,正确匹配
$ curl http://localhost:8888/pkslow-order-service/dev/master
{"name":"pkslow-order-service","profiles":["dev"],"label":"master","version":"9d86e5d11974f0a0e7c20cd53d8f062755193e70","state":null,"propertySources":[{"name":"/Users/pkslow/IdeaProjects/pkslow-modules/config-server/multiple-repos/pkslow-order-service/config/application.properties","source":{"pkslow.webSite":"www.pkslow.com","pkslow.app.name":"order-service"}}]}

# 对于gateway只能匹配profile=dev,无法匹配,读取默认配置
$ curl http://localhost:8888/pkslow-gateway-service/default/master
{"name":"pkslow-gateway-service","profiles":["default"],"label":"master","version":"8358f2b4701fac21a0c7776bc46cec6d9442c549","state":null,"propertySources":[{"name":"/Users/pkslow/IdeaProjects/pkslow-modules/config-server/multiple-repos/pkslow-base/application.properties","source":{"pkslow.birthDate":"2020-08-10"}}]}

# 对于gateway只能匹配profile=dev,正确匹配
$ curl http://localhost:8888/pkslow-gateway-service/dev/master
{"name":"pkslow-gateway-service","profiles":["dev"],"label":"master","version":"1a4e26849b237dc2592ca0d391daaa1a879747d2","state":null,"propertySources":[{"name":"/Users/pkslow/IdeaProjects/pkslow-modules/config-server/multiple-repos/pkslow-gateway-service/config/application.properties","source":{"pkslow.webSite":"www.pkslow.com","pkslow.app.name":"gateway-service"}}]}

# 不存在的服务名,无法匹配,读取默认配置
$ curl http://localhost:8888/unknown-service/dev/master
{"name":"unknown-service","profiles":["dev"],"label":"master","version":"8358f2b4701fac21a0c7776bc46cec6d9442c549","state":null,"propertySources":[{"name":"/Users/pkslow/IdeaProjects/pkslow-modules/config-server/multiple-repos/pkslow-base/application.properties","source":{"pkslow.birthDate":"2020-08-10"}}]}

3 Конфигурация использования клиента

Из предыдущих примеров мы узнали, как сервер получает конфигурацию из базы кода, но все же необходимо дать клиенту возможность получить соответствующую конфигурацию и произвести эффект. Давайте продемонстрируем.

3.1 Подготовка проекта

Построить самый простойSpringboot Webпункт, плюсSpring Cloud Configподдержки, добавьте зависимости следующим образом:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

Добавьте файл конфигурации:bootstrap.properties(Хотя мы должны прочитать конфигурацию с сервера, некоторые конфигурации должны быть добавлены клиентом, например, адрес сервера), как показано ниже:

server.port=8080
spring.application.name=pkslow-gateway-service
spring.cloud.config.uri=http://localhost:8888

Здесь мы настраиваем порт клиента, адрес сервера и имя клиентского приложения Это имя очень важно и будет объяснено позже.

Добавить кControllerвыставлятьAPIЧтобы отобразить содержимое конфигурации, прочитайте:

@RestController
public class PkslowController {
    @Value("${pkslow.age}")
    private Integer age;

    @Value("${pkslow.email}")
    private String email;

    @Value("${pkslow.webSite}")
    private String webSite;

    @GetMapping("/pkslow")
    public Map<String, String> getConfig() {
        Map<String, String> map = new HashMap<>();
        map.put("age", age.toString());
        map.put("email", email);
        map.put("webSite", webSite);
        return map;
    }
}

Затем запустите клиент, и результаты доступа будут следующими:

$ curl http://localhost:8080/pkslow
{"webSite":"default.pkslow.com","age":"9","email":"admin@pkslow.com"}

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

3.2 Как соотносятся клиенты

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

  • labelОтносится к ветке кода.

  • applicationэто имя приложения.

  • profileОбычно используется для указания среды.

В предыдущем примере имя клиентаpkslow-gateway-service;labelне указано, по умолчаниюmaster;profileне указано, по умолчаниюdefault.

Соответствуем правилам на стороне сервера, т.к.pattern: pkslow-gateway-*/dev, поэтому оно может совпадать с именем, но неprofile, поэтому читается конфигурация репозитория по умолчанию:

$ cat pkslow-base/application.properties 
pkslow.webSite=default.pkslow.com
pkslow.age=9
pkslow.email=admin@pkslow.com

Измените конфигурацию клиента, настройтеprofileзаdevследующее:

server.port=8080
spring.application.name=pkslow-gateway-service
spring.profiles.active=dev
spring.cloud.config.uri=http://localhost:8888

Получите конфигурацию клиента снова следующим образом:

$ curl http://localhost:8080/pkslow
{"webSite":"gateway-master.pkslow.com","age":"9","email":"admin@pkslow.com"}

Видно что прочитаноpkslow-gateway-serviceСодержание конфигурации склада:

$ cat pkslow-gateway-service/config/application.properties 
pkslow.webSite=gateway-master.pkslow.com
pkslow.age=9
pkslow.email=admin@pkslow.com

существуетpkslow-gateway-serviceВетка нового кода складаreleaseИ добавьте конфигурацию, а затем измените конфигурацию клиента следующим образом:

server.port=8080
spring.application.name=pkslow-gateway-service
spring.profiles.active=dev
spring.cloud.config.label=release
spring.cloud.config.uri=http://localhost:8888

После перезапуска снова зайдите и правильно прочитайте конфигурацию новой ветки:

$ curl http://localhost:8080/pkslow
{"webSite":"gateway-release.pkslow.com","age":"9","email":"admin@pkslow.com"}

3.3 Проблема вступления в силу конфигурации клиента

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

$ git commit -a -m "update"
[release 0e489fe] update
 1 file changed, 2 insertions(+), 2 deletions(-)

$ curl http://localhost:8888/pkslow-gateway-service/dev/release
{"name":"pkslow-gateway-service","profiles":["dev"],"label":"release","version":"0e489fec5de73b1a6d11befa3f65e44836979e23","state":null,"propertySources":[{"name":"/Users/pkslow/IdeaProjects/pkslow-modules/config-server/multiple-repos/pkslow-gateway-service/config/application.properties","source":{"pkslow.webSite":"gateway-release.pkslow.com","pkslow.age":"10","pkslow.email":"admin@pkslow.com"}}]}

$ curl http://localhost:8080/pkslow
{"webSite":"gateway-release.pkslow.com","age":"9","email":"admin@pkslow.com"}

Получается, что сервер подействовал, а клиент нет. Это связано с тем, что в этом режиме клиент будет только читать конфигурацию, чтобы сделать ее действительной при запуске. Если мы хотим, чтобы клиент также вступил в силу, мы должны использоватьSpringboot actuatorкоторый предоставил/refreshКонечные точки делают.

добавить первымactuatorполагаться:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

конфигурация для обеспечения/refreshМожно получить доступ, добавьте следующую конфигурацию:

management.endpoints.web.exposure.include=refresh

Укажите диапазон обновления вControllerдобавить аннотации@RefreshScopeследующее:

@RefreshScope
@RestController
public class PkslowController {
//xxx
}

Перезапустите приложение. Действие и эффект следующие:

# 修改配置并提交
$ git commit -a -m "update age to 18"
[release fc863bd] update age to 18
 1 file changed, 1 insertion(+), 1 deletion(-)

# 服务端配置生效
$ curl http://localhost:8888/pkslow-gateway-service/dev/release
{"name":"pkslow-gateway-service","profiles":["dev"],"label":"release","version":"fc863bd8849fa1dc5eaf2ce0a97afb485f81c2f0","state":null,"propertySources":[{"name":"/Users/larry/IdeaProjects/pkslow-modules/config-server/multiple-repos/pkslow-gateway-service/config/application.properties","source":{"pkslow.webSite":"gateway-release.pkslow.com","pkslow.age":"18","pkslow.email":"admin@pkslow.com"}}]}

# 客户端没有生效
$ curl http://localhost:8080/pkslow
{"webSite":"gateway-release.pkslow.com","age":"10","email":"admin@pkslow.com"}

# 发送POST请求到客户端/refresh
$ curl -X POST http://localhost:8080/actuator/refresh
["config.client.version","pkslow.age"]

# 客户端已经生效
$ curl http://localhost:8080/pkslow
{"webSite":"gateway-release.pkslow.com","age":"18","email":"admin@pkslow.com"}

3.4 Настройка автоматического обновления

Каждый раз, когда вы отправляете конфигурацию кода, вам нужно отправить ее вручную один разPOSTОчевидно, недостаточно дружелюбно просить клиента обновить конфигурацию.GitHubпри условииwebhookфункция, которая может отправить запрос на указанныйURL, так что автоматическое обновление может быть достигнуто.

пройти черезwebhookАвтоматическое обновление реализации функции один к одному, и если клиентов много (обычно такой сценарий), напрямую таким способом реализовать не получится. Есть два варианта:

(1) Реализуйте порт самостоятельно, чтобы принимать данные отGitЗатем запрос распространяется на каждый сервер. Этот метод более хлопотный и не рекомендуется.

(2) Путем введенияSpring Cloud Busдля обновления нескольких клиентов. но нужно представитьMQ,какkafkaилиRabbitMQ.

3.5 Отличия от обнаружения служб

В микросервисной архитектуре, если и сервер конфигурации, и клиент зарегистрированы в службе обнаружения (например,eureka), клиенту не нужно настраивать адрес сервера, и он получит идентификацию из центра обнаружения служб. Это то же самое, чтоSpringboot AdminТамeurekaВ ситуации есть сходство.

В коде нет ничего особенного, он предназначен для одновременной регистрации сервера и клиента.eurekaВот и все.

4 Резюме

В этой статье шаг за шагом показано, как использоватьSpring Cloud Config, в основном для понимания процесса взаимодействия и правил сопоставления, остальное — детали кода, просто обратитесь к официальной документации.

Несколько статей по настройке:

Как Java считывает свойства файла конфигурации (обычная файловая система-classpath-jar-URL) из этих четырех местоположений

Аннотация @ConfigurationProperties делает настройку аккуратной и простой.

Я просто хочу использовать статью для записи использования @Value, я не хочу искать другую

Springboot интегрирует Jasypt, самый элегантный и удобный способ настройки информационной безопасности.

Используйте Spring Cloud Config для единообразного управления конфигурацией, прекратите размещать файлы конфигурации повсюду

Spring Cloud Config интегрирует Spring Cloud Kubernetes для управления конфигурацией на k8s


Добро пожаловать в публичный аккаунт WeChatТыква медленный разговор>, буду обновлять для вас...

Читайте больше, делитесь больше, пишите больше, организуйте больше.