Статьи

Используйте Spring Cloud Config в качестве внешней конфигурации

Одним из наиболее важных методов непрерывной доставки является сборка ваших двоичных файлов только один раз и их использование в различных средах (разработка, тестирование, приемка и т. Д.). Это означает, что, скорее всего, вам потребуется выполнить внешнюю настройку приложения . С приложениями Spring Boot все сводится к тому, чтобы сохранить значения ваших свойств в ваших application.properties за пределами вашего jar приложения . Делая это, вы можете использовать один и тот же файл jar для развертываний в разных средах (альтернативой является упаковка значений свойств для всех возможных сред с вашим файлом jar, но я не считаю это хорошей практикой в ​​большинстве ситуаций).
Особенно, когда вы создаете и развертываете приложения Spring Boot, вам следует взглянуть на проект Spring Cloud Config . В этом посте я пройдусь по шагам, описанным здесь, и вы увидите, как настроить собственную службу конфигурации всего за несколько шагов.
Прежде чем я покажу, как его настроить, сначала рассмотрим архитектуру:

  • Git-репозиторий используется для хранения значений конфигурации. Git — отличный выбор для этого, так как он позволяет отслеживать и хранить изменения.
  • DevOps (или любая система, которая хочет внести изменения в конфигурацию) может просто изменить значения конфигурации, отправив свои изменения в репозиторий Git.
  • Служба конфигурации поддерживает Git-репозиторий и публикует значения конфигурации по запросу.
  • Службы действуют как клиенты конфигурации и могут запрашивать значения конфигурации у службы конфигурации.

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

Самый простой способ — создать каталог ‘spring-config-example’, который будет содержать весь код, необходимый для этой демонстрации. Это будет считаться корневым каталогом для этого поста.

Настройте репозиторий Git
На этом шаге я создаю файл свойств, который помещаю в (локальное) хранилище Git. Затем файл свойств будет использоваться в качестве источника значений свойств для нашего демонстрационного клиентского приложения.
Сначала создайте новый каталог «configstore» и в этом каталоге создайте новый файл с именем «a-bootiful-client.properties». Добавьте следующее содержимое в файл:

1
2
3
4
server.port=8000
message = Hello World
 
management.security.enabled=false

Затем создайте git-репо с помощью команды
git init ‘, добавьте и передайте файл в локальный репозиторий
git commit -a -m 'initial commit'
Вот именно для этого шага.

Настройте службу конфигурации
Как было сказано ранее, сервис — это просто еще один проект Spring Boot. Для настройки проекта я создал новый подкаталог и поместил в него проект Spring Boot «по умолчанию» со следующим макетом:

01
02
03
04
05
06
07
08
09
10
├── pom.xml
└── src
    └── main
        ├── java
        │   └── net
        │       └── pascalalma
        │           └── cloud
        │               └── ConfigServiceApplication.java
        └── resources
            └── application.properties

Файл «pom.xml» имеет следующее содержимое:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?xml version="1.0" encoding="UTF-8"?>
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>net.pascalalma.cloud</groupId>
  <artifactId>configuration-service</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>jar</packaging>
 
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.2.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-config-server</artifactId>
    </dependency>
  </dependencies>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Camden.SR5</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

Это довольно простой pom для Spring Boot Project. Единственная добавленная зависимость — это зависимость для ‘spring-cloud-config-server’.
Класс Application выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
package net.pascalalma.cloud;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
 
@EnableConfigServer
@SpringBootApplication
public class ConfigServiceApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(ConfigServiceApplication.class, args);
    }
}

Единственное, что здесь отличается, — это аннотация «EnableConfigServer», которая делает это приложение Spring Boot действующим в качестве сервера конфигурации.
Наконец, есть application.properties, содержащий следующее:

1
2
server.port=8888
spring.cloud.config.server.git.uri=/Users/pascalalma/projects/sandbox/spring-config-example/configstore

Помимо определения порта, я добавил URI в репозиторий Git, который содержит свойства для использования. Как уже было сказано, я использую локальное репо здесь, но это, конечно же, может быть и удаленный репозиторий Git.
Это все, что есть для сервера. Позволяет настроить клиентское приложение дальше.

Настройте обслуживание клиентов
Чтобы настроить клиентский проект, я создал новый подкаталог и поместил в него другой проект Spring Boot «по умолчанию» со следующей компоновкой:

