Статьи

Обучающие материалы по Spring Cloud — Введение в Spring Cloud Config Server

проблема

SpringBoot обеспечивает большую гибкость при выводе свойств конфигурации через свойства или файлы YAML. Мы также можем настроить свойства для каждой среды (dev, qa, prod и т. Д.) Отдельно, используя специфические для профиля файлы конфигурации, такие как application.properties , application-dev.properties , application-prod.properties и т. Д. Но после запуска приложения мы не можем обновить свойства во время выполнения. Если мы изменим свойства, нам нужно перезапустить приложение, чтобы использовать обновленные свойства конфигурации.

Кроме того, в контексте большого числа приложений на основе MicroService мы хотим иметь возможность конфигурировать и управлять свойствами конфигурации всех MicroServices из централизованного места.

Решение

Мы можем использовать Spring Cloud Config Server ( http://cloud.spring.io/spring-cloud-static/Dalston.SR2/#_spring_cloud_config ), чтобы централизовать все настройки приложений и использовать клиентский модуль Spring Cloud Config из приложений для использования конфигурации. свойства от сервера конфигурации. Мы также можем обновить свойства конфигурации во время выполнения, не требуя перезапуска приложения.

Многие из модулей Spring Cloud можно использовать в приложениях SpringBoot, даже если вы не собираетесь развертывать свое приложение на каких-либо облачных платформах, таких как AWS, Pivotal CloudFoundry и т. Д.

Сервер Spring Cloud Config

Spring Cloud Config Server — это не что иное, как приложение SpringBoot с настроенным источником свойств конфигурации. Источником конфигурации может быть git- репозиторий, svn- репозиторий или служба Consul ( https://www.consul.io/ ).

В этом посте мы собираемся использовать репозиторий git в качестве источника свойств конфигурации.

Git Config Repository

Создайте git-репозиторий для хранения файлов свойств. Я создал репозиторий config-repo в GitHub, т.е. https://github.com/sivaprasadreddy/config-repo.git .

Предположим, мы собираемся разработать два каталога-сервиса SpringBoot -сервис и сервис заказа . Давайте создадим файлы конфигурации catalogservice.properties и orderservice.properties для службы каталогов и службы заказов соответственно.

конфигурации-Репо / catalogservice.properties

1
2
3
4
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/catalog
spring.datasource.username=root
spring.datasource.password=admin

конфигурации-Репо / orderservice.properties

1
2
3
4
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

Мы также можем создавать специфичные для профиля файлы конфигурации, такие как catalogservice-dev.properties , catalogservice-prod.properties , orderservice-dev.properties , orderservice-prod.properties .

конфигурации-репо / catalogservice-prod.properties

1
2
3
4
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://appsrv1:3306/catalog
spring.datasource.username=appuser46
spring.datasource.password=T(iV&#)X84@1!

конфигурации-репо / orderservice-prod.properties

1
2
3
4
spring.rabbitmq.host=srv245.ind.com
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin23
spring.rabbitmq.password=uY7&%we@1!

Теперь зафиксируйте все файлы свойств конфигурации в git-репозитории config-repo .

Серверное приложение Spring Cloud Config

Давайте создадим приложение SpringBoot spring-cloud-config-server из http://start.spring.io или из вашей любимой среды IDE, выбрав стартовые Config Server и Actuator .

Это сгенерирует проект maven со следующим 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
53
54
55
56
57
58
59
60
61
62
63
64
<?xml version="1.0" encoding="UTF-8"?>
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    <modelVersion>4.0.0</modelVersion>
  
    <groupId>com.sivalabs</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>spring-cloud-config-server</name>
  
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.RELEASE</version>
        <relativePath/>
    </parent>
  
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR2</spring-cloud.version>
    </properties>
  
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
  
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</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>

Чтобы сделать наше приложение SpringBoot в качестве сервера SpringCloud Config, нам просто нужно добавить аннотацию @EnableConfigServer в основной класс точки входа и настроить свойство spring.cloud.config.server.git.uri, указывающее на репозиторий git.

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

весна-облако-конфиг-сервер / SRC / основной / ресурсы / application.properties

1
2
3
server.port=8888
spring.cloud.config.server.git.uri=https://github.com/sivaprasadreddy/config-repo.git
management.security.enabled=false

В дополнение к настройке git repo uri мы настроили server.port для 8888 и отключили защиту привода . Теперь вы можете запустить приложение, которое запустится на порту 8888.

Сервер Spring Cloud Config предоставляет следующие конечные точки REST для получения свойств конфигурации конкретного приложения:

1
2
3
4
5
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties

Здесь {application} относится к значению свойства spring.config.name , {profile} — активный профиль, а {label} — необязательная метка git (по умолчанию «master»).

Теперь, если вы получите доступ к URL-адресу http: // localhost: 8888 / catalogservice / default, вы получите следующий ответ с подробностями конфигурации по умолчанию службы каталогов:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
{
    "name": "catalogservice",
    "profiles": [
        "default"
    ],
    "label": null,
    "version": "8a06f25aeb3f28a8f06b5634eae01858b2c6465d",
    "state": null,
    "propertySources": [
        {
            "source": {
                "spring.datasource.username": "root",
                "spring.datasource.driver-class-name": "com.mysql.jdbc.Driver",
                "spring.datasource.password": "admin",
                "spring.datasource.url": "jdbc:mysql://localhost:3306/catalog"
            }
        }
    ]
}

Если вы перейдете по URL-адресу http: // localhost: 8888 / catalogservice / prod, то получите следующий ответ с подробностями конфигурации каталога catalogservice .

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
{
    "name": "catalogservice",
    "profiles": [
        "prod"
    ],
    "label": null,
    "version": "8a06f25aeb3f28a8f06b5634eae01858b2c6465d",
    "state": null,
    "propertySources": [
        {
            "source": {
                "spring.datasource.username": "appuser46",
                "spring.datasource.driver-class-name": "com.mysql.jdbc.Driver",
                "spring.datasource.password": "T(iV&#)X84@1!",
                "spring.datasource.url": "jdbc:mysql://appsrv1:3306/catalog"
            }
        },
        {
            "source": {
                "spring.datasource.username": "root",
                "spring.datasource.driver-class-name": "com.mysql.jdbc.Driver",
                "spring.datasource.password": "admin",
                "spring.datasource.url": "jdbc:mysql://localhost:3306/catalog"
            }
        }
    ]
}

В дополнение к конкретным файлам конфигурации приложения, таким как catalogservice.properties , orderservice.properties , вы можете создать файл application.properties, содержащий общие свойства конфигурации для всех приложений. Как вы уже догадались, у вас могут быть профильные файлы, такие как application-dev.properties, application-prod.properties .

Предположим, у вас есть файл application.properties в config-repo со следующими свойствами:

1
2
message=helloworld
jdbc.datasource.url=jdbc:mysql://localhost:3306/defapp

Теперь, если вы получите доступ к http: // localhost: 8888 / catalogservice / prod, вы получите следующий ответ:

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
{
    "name": "catalogservice",
    "profiles": [
        "prod"
    ],
    "label": null,
    "version": "8a06f25aeb3f28a8f06b5634eae01858b2c6465d",
    "state": null,
    "propertySources": [
        {
            "source": {
              "spring.datasource.username": "appuser46",
              "spring.datasource.driver-class-name": "com.mysql.jdbc.Driver",
              "spring.datasource.password": "T(iV&#)X84@1!",
              "spring.datasource.url": "jdbc:mysql://appsrv1:3306/catalog"
            }
        },
        {
            "source": {
                "spring.datasource.username": "root",
                "spring.datasource.driver-class-name": "com.mysql.jdbc.Driver",
                "spring.datasource.password": "admin",
                "spring.datasource.url": "jdbc:mysql://localhost:3306/catalog"
            }
        },
        {
            "source": {
                "message": "helloworld",
                "jdbc.datasource.url": "jdbc:mysql://localhost:3306/defapp"
            }
        }
    ]
}

Аналогичным образом вы можете получить доступ к http: // localhost: 8888 / orderservice / default, чтобы получить подробную информацию о конфигурации службы заказа.

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
{
    "name": "orderservice",
    "profiles": [
        "default"
    ],
    "label": null,
    "version": "8a06f25aeb3f28a8f06b5634eae01858b2c6465d",
    "state": null,
    "propertySources": [
        {
            "source": {
              "spring.rabbitmq.host": "localhost"
              "spring.rabbitmq.port": "5672"
              "spring.rabbitmq.username": "guest"
              "spring.rabbitmq.password": "guest"
            }
        },
        {
            "source": {
                "message": "helloworld",
                "jdbc.datasource.url": "jdbc:mysql://localhost:3306/defapp"
            }
        }
    ]
}

Теперь, когда мы увидели, как создать сервер конфигурации с помощью Spring Cloud Config Server и как получить свойства конфигурации приложения, используя REST API.

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

Клиент Spring Cloud Config (каталог-сервис)

Создайте службу каталога приложений SpringBoot с помощью клиентов Config, Web и Actuator .

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?xml version="1.0" encoding="UTF-8"?>
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    <modelVersion>4.0.0</modelVersion>
  
    <groupId>com.sivalabs</groupId>
    <artifactId>catalog-service</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>
  
    <name>spring-cloud-config-client</name>
  
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.RELEASE</version>
        <relativePath/>
    </parent>
  
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR2</spring-cloud.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>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
  
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</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>

Обычно в приложении SpringBoot мы настраиваем свойства в application.properties . Но при использовании Spring Cloud Config Server мы используем файл bootstrap.properties или bootstrap.yml для настройки URL-адреса сервера Config, и модуль Spring Cloud Config Client позаботится о запуске приложения, извлекая свойства приложения из Config Server.

Настройте следующие свойства в src / main / resources / bootstrap.properties :

1
2
3
4
server.port=8181
spring.application.name=catalogservice
spring.cloud.config.uri=http://localhost:8888
management.security.enabled=false

Мы настроили URL сервера конфигурации, используя свойство spring.cloud.config.uri . Также мы указали имя приложения, используя свойство spring.application.name .

Обратите внимание, что значение свойства spring.application.name должно совпадать с базовым именем файла ( catalogservice ) в config-repo.

Теперь запустите следующий класс основной точки входа службы каталогов:

01
02
03
04
05
06
07
08
09
10
11
12
package com.sivalabs.catalogservice;
  
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
  
@SpringBootApplication
public class CatalogServiceApplication {
  
    public static void main(String[] args) {
        SpringApplication.run(CatalogServiceApplication.class, args);
    }
}

Мы можем получить доступ к конечной точке привода http: // localhost: 8181 / env, чтобы увидеть все свойства конфигурации.

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
{
    "profiles": [],
    "server.ports": {
        "local.server.port": 8080
    },
    "configService:configClient": {
        "config.client.version": "8a06f25aeb3f28a8f06b5634eae01858b2c6465d"
    },
        "spring.datasource.username": "root",
        "spring.datasource.driver-class-name": "com.mysql.jdbc.Driver",
        "spring.datasource.password": "******",
        "spring.datasource.url": "jdbc:mysql://localhost:3306/catalog"
    },
        "message": "helloworld",
        "jdbc.datasource.url": "jdbc:mysql://localhost:3306/defapp"
    },
    "servletContextInitParams": {},
    "systemProperties": {
        ...
        ...
    },
    "systemEnvironment": {
        ...
        ...
    },
    "springCloudClientHostInfo": {
        "spring.cloud.client.hostname": "192.168.0.101",
        "spring.cloud.client.ipAddress": "192.168.0.101"
    },
    "applicationConfig: [classpath:/bootstrap.properties]": {
        "management.security.enabled": "false",
        "spring.cloud.config.uri": "http://localhost:8888",
        "spring.application.name": "catalogservice"
    },
    "defaultProperties": {}
}

Вы можете видеть, что приложение службы каталогов извлекает свойства службы каталогов с сервера Config во время начальной загрузки. Вы можете связать эти свойства с помощью @Value или @EnableConfigurationProperties точно так же, как вы связываете, если они определены в самом приложении.

Приоритет свойств

Теперь, когда мы знаем, что есть много способов предоставить свойства конфигурации во многих файлах, таких как application.properties, bootstrap.properties и их варианты профиля внутри приложения src / main / resources и {application-name} — {profile} .properties, application- {профиль}. свойства в config-repo.

На следующих диаграммах показано преимущество свойств конфигурации в разных местах свойств.

Обновить свойства во время выполнения

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

Обновите catalogservice.properties в git-репозитории config-repo и передайте изменения. Теперь, если вы получите доступ к http: // localhost: 8181 / env, вы все равно увидите старые свойства.

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

  • Пометьте Spring bean-компоненты, которые вы хотите перезагрузить при изменении конфигурации, с помощью @RefreshScope
  • Выдать http: // localhost: 8181 / обновить запрос методом POST

Чтобы проверить поведение при перезагрузке, добавим свойство name = Siva в config-repo / catalogservice.properties и зафиксируем его.

Создайте простой RestController для отображения значения имени следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
@RestController
@RefreshScope
class HomeController
{
    @Value("${name}")
    String name;
  
    @GetMapping("/name")
    public String name()
    {
        return name;
    }
}

Теперь зайдите на http: // localhost: 8181 / name, которое будет отображать Siva . Теперь измените значение свойства на name = Prasad в config-repo / catalogservice.properties и зафиксируйте его.

Чтобы перезагрузить изменения конфигурации, запустите http: // localhost: 8181 / запрос на обновление с использованием метода POST и снова получите доступ к http: // localhost: 8181 / name, которое должно отображать Prasad

Но выдавать / обновлять запросы вручную утомительно и нецелесообразно в случае большого количества приложений и нескольких экземпляров одного и того же приложения. Мы расскажем, как решить эту проблему с помощью Spring Cloud Bus в следующем посте
Учебные пособия по Spring Cloud — автоматическое обновление изменений конфигурации с использованием Spring Cloud Bus ( http://sivalabs.in/2017/08/spring-cloud-tutorials-auto-refresh-config-changes-using-spring-cloud-bus/ ).

Исходный код этой статьи находится по адресу https://github.com/sivaprasadreddy/spring-cloud-tutorial.