related

  1. Spring Cloud Series 1 – Service Registration and Discovery Eureka

  2. Spring Cloud – Client calls Rest + Ribbon

  3. Spring Cloud Combat Series iii – Declarative client Feign

  4. Spring Cloud Series iv – Fuse Hystrix

  5. Spring Cloud Combat Series 5 – Service Gateway Zuul

  6. Spring Cloud Deployment Series (6) – Distributed Configuration center Spring Cloud Config

  7. Spring Cloud Combat Series (7) – Service Link Tracking Spring Cloud Sleuth

  8. Spring Cloud Combat Series (8) – Micro service monitoring Spring Boot Admin

  9. Spring Cloud OAuth 2.0

  10. Single sign-on JWT and Spring Security OAuth

preface

In a distributed system, due to the large number of services, a distributed configuration center is required to facilitate unified management and real-time update of service configuration files. The distributed configuration center component provided by Spring Cloud is Spring Cloud Config, which supports placing configuration services in the memory of the configuration service (that is, locally) as well as in a remote Git repository. Spring Cloud Config provides two roles, one as Config Server and the other as Config Client.

The body of the

1. The Config Server reads the configuration file from the local PC

Create a new Spring Boot project module named config-server with the following pom.xml configuration:

<?xml version="1.0" encoding="UTF-8"? >
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3. RELEASE</version>
        <relativePath/> <! -- lookup parent from repository -->
    </parent>
    <groupId>io.github.ostenant.springcloud</groupId>
    <artifactId>config-server</artifactId>
    <version>0.0.1 - the SNAPSHOT</version>
    <name>config-server</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.RELEASE</spring-cloud.version>
    </properties>

    <dependencies>
        <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>
Copy the code

Start the configuration server using the @enableconFigServer annotation on the application startup class.

@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {

    public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); }}Copy the code

You need to do the following in the application configuration file application.properties. Run spring.profile.active=native to configure Config Server to read the configuration from the shared directory of Classpath.

server:
  port: 8769
spring:
  application:
    name: config-server
  profiles:
    active: native
  cloud:
    config:
      server:
        native:
          search-locations: classpath:/shared
Copy the code

Create a shared folder in SRC /main/resources and create a config-client-dev.yml file in shared folder.

server:
  port: 8762
foo: foo version 1
Copy the code

Run the Main () method of ConfigServerApplication to start the ConfigServer application on port 8769.

2. Build the Config Client

Create a Spring Boot project module named config-client with the following pom.xml configuration:

<?xml version="1.0" encoding="UTF-8"? >
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3. RELEASE</version>
        <relativePath/> <! -- lookup parent from repository -->
    </parent>
    <groupId>io.github.ostenant.springcloud</groupId>
    <artifactId>config-client</artifactId>
    <version>0.0.1 - the SNAPSHOT</version>
    <name>config-client</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.RELEASE</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-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>
Copy the code

Create a new bootstrap.yml file in the Resources directory because bootstrap has precedence over Application.

The variables {spring.application.name} and {spring.profiles.active}, which are connected by “-“, are the configuration names that the Config Client reads from the Config Server.

bootstrap.yml

spring:
  application:
    name: config-client
  cloud:
    config:
      uri: http://localhost:8769
      fail-fast: true # Failed to read the data
  profiles:
    active: dev
Copy the code

Configure an interface to test the foo variable that reads the configuration file and returns it to the client through the API interface.

@RestController
@SpringBootApplication
public class ConfigClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigClientApplication.class, args);
    }

    @Value("${foo}")
    private String foo;

    @RequestMapping(value = "/foo")
    public String foo(a){
        returnfoo; }}Copy the code

Start the config – client application, visit http://localhost:8762/foo, the server response data is as follows:

foo version 1

You can see that config-client successfully reads variable foo in config file config-client-dev.yml from the shared local file directory of the config-server project.

3. Config Server reads the configuration file from the remote Git repository

Modify the config-server configuration file application.yml as follows.

server:
  port: 8769
spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: https://coding.net/ostenant/config-repo
          search-paths: test
          username: [email protected]
          password: xxxx
      label: master
Copy the code

If the Git repository is an open repository, you can leave the username and password blank. This parameter is required for a private repository. In this example, a private repository is configured.