1
2
3
4
5
6
7
8
├── pom.xml
└── src
    └── main
        ├── java
        │   └── hello
        │       └── ConfigClientApplication.java
        └── resources
            └── bootstrap.properties

Как видите, этот проект так же прост, как и другой. Он содержит pom, один файл Java и файл свойств. Давайте пройдемся по каждому из них.
«Pom.xml» содержит следующее:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?xml version="1.0" encoding="UTF-8"?>
  <modelVersion>4.0.0</modelVersion>
  <groupId>net.pascalalma.cloud</groupId>
  <artifactId>configuration-client</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>jar</packaging>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.2.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
  </dependencies>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Camden.SR5</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

Далее идет файл Java. На самом деле он содержит два класса: приложение для запуска Spring Boot и контроллер, обрабатывающий входящие HTTP-запросы. Файл выглядит так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package net.pascalalma.cloud.client;
 
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@SpringBootApplication
public class ConfigClientApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(ConfigClientApplication.class, args);
    }
}
 
@RefreshScope
@RestController
class MessageRestController {
 
    @Value("${message:Hello default}")
    private String message;
 
    @RequestMapping("/message")
    String getMessage() {
        return this.message;
    }
}

RefreshScope добавлен, чтобы иметь возможность перезагрузить свойства, когда я изменю их позже в нашем тесте.
Последний файл — это «bootstrap.properties». Этот файл используется приложением Spring Boot CLient при запуске приложения для загрузки удаленного файла «application.properties» до его запуска. Файл содержит следующее:

1
2
spring.application.name=a-bootiful-client
spring.cloud.config.uri=http://localhost:8888

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

Протестируйте настройку
Теперь, когда весь код установлен, я могу проверить, работает ли он. Я открываю три терминальных сессии.
Первым я перехожу в каталог ‘configuration-server’ и выполняю ‘ mvn spring-boot:run ‘, чтобы запустить сервер конфигурации.
Во втором я перехожу в каталог ‘ mvn spring-boot:run -client’ и выполняю ‘ mvn spring-boot:run ‘, чтобы запустить клиент конфигурации.
Третий, который я использую, чтобы позвонить клиенту, чтобы проверить сервер конфигурации. Когда я выполняю команду « curl localhost:8000/message », я ожидаю получить возвращенное сообщение, которое я положил в configstore на первом шаге:

1
2
$ curl localhost:8000/message
Hello World!

Теперь, когда я внесу изменение в хранилище конфигурации, оно не будет автоматически отражено в клиенте. Я редактирую файл «a-bootiful-client.properties» и обновляю сообщение так:
message = Hello World from Spring Boot!\n\n . И, конечно, зафиксируйте файл в хранилище с помощью ‘ git commit -a -m 'updated message'
Когда я выполняю ту же команду curl в клиентском приложении, никаких изменений не произойдет. Если я закручиваю сообщение прямо на сервере конфигурации, я вижу изменение:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
$ curl localhost:8888/a-bootiful-client/default
{"name":"a-bootiful-client"
,"profiles":"default"]
,"label":"master"
,"version":"98c6f8d8dd9a9b2cb36496ca4ac54ffb35806dbc"
,"state":null
,"propertySources":[
  {"name":"/Users/pascalalma/projects/sandbox/spring-config-example/configstore/a-bootiful-client.properties"
  ,"source":{"server.port":"8000"
    ,"management.security.enabled":"false"
    ,"message":"Hello World from Spring Boot!\n\n"}
  }
  ]
}

Чтобы получить это измененное значение с сервера конфигурации на клиент, мне нужно обновить клиент с помощью следующей команды:
'curl -X POST http://localhost:8000/refresh ' . Если я сейчас сверну клиента, то увижу ожидаемое обновленное сообщение:

1
2
$ curl localhost:8000/message
Hello World from Spring Boot!

Возможно, вы заметили, что свойство ‘management.security.enabled’ установлено в false в ‘application.properties’ для этой демонстрации. Это было сделано для того, чтобы это было легко протестировать (по умолчанию начиная с Spring Boot 1.5 конечные точки привода по умолчанию защищены)

Функциональность, показанная в этом посте, на самом деле является лишь вершиной айсберга Возможно гораздо больше, в сочетании с другими инструментами, такими как Spring Cloud Consul и Spring Cloud Bus , но также и со стандартными функциями Spring, такими как безопасность и профили . Этого поста должно быть достаточно, чтобы вы сами начали его проверять.