Переопределить свойства удаленной конфигурации
Источником конфигурации приложения обычно является удаленный сервер Config Server.По умолчанию локальная конфигурация имеет более низкий приоритет, чем удаленный репозиторий конфигурации. Если вы хотите реализовать системные переменные и файлы конфигурации локального приложения для переопределения значений атрибутов в удаленном хранилище, вы можете установить его следующим образом:
spring:
cloud:
config:
allowOverride: true
overrideNone: true
overrideSystemProperties: false
- overrideNone: если для параметра allowOverride задано значение true, для параметра overrideNone задано значение true, внешняя конфигурация имеет более низкий приоритет и не может переопределить существующие источники свойств. Значение по умолчанию — ложь
- allowOverride: указывает, включено ли свойство overrideSystemProperties. По умолчанию установлено значение true, установленное значение false означает запрет пользовательских настроек.
- overrideSystemProperties: используется для определения того, может ли внешняя конфигурация переопределять системные свойства, значение по умолчанию — true.
Благодаря приведенной выше конфигурации клиент может понять, что локальная конфигурация имеет более высокий приоритет и не может быть перезаписана. Поскольку текущая версия Spring Cloud, на которой мы основаны,Edgware.RELEASE
, вышеуказанные настройки не работают, но используйтеPropertySourceBootstrapProperties
значение по умолчанию в . Подробности смотрите в выпуске:https://github.com/spring-cloud/spring-cloud-commons/pull/250
, мы поговорим о конкретном источнике ошибки, когда будем анализировать его ниже.
Анализ исходного кода
ConfigServicePropertySourceLocator
Перезапись свойств удаленной конфигурации в конечном счете связана с конфигурацией, полученной при запуске клиента.Как быть с конфигурацией после получения конфигурации? Давайте посмотрим на класс получения ресурсов в весенней конфигурации облака.ConfigServicePropertySourceLocator
диаграмма классов.
ConfigServicePropertySourceLocator
Суть в том, что это локатор ресурсов свойств, основным методом которого являетсяlocate(Environment environment)
. Во-первых, замените заполнители в configClientProperties приложением, профилем и меткой среды, в которой в данный момент работает приложение, и инициализируйте RestTemplate, затем пройдитесь по массиву меток, пока не будет получена действительная информация о конфигурации, и, наконец, повторите попытку в зависимости от того, быстро ли произойдет сбой. . Основной процесс выглядит следующим образом:
locate(Environment environment)
перечислитьgetRemoteEnvironment(restTemplate, properties, label, state)
Метод получает данные конфигурации на удаленном сервере по протоколу http. Реализация также очень проста.Он отображает и заменяет заполнители в пути пути запроса, а затем собирает заголовки.После сборки запрос может быть отправлен, и, наконец, возвращается результат.
В приведенной выше реализации мы видим, что полученная информация о конфигурации хранится вCompositePropertySource
, как он используется? Еще один важный класс, который следует добавить сюда, — это PropertySourceBootstrapConfiguration, который реализует интерфейс ApplicationContextInitializer, который будет использоваться до обновления контекста приложения.refresh()
Вызывается для выполнения операции инициализации, стек вызовов после запуска приложения выглядит следующим образом:
SpringApplicationBuilder.run() -> SpringApplication.run() -> SpringApplication.createAndRefreshContext() -> SpringApplication.applyInitializers() -> PropertySourceBootstrapConfiguration.initialize()
PropertySourceBootstrapConfiguration
в то время как вышеConfigServicePropertySourceLocator
Метод locate будет вызываться при инициализации, чтобы убедиться, что контекст может получить необходимую информацию о конфигурации до его обновления. В частности, посмотрите на метод инициализации:
public class PropertySourceBootstrapConfiguration implements
ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
private int order = Ordered.HIGHEST_PRECEDENCE + 10;
@Autowired(required = false)
private List<PropertySourceLocator> propertySourceLocators = new ArrayList<>();
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
CompositePropertySource composite = new CompositePropertySource(
BOOTSTRAP_PROPERTY_SOURCE_NAME);
//对propertySourceLocators数组进行排序,根据默认的AnnotationAwareOrderComparator
AnnotationAwareOrderComparator.sort(this.propertySourceLocators);
boolean empty = true;
//获取运行的环境上下文
ConfigurableEnvironment environment = applicationContext.getEnvironment();
for (PropertySourceLocator locator : this.propertySourceLocators) {
//遍历this.propertySourceLocators
PropertySource<?> source = null;
source = locator.locate(environment);
if (source == null) {
continue;
}
logger.info("Located property source: " + source);
//将source添加到PropertySource的链表中
composite.addPropertySource(source);
empty = false;
}
//只有source不为空的情况,才会设置到environment中
if (!empty) {
//返回Environment的可变形式,可进行的操作如addFirst、addLast
MutablePropertySources propertySources = environment.getPropertySources();
String logConfig = environment.resolvePlaceholders("${logging.config:}");
LogFile logFile = LogFile.get(environment);
if (propertySources.contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
//移除bootstrapProperties
propertySources.remove(BOOTSTRAP_PROPERTY_SOURCE_NAME);
}
//根据config server覆写的规则,设置propertySources
insertPropertySources(propertySources, composite);
reinitializeLoggingSystem(environment, logConfig, logFile);
setLogLevels(environment);
//处理多个active profiles的配置信息
handleIncludedProfiles(environment);
}
}
//...
}
Давайте посмотрим ниже, вinitialize
что делается в методе.
- Отсортируйте массив propertySourceLocators в соответствии с параметрами сортировки AnnotationAwareOrderComparator по умолчанию.
- Получить контекст рабочей среды ConfigurableEnvironment
- При обходе propertySourceLocators
- Вызовите метод locate, передав полученную контекстную среду
- Добавить источник в связанный список PropertySource
- Установите, является ли источник пустым идентификатором scalar empty
- Если источник не пуст, он будет установлен в среду
- Возвращает переменную форму Environment, которой можно управлять, например, addFirst, addLast
- Удалить bootstrapProperties в propertySources
- Установите propertySources в соответствии с правилами, переопределенными сервером конфигурации.
- Обработка информации о конфигурации для нескольких активных профилей
метод инициализацииinitialize
При обработке сначала ставить все объекты типа PropertySourceLocatorlocate
Метод проходит, затем помещает полученные различными способами значения свойств в CompositePropertySource, и, наконец, вызываетinsertPropertySources(propertySources, composite)
Метод установлен в Environment. Spring Cloud Context предоставляет способ переопределения удаленных свойств.PropertySourceBootstrapProperties
и используйте этот класс конфигурации для определения приоритета источника атрибута.
private void insertPropertySources(MutablePropertySources propertySources,
CompositePropertySource composite) {
MutablePropertySources incoming = new MutablePropertySources();
incoming.addFirst(composite);
PropertySourceBootstrapProperties remoteProperties = new PropertySourceBootstrapProperties();
new RelaxedDataBinder(remoteProperties, "spring.cloud.config")
.bind(new PropertySourcesPropertyValues(incoming));
//如果不允许本地覆写
if (!remoteProperties.isAllowOverride() || (!remoteProperties.isOverrideNone()
&& remoteProperties.isOverrideSystemProperties())) {
propertySources.addFirst(composite);
return;
}
//overrideNone为true,外部配置优先级最低
if (remoteProperties.isOverrideNone()) {
propertySources.addLast(composite);
return;
}
if (propertySources
.contains(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME)) {
//根据overrideSystemProperties,设置外部配置的优先级
if (!remoteProperties.isOverrideSystemProperties()) {
propertySources.addAfter(
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
composite);
}
else {
propertySources.addBefore(
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
composite);
}
}
else {
propertySources.addLast(composite);
}
}
Вышеупомянутая реализация в основном основана наPropertySourceBootstrapProperties
свойства, чтобы настроить приоритет нескольких источников конфигурации. Это видно по его реализацииPropertySourceBootstrapProperties
Объект инициализируется напрямую, используя значения свойств по умолчанию вместо внедрения того, что мы установили в файле конфигурации.
Фиксированная реализация:
@Autowired(required = false)
private PropertySourceBootstrapProperties remotePropertiesForOverriding;
private void insertPropertySources(MutablePropertySources propertySources, CompositePropertySource composite) {
MutablePropertySources incoming = new MutablePropertySources();
incoming.addFirst(composite);
PropertySourceBootstrapProperties remoteProperties = remotePropertiesForOverriding == null ? new PropertySourceBootstrapProperties() : remotePropertiesForOverriding;
...
}