Directory navigation
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:
- Microservice topic 01-Spring Application
- Microservice topic 02-Spring Web MVC view technology
- Microservice topic 03-REST
- Microservice topic 04-Spring WebFlux principle
- Microservice topic 05-Spring WebFlux application
- Microservices topic 06-Cloud Native Applications
- Microservice topic 07-Spring Cloud configuration management
- Microservice topic 08-Spring Cloud service discovery
- Microservice topic 09-Spring Cloud load balancing
- Microservice topic 10-Spring Cloud service circuit breaker
- Microservice topic 11-Spring Cloud service call
- Microservice topic 12-Spring Cloud Gateway
- Microservice topic 13-Spring Cloud Stream (on)
- Microservice topic 14-Spring Cloud Bus
- Microservice topic 15-Spring Cloud Stream implementation
- Microservice topic 16-Spring Cloud overall review
The key points of this section are:
- Environment Endpoint: Introduce
/env
the usage scenarios of the endpoint, and interpret its source code to understand the mystery - Basic usage: introduction
@EnableConfigServer
,Environment
storage - Official Implementation of Distributed Configuration: Introduction to the implementation of Spring's official standard distributed configuration: JDBC implementation
- Dynamic configuration attribute Bean: introduce the
@RefreshScope
basic 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
Well-known open source projects abroad
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:
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.
Java Client reads HttpClient by itself
In traditional project configuration management, Java Client reads HttpClient by itself. The usual process is as follows:
- First get the configuration file text information
- Convert text information into Properties object
- Read the corresponding value according to the key of the configuration file (yml/properties)
- The business logic code loads the value value (through Spring injection configuration)
- 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 Configuration
provide the most common type of Value conversion.
The reason is that the keys and values of Properties integrated with Hashtable are both Object types:
Next, let’s look at the implementation classes of Configuration:
There are many implementation classes. Here are a few common subclass implementations to illustrate:
-
PropertiesConfiguration
: The Properties as aConfiguration
configuration -
MapConfiguration
: Store configuration information in the form of MapEnvironmentConfiguration
: OS environment variablesSystemConfiguration
: 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.
In its sub-implementation class ConfigurableEnvironment there is such a method:
MutablePropertySources getPropertySources();
And MutablePropertySources is used to store a collection of configuration sources:
About PropertySource
configuration source, the Apache PropertiesConfiguration contrast, there are also many classes implemented in PropertySource:
MapPropertySource
PropertiesPropertySource
CompositePropertySource
: Combine the configuration, the storage method isLinkedHashSet<PropertySource>
, the characteristic is orderly and can be deduplicated.
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:
- 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.
- 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.
- 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).
- 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.
- 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>
- By
@EnableConfigServer
the 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);
}
}
- 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
- Service access
When we visit: http://localhost:10086/config/default actually read the config.properties configuration file in the configs directory.
When we visit: http://localhost:10086/config/test actually read the config-test.properties configuration file in the configs directory.
Note the version number of git:
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 @EnableConfigServer
this 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
, importConfigServerConfiguration
and registerMarker
Bean, andMarker
Bean also asConfigServerAutoConfiguration
one of the conditions.
Case study JDBC implementation
-
JdbcTemplate Bean source
JdbcTemplateAutoConfiguration
-
SQL source
JdbcEnvironmentProperties
,The content is:,spring.cloud.config.server.jdbc.sql
if not configured, it will be usedDEFAULT_SQL
by 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 EnvironmentRepository
achieved?
A: premise: how to activate a custom EnvironmentRepository
implementation, 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 EnvironmentRepository
Bean appears in the Spring application context , then it is activated DefaultRepositoryConfiguration
by default (Git implementation), otherwise a custom implementation is adopted.
Custom implementation
Custom EnvironmentRepository
Bean
@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
DefaultRepositoryConfiguration
assembly.
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