Microservice topic 07-Spring Cloud configuration management

Preface

In the previous chapter, we talked about the topic of microservices 06-Cloud Native Applications . In this section, continue to share the content of the microservice topic, a total of 16 sections, namely:

The key points of this section are:

  • Environment Endpoint: Introduce /envthe usage scenarios of the endpoint, and interpret its source code to understand the mystery
  • Basic usage: introduction @EnableConfigServer, Environmentstorage
  • Official Implementation of Distributed Configuration: Introduction to the implementation of Spring's official standard distributed configuration: JDBC implementation
  • Dynamic configuration attribute Bean: introduce the @RefreshScopebasic usage and usage scenarios, and explain its limitations
  • Health indicators: introduce Spring Boot standard ports ( /health) and health indicators (Health Indicator)
  • Customized implementation of health indicators: Implementation of customized implementation of health indicators for distributed configuration

Open source project

Students who have done SpringCloud configuration management will definitely come into contact with some enterprise-level configuration management frameworks. Here is a reference.

Well-known domestic open source projects

Baidu Disconf

Ctrip Apollo

Ali Nacos

Well-known open source projects abroad

Spring Cloud Config

Netfix Archaius

Apache Zookeeper

Client

The past and present of Spring Cloud Config

Traditional configuration management is based on Spring Stack, so Client and Server are related through Spring:
Insert picture description here
Q: How is the distributed configuration of Spring Cloud designed?

A: The configuration read of Spring Cloud loads the configuration server when the client starts. However, it is usually distributed in different regions, and the client configuration on different machines is different. For example, the QPS of the Chinese Client is 1000, and the QPS of the American Client is 500, you can use the service fuse mechanism ${app.qps} Go design. And the latest version of SpringCloud server supports loading Github/SVN, database and configuration files.
Insert picture description here

Java Client reads HttpClient by itself

In traditional project configuration management, Java Client reads HttpClient by itself. The usual process is as follows:

  1. First get the configuration file text information
  2. Convert text information into Properties object
  3. Read the corresponding value according to the key of the configuration file (yml/properties)
  4. The business logic code loads the value value (through Spring injection configuration)
  5. The new configuration is effective for the APP

Q: What are the disadvantages of the traditional configuration client pulling the configuration on the configuration server through Http?

A: In the process of pulling through http, the Http1.1 version of the protocol is stateless, that is, short connection. This means that the client must adopt a polling strategy every time it is updated, and the long-term operation is obviously not the result we want to see.

Configure third party library

Faced with the shortcomings of JavaClient using Http short connections, we can usually use third-party libraries to manage configuration files.

Open source project Configuration source order (configuration priority override) Configuration source (storage medium) Conversion type (programming convenience)
Apache Commons Configuration Configuration Rich, basically support all types
Spring FrameWork addFirst() priority coverage PropertySource

Apache Commons Configuration

The pom coordinates are as follows:

<dependency>
	<groupId>commons-configuration</groupId>
	<artifactId>commons-configuration</artifactId>
	<version>1.9</version>
</dependency>

Expand the source, found commons-configuration package inside the core classes Configurationprovide the most common type of Value conversion.
Insert picture description here

The reason is that the keys and values ​​of Properties integrated with Hashtable are both Object types:
Insert picture description here
Next, let’s look at the implementation classes of Configuration:
Insert picture description here
There are many implementation classes. Here are a few common subclass implementations to illustrate:

  • PropertiesConfiguration: The Properties as a Configurationconfiguration

  • MapConfiguration: Store configuration information in the form of Map

    • EnvironmentConfiguration : OS environment variables
    • SystemConfiguration : Java system properties
  • CompositeConfiguration: Combine the configuration, the storage method is List <Configuration>

Regardless of Spring's native configuration reading or third-party library configuration reading, the core concept is: configuration sources , their priorities , and configuration conversion capabilities !

Q: Seeing this, we can't help thinking, is HTTP resource a configuration?