configuration explain
spring.cloud.config.server.git.uri Configure the Git repository address
spring.cloud.config.server.git.searchPaths Configuring the warehouse path
spring.cloud.config.label Configure branches of the repository
spring.cloud.config.server.git.username The username that accesses the Git repository
spring.cloud.config.server.git.password The user password to access the Git repository

Remote warehouse https://coding.net/ostenant/config-repo a called config – the client – dev. The properties of configuration files, configuration is an attribute:

foo = foo version 2
Copy the code

Restart the application config – and config – client server, visit http://localhost:8762/foo again, server response data is as follows:

foo version 2

Config-server reads the configuration file from the remote Git repository, and config-client reads the configuration properties from the config-server.

4. Build a highly available Config Server

Make the configuration center config-server a microservice and cluster it to achieve high availability.

4.1. Modify the Config Server

The Eureka client introduced in Config Server initially relies on spring-cloud-starter-Eureka.

<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
Copy the code

Register Config Server with Eureka Server by annotating @enableEurekaclient on the application startup class.

Add the service registry address to the configuration file application.yml:

eureka:
  client:
    service-url:
      defaultZone: http://locahost:8761/eureka/
Copy the code

4.2. Modify the Config Client

Similarly, the Eureka Client introduced in Config Client initially relies on spring-cloud-starter-Eureka.

<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
Copy the code

Register the Config Client with the Eureka Server by annotating @enableEurekaclient on the application startup class.

Add the service registry address to the configuration file application.yml:

eureka:
  client:
    service-url:
      defaultZone: http://locahost:8761/eureka/
Copy the code

Add related configuration to the configuration file application.yml and read related configuration file from the configuration service whose service-id is config-server.

spring:
  application:
    name: config-client
  cloud:
    config:
      fail-fast: true
      discovery:
        enabled: true
        service-id: config-server
  profiles:
    active: dev
server:
  port: 8762
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
Copy the code

Restart the application config – and config – client server, visit http://localhost:8762/foo again, server response data is as follows:

foo version 2

You only need to start multiple config-server instances to set up a highly available config-server cluster.

5. Refresh the configuration using Spring Cloud Bus

Spring Cloud Bus connects distributed nodes through a lightweight message broker. It can be used to broadcast changes to configuration files or communication between services, as well as for monitoring. When the distributed configuration file is changed, the local configuration can be refreshed instantly via Spring Cloud Bus notification in each microservice.

5.1. The config – client

Add the spring-cloud-starter-bus-amQP startup dependency to the config-client pop.xml.

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
Copy the code

Add RabbitMQ configuration including RabbitMQ address, port, username and password to the application. Yml file of the project. In order to facilitate verification, will management. Security. Change enabled to false.

spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
management.security.enabled=false
Copy the code

Finally, add the @refreshScope annotation to the configuration class where the properties need to be updated.

@RefreshScope
@RestController
@SpringBootApplication
public class ConfigClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigClientApplication.class, args);
    }

    @Value("${foo}")
    private String foo;

    @RequestMapping(value = "/foo")
    public String foo(a){
        returnfoo; }}Copy the code

Start two config-client instances with ports 8762 and 8763 respectively. Visit http://localhost:8762/foo or http://localhost:8763/foo, after the completion of start, the server response data is as follows:

foo version 2

Change the config-client-dev.properties of the remote Git repository configuration file to change the value of foo to “foo Version 3”.

Visit http://localhost:8762/bus/refresh request refresh configuration, set the “destination” parameter is to refresh the attributes of the service name. For example, “http://localhost:8762/bus/refresh? Destination =config-client:** “, that is, refresh all service instances whose service name is config-client.

Visit http://localhost:8762/foo and http://localhost:8763/foo, again the server response data is as follows:

foo version 3

The test results show that all instances of the /bus/refresh notification service named config-client have refreshed the local configuration of the foo property.

reference

  • An In-depth Understanding of Spring Cloud and Microservice Construction by Zhipeng Fang

Welcome to pay attention to the technical public number: Zero one Technology Stack

This account will continue to share learning materials and articles on back-end technologies, including virtual machine basics, multithreaded programming, high-performance frameworks, asynchronous, caching and messaging middleware, distributed and microservices, architecture learning and progression.