Spring Cloud переопределяет свойства удаленной конфигурации

Spring Boot

Переопределить свойства удаленной конфигурации

Источником конфигурации приложения обычно является удаленный сервер 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
Диаграмма класса ConfigServicePropertySourceLocator

ConfigServicePropertySourceLocatorСуть в том, что это локатор ресурсов свойств, основным методом которого являетсяlocate(Environment environment). Во-первых, замените заполнители в configClientProperties приложением, профилем и меткой среды, в которой в данный момент работает приложение, и инициализируйте RestTemplate, затем пройдитесь по массиву меток, пока не будет получена действительная информация о конфигурации, и, наконец, повторите попытку в зависимости от того, быстро ли произойдет сбой. . Основной процесс выглядит следующим образом:

locate
найти поток обработки

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;
        ...
    
}

Подписывайтесь на свежие статьи, приглашаю обратить внимание на мой публичный номер

微信公众号

Ссылаться на

Spring Cloud Edgware.RELEASE