A: Generally, the configuration source we refer to refers to files, HTTP resources, data sources, Git, etc., but they all have the same goal. They all exist in the form of URLs, so HTTP resources count as a configuration.

  • URL path corresponding to the file file:///
  • URL path corresponding to http resource http://
  • The URL path corresponding to the data source jdbc://
  • URL path corresponding to git git://

Spring FrameWork

The commons-configuration method mentioned earlier is implemented through Apache Commons Configuration, then in Spring FrameWork, Environment is used as a medium for configuration management.

Insert picture description here

In its sub-implementation class ConfigurableEnvironment there is such a method:

MutablePropertySources getPropertySources();

And MutablePropertySources is used to store a collection of configuration sources:
Insert picture description here

About PropertySourceconfiguration source, the Apache PropertiesConfiguration contrast, there are also many classes implemented in PropertySource:

  • MapPropertySource
    • PropertiesPropertySource
  • CompositePropertySource: Combine the configuration, the storage method is LinkedHashSet<PropertySource>, the characteristic is orderly and can be deduplicated.
    Insert picture description here

Tips: What is the difference between LinkedHashSet and LinkedHashMap?

  • SystemEnvironmentPropertySource Environment variable configuration

Spring Cloud client configuration location extension: PropertySourceLocator

Spring Cloud client configuration management

Now we organize the configuration process of the client and server:

Insert picture description here

  1. First of all, it must be clear that the external configuration of the project has many forms, such as command line parameters, Java System properties, application properties configuration files, etc.
  2. But now if you want to use a server as configuration management, you should put the loading order of the configuration center first. We know that in the process of getProperties, it will take the form of addFirst.
  3. Through the introduction of the context-level loading order problem in the previous section, isn't it just the solution to this problem? The Bootstrap context is the parent of all contexts, so we can place the configuration center in the Bootstrap ApplicationContext (Bootstrap parent context). Set other forms of configuration to Service ApplicationContext (service-level context).
  4. In this way, the content from the configuration center in the parent context of Bootstrap will be loaded first when it is loaded when the client starts.

Server

Based on Git

The effect achieved is to load the configuration in the Git warehouse by configuring the server of Spring Cloud Config:

Here I put the git repository in the /resources/configs directory, and distinguished by different profiles.

Insert picture description here

  1. Configure server dependencies, space is limited, please move to the Github code address at the end of the article for complete dependencies.
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
   
    <properties>
        <spring-cloud.version>Hoxton.SR6</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
        </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>
  1. By @EnableConfigServerthe statement of the current service is the service end of Spring Cloud Config.
@SpringBootApplication
@EnableConfigServer
public class DemoApplication {
    
    

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

}
  1. Configuration file related

Versioned configuration

## 配置服务器应用名字
spring.application.name = config-server

## 设置服务端口号
server.port = 10086

## 配置服务器git本地文件系统路径
spring.cloud.config.server.git.uri = \
${user.dir}/src/main/resources/configs/

Version file

config.properties file:

name = jack

config-test.properties file:

name = tom
  1. Service access

When we visit: http://localhost:10086/config/default actually read the config.properties configuration file in the configs directory.

Insert picture description here

When we visit: http://localhost:10086/config/test actually read the config-test.properties configuration file in the configs directory.

Insert picture description here
Note the version number of git:

Insert picture description here

Spring Cloud Config implements a complete configuration management API design. In the use of configuration, a three-stage style is often used to set the path, that is, /application name/profile/${label}, where ${label} represents the branch. If no branch is declared, the master branch is loaded by default. If the profile environment is not declared, it is equivalent to /application name.properties.

We also need to know that the DEMO demonstrated above has many problems:

  • Complex version update mechanism (Git repository)
    • version
    • Branch
    • submit
    • Configuration
  • Content updates with stubborn feet (not real-time)
    • The client starts the pull for the first time
    • Need to integrate BUS for update notification

Design principle

