In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
In this issue, the editor will bring you how to parse the source code of Apollo client design principles. The article is rich in content and analyzes and describes for you from a professional point of view. I hope you can get something after reading this article.
1. Design principle
Figure 1 briefly describes the implementation principle of the Apollo client.
The client and server maintain a long connection to compile the real-time update push of the configuration.
Timed pull configuration is a scheduled task local to the client. It defaults to pulling every 5 minutes, or you can override it by specifying System Property:apollo.refreshInterval at runtime (in minutes). Push + timed pull = double insurance.
After the client obtains the latest configuration of the application from the Apollo configuration center server, it will be saved in memory.
The client will cache a copy of the configuration obtained from the server in the local file system. When the service or network is not available, you can use the local configuration, that is, our local development mode env=Local.
two。 The principle of integration with Spring
Apollo not only supports API to obtain configuration, but also supports integration with Spring/Spring Boot. After integration, you can obtain configuration directly through @ Value. Let's analyze the principle of integration.
Spring has added ConfigurableEnvironment and PropertySource since version 3.1:
ConfigurableEnvironment implements the Environment interface and contains multiple Property-Source.
PropertySource can be understood as the property configuration of many Key-Value, and the structure at run time is shown in figure 2.
It is important to note that there is a priority order between PropertySource, and if a Key exists in multiple property source, then the property source in front of it takes precedence.
The principle of integration is that during the application startup phase, Apollo takes the configuration from the remote end, assembles it into PropertySource and inserts it into the first one, as shown in figure 3.
3. Initialize the configuration to Spring at startup
The client integrates the code analysis of Spring, and we also explain it in a simplified way.
First of all, let's analyze how the configuration pulled from Apollo at the start of the project is integrated into Spring. Create a PropertySourcesProcessor class to initialize the configuration into Spring PropertySource. The specific code is shown below.
@ Componentpublic class PropertySourcesProcessor implements BeanFactoryPostProcessor, EnvironmentAware {String APOLLO_PROPERTY_SOURCE_NAME = "ApolloPropertySources"; private ConfigurableEnvironment environment;@Overridepublic void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory) throws BeansException {/ / initialize the configuration to Spring PropertySourceConfig config = new Config (); ConfigPropertySource configPropertySource = new ConfigPropertySource ("ap-plication", config); CompositePropertySource composite = new CompositePropertySource (APOLLO_PROPERTY_SOURCE_NAME); composite.addPropertySource (configPropertySource); environment.getPropertySources () .addFirst (composite) } @ Overridepublic void setEnvironment (Environment environment) {this.environment = (ConfigurableEnvironment) environment;}}
The EnvironmentAware interface is implemented to get the Environment object. To implement the BeanFactory-Post-Processor interface, we can read bean information and modify it before the container instantiates the bean.
Config is an interface in Apollo that defines many ways to read configurations, such as getProperty:getIntProperty, etc. To implement these methods through subclasses, we will simplify here and define them directly into a class, providing two necessary methods, as shown below.
Public class Config {public String getProperty (String key, String defaultValue) {if (key.equals ("bianchengName")) {return "C language Chinese Network";} return null;} public Set getPropertyNames () {Set names = new HashSet (); names.add ("bianchengName"); return names;}}
Config is the configuration class. After the configuration is pulled, it will be stored in the class, and all configuration reads must go through it. Here, we define the key to be read as bianchengName.
Then you need to encapsulate the Config into PropertySource before it can be inserted into the Spring Environment.
Define a ConfigPropertySource that encapsulates Config as PropertySource,ConfigProperty-Source inherits EnumerablePropertySource,EnumerablePropertySource and inherits PropertySource. The specific code is shown below.
Public class ConfigPropertySource extends EnumerablePropertySource {private static final String [] EMPTY_ARRAY = new String [0]; ConfigPropertySource (String name, Config source) {super (name, source);} @ Overridepublic String [] getPropertyNames () {Set propertyNames = this.source.getPropertyNames (); if (propertyNames.isEmpty ()) {return EMPTY_ARRAY;} return propertyNames.toArray (new String [propertyNames.size ()]);} @ Overridepublic Object getProperty (String name) {return this.source.getProperty (name, null) }}
What needs to be done is to override the getPropertyNames and getProperty methods. When these two methods are called, the contents of the Config are returned.
Finally, add ConfigPropertySource to the CompositePropertySource and add it to the Confi-gu-rable-Environment.
Define an interface to test whether it works or not, as shown below.
@ RestControllerpublic class ConfigController {@ Value ("${bianchengName:zhangsan}") private String name;@GetMapping ("/ get") private String bianchengUrl;@GetMapping ("/ get") public String get () {return name + bianchengUrl;}}
Add the corresponding configuration to the configuration file:
BianchengName=xxxbianchengUrl= http://minglisoft.cn/cloud
Before adding the code mentioned above, accessing the / get interface returns xxx http://c.biancheng.net. After adding the code explained above, the returned content becomes the ape world http://c.biancheng.net.
This is because the return value of the key corresponding to bianchengName in Config is ape world, and it indirectly proves that the local value can be overwritten in this way at startup. This is the principle of Apollo and Spring integration.
4. How to refresh when modifying the configuration while running
In this section, we will explain how to update the value in Spring when the configuration is changed and pushed to the client during the project run.
The principle is to store all these configurations and modify them when the configuration changes. A SpringValueProcessor class is defined in Apollo to handle changes to values in Spring. Only part of the code is posted below, as shown below.
@ Componentpublic class SpringValueProcessor implements BeanPostProcessor, BeanFactoryAware {private PlaceholderHelper placeholderHelper = new PlaceholderHelper (); private BeanFactory beanFactory;public SpringValueRegistry springValueRegistry = new SpringValueRegistry (); @ Overridepublic Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException {Class clazz = bean.getClass (); for (Field field: findAllField (clazz)) {processField (bean, beanName, field);} return bean;} private void processField (Object bean, String beanName, Field field) {/ / register @ Value on fieldValue value = field.getAnnotation (Value.class) If (value = = null) {return;} Set keys = placeholderHelper.extractPlaceholderKeys (value.value ()); if (keys.isEmpty ()) {return;} for (String key: keys) {SpringValue springValue = new SpringValue (key, value.value (), bean, beanName, field, false); springValueRegistry.register (beanFactory, key, springValue);}}
The values in each bean are processed by implementing BeanPostProcessor, and then the configuration information is encapsulated as a SpringValue and stored in springValueRegistry.
The SpringValue code is shown below.
Public class SpringValue {private MethodParameter methodParameter;private Field field;private Object bean;private String beanName;private String key;private String placeholder;private Class targetType;private Type genericType;private boolean isJson;}
SpringValueRegistry is stored using Map, and the code is shown below.
Public class SpringValueRegistry {private final Map registry = Maps.newConcurrentMap (); private final Object LOCK = new Object (); public void register (BeanFactory beanFactory, String key, SpringValue springValue) {if (! registry.containsKey (beanFactory)) {synchronized (LOCK) {if (! registry.containsKey (beanFactory)) {registry.put (beanFactory, LinkedListMultimap.create ()) } registry.get (beanFactory) .put (key, springValue);} public Collection get (BeanFactory beanFactory, String key) {Multimap beanFactorySpringValues = registry.get (beanFactory); if (beanFactorySpringValues = = null) {return null;} return beanFactorySpringValues.get (key);}}
Write an interface to simulate configuration changes, as shown below.
@ RestControllerpublic class ConfigController {@ Autowiredprivate SpringValueProcessor springValueProcessor;@Autowiredprivate ConfigurableBeanFactory beanFactory;@GetMapping ("/ update") public String update (String value) {Collection targetValues = springValueProcessor.springValueRegistry.get (beanFactory, "bianchengName"); for (SpringValueval: targetValues) {try {val.update (value);} catch (IllegalAccessException | InvocationTargetException e) {e.printStackTrace ();}} return name;}}
When we call the / update interface, we can see in the previous / get interface that the value of the ape world has been changed to the value you passed in, which is dynamic modification.
You can learn a lot by reading the source code of Apollo.
Apollo uses Mysql. Apollo is a number of libraries through which to distinguish configurations in different environments.
Apollo implements push based on Http persistent connection, as well as timing pull logic for disaster recovery.
Apollo also has its own native objects that get values, and it is also integrated into Spring to be compatible with the way older projects are used.
Annotations can be used to monitor directly in Apollo, which is very convenient.
This is what the source code parsing of the Apollo client design principle shared by Xiaobian is like. If you happen to have similar doubts, you might as well refer to the above analysis to understand. If you want to know more about it, you are welcome to follow the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.