当前位置:网站首页>Handwriting distributed configuration center (1)
Handwriting distributed configuration center (1)
2022-07-25 21:24:00 【You who share dry goods】
1 What is a distributed configuration center
In fact, it is to separate some configuration information from its own system , And these information can be obtained in real time by application . Here we use springboot For example , We all know springboot When it starts , Will load resource Under directory application.properties perhaps application.yml. At this time, we will springboot The configuration file that needs to be loaded when starting Not together with the project , Unified management , This is the core idea of distributed configuration center .
1.1 What are the components of the distributed configuration center
1.1.1, There is an interface to operate and configure
1.1.2, Data can be persistent ( To prevent loss , The service offline configuration still exists at startup )
1.1.3, There are clients and servers , The client actively pulls data or the server actively pushes data . And refresh the configuration of this machine .( The core )
1.1.4, Some operation logs of the management interface , Authority system, etc .
2, Mainstream configuration centers in the market
2.1 Ali's nacos
Nacos Dedicated to helping you discover 、 Configure and manage microservices .Nacos Provides an easy-to-use feature set , Helps you quickly implement dynamic service discovery 、 Service configuration 、 Service metadata and traffic management .
Nacos Helps you build more quickly and easily 、 Deliver and manage microservice platforms . Nacos Is to build in “ service ” Modern application architecture centered ( For example, the microservices paradigm 、 Cloud native paradigm ) Service infrastructure . Please refer to the official website for specific use
2.2 nacos Principle , Namely service Monitor whether the configuration changes , Send it to the client through a long link
The schematic diagram of the architecture is as follows , This is push mode , But it is based on long links
2.3 Ctrip's Apollo
Apollo It is a production level configuration center product developed and open-source by Ctrip framework department , It can centrally manage applications in different environments 、 Configuration of different clusters , After configuration modification, it can be pushed to the application end in real time , And have standard authority 、 Process governance and other features , Applicable to microservice configuration management scenarios . Please refer to the official website for specific use
The schematic diagram of Ctrip's architecture is also similar to Nacos It's the same , Also long link polling , Server push mode .
2.3 spirgcloud config
springCloudConfig, It supports the configuration service to be placed in the memory of the configuration service ( Namely local ), It also supports remote Git/svn Warehouse .
When the service starts config Service It will be remotely git Pull configuration file , And save it locally git library , When remote git Is not available , From the local git The file library pulls configuration information . Please refer to the official website for specific use .
2.4 Baidu disconf
Disconf Baidu is an open source product based on Zookeeper Distributed configuration management software . At present, many companies are using , Including drops 、 Baidu 、 NetEase 、 Shunfeng and other companies . The configuration properties can be dynamically modified through simple interface operation , It's very convenient . Use Disconf One of the great benefits found after is that it saves a lot of configuration , And the configuration can be automatically load, In real time .
Basic schematic diagram : Of course, the concrete must be more complicated than this , This is just the main process .
3 How to implement your own distributed configuration center
3.1 Dynamically modify local @Value Configuration of annotations
3.2 In different bean in , same value How to modify at the same time .
4 Specific ideas
How to dynamically modify @Value annotation Configuration of , We need to know springboot How to load application.ym perhaps application.properties Of documents .
I use it here. springboot2.1.1 Code for demonstration .
Start by opening
find spring.factors Configuration file for
We can see that the above three are the loaders of configuration files , It also shows why properties The priority ratio yaml High priority . He is arranged from top to bottom . But the real configuration file executes the following
Let's click to see the implementation class
ConfigFileApplicationListene
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
// How to load resources
addPropertySources(environment, application.getResourceLoader());
}
protected void addPropertySources(ConfigurableEnvironment environment,
ResourceLoader resourceLoader) {
RandomValuePropertySource.addToEnvironment(environment);
// Give resources to load To the environment variable
new Loader(environment, resourceLoader).load();
}
// Reuse propertySource The parser parses
Loader(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
this.environment = environment;
this.placeholdersResolver = new PropertySourcesPlaceholdersResolver(
this.environment);
this.resourceLoader = (resourceLoader != null) ? resourceLoade
: new DefaultResourceLoader();
this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(
PropertySourceLoader.class, getClass().getClassLoader());
}Then we will know , That is, if we can EnvironmentPostProcessor , The method in the rewrite can also dynamically load the configuration file . Now let's start the code implementation .
4.1 Code implementation
In that case, we can achieve EnvironmentPostProcessor This class dynamically loads the configuration file through the interface .
The following is the specific code implementation
@Autowired
ConfigurableEnvironment configurableEnvironment;
@Autowired
Environment environment;
@Test
public void test() {
String name = environment.getProperty("name");
System.out.printf(" Before dynamic loading " +name);
Map<String,String> map = new HashMap<>();
map.put("name"," toot toot ");
configurableEnvironment.getPropertySources().addLast(
new OriginTrackedMapPropertySource("xxxx.xml", map)
);
String property = environment.getProperty("name");
System.out.printf(" After dynamic loading " +property);
}4.1.2 unit testing
The end result is
We have now solved the first problem , How to dynamically add environment variables
The second question is @value How to dynamically refresh the annotation .
Then we need ConfigurablePropertyResolver This class , To parse this key , stay find @value Corresponding bean Refresh through reflection
Specific code
4.2 Code implementation
public static void refreshBean(Object bean, ConfigurablePropertyResolver propertyResolver) {
// Definition EL Expression interpreter
SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
TemplateParserContext templateParserContext= new TemplateParserContext();
String keyResolver, valueResolver = null;
Object parserValue;
// Get real object properties
Field[] declaredFields = bean.getClass().getDeclaredFields();
boolean cglib = Arrays.stream(declaredFields).anyMatch(x -> x.getName().contains("CGLIB"));
// If it is cglib The proxy finds its parent
if(cglib){
declaredFields = bean.getClass().getSuperclass().getDeclaredFields();
}
// Traverse Bean All attributes of the instance
for (Field field : declaredFields) {
// Judge field Does it contain @Value annotation
if (field.isAnnotationPresent(Value.class)) {
// Read Value Annotation placeholder
keyResolver = field.getAnnotation(Value.class).value();
try {
// Read property values
valueResolver = propertyResolver.resolveRequiredPlaceholders(keyResolver);
// EL Expression parsing
// Compatible form as :@Value("#{'${codest.five.url}'.split(',')}") contain EL In the case of expressions
Expression expression = spelExpressionParser.parseExpression(valueResolver, templateParserContext);
if(field.getType() == Boolean.class){
parserValue =Boolean.valueOf(expression.getValue().toString());
}
else if(field.getType() == Integer.class){
parserValue =Integer.valueOf(expression.getValue().toString());
}
else if(field.getType() == Long.class){
parserValue =Long.valueOf(expression.getValue().toString());
}else {
parserValue = expression.getValue(field.getType());
}
} catch (IllegalArgumentException e) {
continue;
}
// Determine whether the configuration item exists
if (Objects.nonNull(valueResolver)) {
field.setAccessible(true);
try {
field.set(bean, parserValue);
continue;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}We are writing a unit test test
4.2.1 unit testing
@Autowired
ConfigurableEnvironment configurableEnvironment;
@Autowired
ConfigurablePropertyResolver configurablePropertyResolver;
@Autowired
Person person;
@Test
public void test() {
System.out.printf(" Before dynamic loading " +person.getName());
Map<String,Object> map = new HashMap<>();
map.put("name"," toot toot ");
configurableEnvironment.getPropertySources().forEach( x->{
if (x instanceof OriginTrackedMapPropertySource ) {
Map<String,Object> map1 = (Map<String, Object>) x.getSource();
map1.putAll(map);
}
}
);
refreshBean(person,configurablePropertyResolver);
System.out.printf(" After dynamic loading " +person.getName());
}The final results :
perfect , In the next issue, we will solve Multiple bean, @value How to refresh at the same time .
Specific documents will be sent to Nuggets first , Please pay attention to Nuggets https://juejin.cn/post/7121327906269200421
边栏推荐
- 一道golang中关于map的并发读写的面试题
- Huatai Securities account opening process, is it safe to open an account on your mobile phone
- When MySQL imports data, it has been changed to CSV utf8 file and the file name is English. Why does it still fail to import
- Byte side: can TCP and UDP use the same port?
- Basic method of black box (function) test
- ES6 --- four powerful operators (?,? =,?.,?:)
- How to choose sentinel vs. hystrix current limiting?
- Experience sharing of system architecture designers preparing for the exam: from point to surface
- IEC61131 address representation
- Matlab---eeglab check EEG signal
猜你喜欢

接口测试工具 restlet client

Zero basic learning canoe panel (17) -- panel CAPL function

Debugged PEB (beingdebugged, ntglobalflag)

Too many passwords, don't know how to record? Why don't you write a password box applet yourself

pyqt5使用pyqtgraph绘制多个Y值散点图

人脸与关键点检测:YOLO5Face实战

JMeter distributed pressure measurement

零基础学习CANoe Panel(17)—— Panel CAPL Function

2022 latest examination questions and answers of eight members (standard staff) of Shanghai Architecture

NVIDIA has opened source a comprehensive library of 3D deep learning based on pytorch
随机推荐
Matlab---eeglab check EEG signal
Hello, I'd like to ask questions about C and database operation.
Miscellaneous notes -- a hodgepodge
Kali modify the update source (it is not safe to update with this source)
My heart's broken! After being cheated by 30000, a 16-year-old girl was unconvinced and cheated by 50000
ONEFLOW V0.8.0 officially released
Rent two or three things
NPM module removal_ [solved] after NPM uninstalls the module, the module is not removed from package.json [easy to understand]
工作面试总遇秒杀? 看了京东 T8 大咖私藏的秒杀系统笔记, 已献出膝盖
ag 搜索工具参数详解
Research: more than 70% of doctors are still prescribing unsafe antibiotic drugs
A detailed explanation of SCP command
CNN structural design skills: taking into account speed accuracy and engineering implementation
IEC61131 address representation
牛客-TOP101-BM38
Vivo official website app full model UI adaptation scheme
Explain the principle of MySQL master-slave replication in detail
Opencv learning Fourier transform experience and line direction Fourier transform code
浅谈web性能优化(一)
MySQL master-slave replication data synchronization, summary of common problems