Earlier demo demonstrated in Config Server involved in @EnableConfigServerthis annotation, and now we analyze:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ConfigServerConfiguration.class)
public @interface EnableConfigServer {
    
    

}

Note that @Import is used to indicate that the actual configuration class is ConfigServerConfiguration:

@Configuration
public class ConfigServerConfiguration {
    
    
	class Marker {
    
    }

	@Bean
	public Marker enableConfigServerMarker() {
    
    
		return new Marker();
	}
}

We found that the ConfigServerConfiguration class is actually used in ConfigServerAutoConfiguration:

@Configuration
@ConditionalOnBean(ConfigServerConfiguration.Marker.class)
@EnableConfigurationProperties(ConfigServerProperties.class)
@Import({
    
     EnvironmentRepositoryConfiguration.class, CompositeConfiguration.class, ResourceRepositoryConfiguration.class,
		ConfigServerEncryptionConfiguration.class, ConfigServerMvcConfiguration.class })
public class ConfigServerAutoConfiguration {
    
    

}

From here we find: When the application configuration class marked @EnableConfigSever, import ConfigServerConfigurationand register MarkerBean, and MarkerBean also as ConfigServerAutoConfigurationone of the conditions.

Case study JDBC implementation

  • JdbcTemplate Bean source

    • JdbcTemplateAutoConfiguration
  • SQL source

    • JdbcEnvironmentProperties,The content is:, spring.cloud.config.server.jdbc.sqlif not configured, it will be used DEFAULT_SQLby default , namely:
            SELECT KEY, VALUE from PROPERTIES where APPLICATION=? and PROFILE=? and LABEL=?
    

Looking back at the above demo and combining the source code, we will also draw the following conclusions:

KEY VALUE APPLICATION PROFILE LABEL
name zhangsan config default master
name lysis config test master

Essential description:

  • JDBC: connection technology

  • DB: storage medium

  • Core interface: EnvironmentRepository

Q: Can I customize EnvironmentRepositoryachieved?

A: premise: how to activate a custom EnvironmentRepositoryimplementation, first of all find a reason why the default configuration Git repository:

@Configuration
@ConditionalOnMissingBean(value = EnvironmentRepository.class, search = SearchStrategy.CURRENT)
class DefaultRepositoryConfiguration {
    
    
	...
	@Bean
	public MultipleJGitEnvironmentRepository defaultEnvironmentRepository(
	        MultipleJGitEnvironmentRepositoryFactory gitEnvironmentRepositoryFactory,
			MultipleJGitEnvironmentProperties environmentProperties) throws Exception {
    
    
		return gitEnvironmentRepositoryFactory.build(environmentProperties);
	}
}

When no EnvironmentRepositoryBean appears in the Spring application context , then it is activated DefaultRepositoryConfigurationby default (Git implementation), otherwise a custom implementation is adopted.

Custom implementation

Custom EnvironmentRepositoryBean

    @Bean
    public EnvironmentRepository environmentRepository() {
    
    
        return (String application, String profile, String label) -> {
    
    
            Environment environment = new Environment("default", profile);
            List<PropertySource> propertySources = environment.getPropertySources();
            Map<String, Object> source = new HashMap<>();
            source.put("name", "test");
            PropertySource propertySource = new PropertySource("map", source);
            // 追加 PropertySource
            propertySources.add(propertySource);
            return environment;
        };
    }

The failure to achieve the above DefaultRepositoryConfigurationassembly.

Compare the implementation of Spring Cloud's built-in configuration storage

  • The Git Way: Give Up Early

  • JDBC way: too simple

  • Zookeeper method: more suitable for distributed configuration

  • Custom method: high-end players

postscript

The code address of this section: https://github.com/harrypottry/spring-cloud-config-server

For more architectural knowledge, please pay attention to this series of articles on Java : The Road to Growth of Java Architects

Guess you like

Origin blog.csdn.net/qq_34361283/article/details/106688971