This is the 14th day of my participation in Gwen Challenge

“Configuration center Spring Cloud Config in detail” series of articles updated, together in the road of technology progress! This series of articles will introduce Spring Cloud Config, which provides a distributed configuration center in Spring Cloud. In addition to the code to realize system functions, application services also need to connect resources and other applications. There are often a lot of data that need to be configured externally to adjust the behavior of applications, such as switching different databases and setting function switches. With the increase of microservices, the system needs to be scalable and extensible, in addition to managing the configuration data of a considerable number of service instances. In the application development stage, each service is autonomous, but in the production environment, it will bring great trouble to the operation and maintenance, especially the micro service scale is relatively large, configuration update is more troublesome. Therefore, the system needs to establish a unified configuration management center.

In previous articles, we went into some of the details of the client implementation. This article will focus on specifying the configuration server through HTTP URIs and service delivery.

Specify the Config Server through the HTTP URI

Retry annotation specifies the interceptor configuration configServerRetryInterceptor, the initialization of an object, as has been said in the previous. ConfigServicePropertySourceLocator essence is a property resource locator, the main method is # locate (Environment Environment). Initialize the RestTemplate by replacing the placeholders in configClientProperties with the Application, Profile, and Label of the current running application environment, and then iterate through the Labels array until the configuration information is valid. Finally, a retry is performed depending on whether a quick failure occurs. The main flow chart is as follows:

#locate(Environment Environment) calls the #getRemoteEnvironment method to retrieve configuration data from the remote server via HTTP. This is done by first replacing the placeholder in the request path, then performing headers assembly, sending the request after assembly, and finally returning the result. In the above implementation, we see that the obtained configuration information is stored at CompositePropertySource, so how is it used? Here is another important class PropertySourceBootstrapConfiguration, it implements the ApplicationContextInitializer interface, the interface will refresh before application context refresh () callback, The call stack after the application is started is as follows:

SpringApplicationBuilder.run() -> SpringApplication.run() -> SpringApplication.createAndRefreshContext() -> SpringApplication.applyInitializers() -> PropertySourceBootstrapConfiguration.initialize()
Copy the code

And above ConfigServicePropertySourceLocator will locate method in PropertySourceBootstrapConfiguration. # in the initialize is called, This ensures that the context gets the necessary configuration information before refreshing. Look at the initialize method:

public class PropertySourceBootstrapConfiguration implements
		ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {

	@Override
	public void initialize(ConfigurableApplicationContext applicationContext) {
		CompositePropertySource composite = new CompositePropertySource(
				BOOTSTRAP_PROPERTY_SOURCE_NAME);
		AnnotationAwareOrderComparator.sort(this.propertySourceLocators);
		boolean empty = true;
		ConfigurableEnvironment environment = applicationContext.getEnvironment();
		for (PropertySourceLocator locator : this.propertySourceLocators) { PropertySource<? > source =null;
			source = locator.locate(environment);
			if (source == null) {
				continue;
			}
			composite.addPropertySource(source);
			empty = false;
		}
		if(! empty) { MutablePropertySources propertySources = environment.getPropertySources(); String logConfig = environment.resolvePlaceholders("${logging.config:}");
			LogFile logFile = LogFile.get(environment);
			if(propertySources.contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) { propertySources.remove(BOOTSTRAP_PROPERTY_SOURCE_NAME); } insertPropertySources(propertySources, composite); reinitializeLoggingSystem(environment, logConfig, logFile); setLogLevels(environment); handleIncludedProfiles(environment); }}... }Copy the code

Let’s take a look at what happens in the Initialize method.

  • According to the default AnnotationAwareOrderComparator collation of propertySourceLocators sort an array
  • Gets the runtime environment context ConfigurableEnvironment
  • When traversing propertySourceLocators
    • Call the Locate method, passing in the obtained context Environment
    • Add source to the list of PropertySource
    • The identity scalar empty that sets whether source is empty
  • Set to environment only if source is not empty
    • Returns the variable form of the Environment for operations such as addFirst and addLast
    • Remove bootstrapProperties from propertySources
    • Set propertySources according to the rules overridden by config Server
    • Process configuration information for multiple active profiles

The above procedure applies the configuration information pulled from the specified Config Server to our client service.

Specify Config Server through service discovery

Specify Config Server through service discovery. When the Config Client starts up, it first finds Config Server through service discovery, then pulls the corresponding configuration information from Config Server, and initializes the Spring environment with these remote property resources. If you use the service discovery components, such as Eureka, Spring Cloud Consul, you need to set up Spring. Cloud. Config. Discovery. Enabled = true, because of the way is the default HTTP URI, The client application cannot register with the service. All client applications must be configured with correct service discovery information. Such as using Spring Cloud Netflix, you need to specify the Eureka server address Eureka. Client. ServiceUrl. DefaultZone. Locate service registrations at startup with the overhead of requiring additional network requests. The advantage is that Config Server is highly available and avoids single points of failure. The default serviceId is “configServer”. We can pass on the client side of the spring. The cloud. Config. Discovery. ServiceId properties to change (usually by the spring in the config Server. Application. The name configured a service). Service discovery client implementation to support multiple types of metadata map, such as Eureka Eureka. Instance. MetadataMap. Some additional properties of Config Server need to be configured in the metadata of the service registry so that the client can connect properly. If Config Server uses basic HTTP security, we can configure the user name and password for the certificate. Or if Config Server has a context path, we can set “configPath”. You can configure the client config information as follows:

eureka:
  instance:
    .
    metadataMap:
      user: osufhalskjrtl
      password: lviuhlszvaorhvlo5847
      configPath: /config
Copy the code

Below we see DiscoveryClientConfigServiceBootstrapConfiguration configured in what context before the start.

@ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled", matchIfMissing = false)
@Configuration
@Import({ UtilAutoConfiguration.class })
@EnableDiscoveryClient
public class DiscoveryClientConfigServiceBootstrapConfiguration {

	@Bean
	public ConfigServerInstanceProvider configServerInstanceProvider( DiscoveryClient discoveryClient) {
		return new ConfigServerInstanceProvider(discoveryClient);
	}

	@EventListener(ContextRefreshedEvent.class)
	public void startup(ContextRefreshedEvent event) {
		refresh();
	}

	@EventListener(HeartbeatEvent.class)
	public void heartbeat(HeartbeatEvent event) {
		if(monitor.update(event.getValue())) { refresh(); }}}Copy the code

It mainly configures the Config client to find the Config Server service through the service discovery component. It also configures the listener of two kinds of events: context refresh event and heartbeat event. After getting the configuration information from Config Server, the rest of the process is the same as getting Config Server by specifying the HTTP URI, as explained in the previous article.

summary

This article focuses on how the Spring Cloud Config client specifies the configuration server through HTTP URIs and service discovery, as well as the related implementation details. The following articles will describe the implementation of server-side configuration change monitoring in the client implementation.