#前言

       近年来,微服务架构的模式越来越受到大众的追捧。究其缘由,传统的单体式应用服务一直面临的问题:业务代码臃肿、部署更新繁琐、语言单一,无法满足如今互联网产品业务需求快速变化时快捷、解耦的开发和部署需求。微服务思想,根据业务模块和基础能力需求,拆分成平级的服务组件,每个组件服务可以采用最适合的语言平台或者技术架构。
       服务分离,解耦了开发和部署,同时,也面临着亟待解决的问题:服务的配置管理,服务间数据交互等。

##统一配置服务

       传统的单体式应用,由于代码的高度集中,配置的管理相对比较容易。一般的企业配置会选择存储到数据库,升级部署时只需要修改数据库连接配置即可,再不济,由于服务集中,直接修改配置文件也行。
       微服务拆分后,服务变多,部署更新时,挨个服务的去修改配置变得不切实际,不仅效率低,出错的概率也大。而且,微服务模式之后,数据库也已经分离,从数据库读取配置也变成不可能。所以,需要一种方案来解决这种情况。解决这种情况,无非只需要提供一条所有的微服务都能获取配置的途径,这种需求引申出一个基础能力组件:统一配置服务

##spring cloud config

       Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。下面我们要介绍的是其中的配置中心:spring cloud config,以下简称configServer。

##简介

       统一配置服务分两部分:提供配置的服务端和提供到服务端获取配置的客户端。很容易理解,提供配置的服务端是独立的微服务,负责从配置库提取配置提供给其他微服务。供到服务端获取配置的客户端,其实就是配置服务提供的工具,帮组微服务从配置服务服务端获取配置。

##构建适合自己的配置服务

       关于configServer的使用方法,在这里我们不作详细的说明,官网有文档可以参考。我们这里介绍下如何结合自己目前的项目对configServer进行扩展。
       configServer目前提供基于git、svn和本地文件的方式管理配置。基于git和svn的配置管理依赖于git和svn服务,对于需要产品式快速部署场景,不可能为每套环境单独部署一套git或者svn服务(有人说用公有的git和sv服务,这个需要微服务有外网的访问权限,部分政府性质的企业不会允许内部的服务访问公网)。大多数企业对于自己的项目都有一套配置维护的模式,configServer提供的几种配置模式不一定能满足所有的需求,所以,在configServer原有功能基础上扩展一套适用于自己企业的配置管理模式显得很有必要。
       翻看configServer的源码可以发现,有个关键的接口EnvironmentRepository,根据其命名和提供的方法可以猜出,是用于从配置库读取配置的对象。

public interface EnvironmentRepository {

	Environment findOne(String application, String profile, String label);

}

       configServer通过spring.profiles.active配置选择配置库模式,从自动加载配置文件看,支持native、git、subversion

微服务配置ribbon重试次数 微服务config_微服务配置ribbon重试次数


       从上面的代码分析,我们需要实现一套从自己的配置库读取配置的EnvironmentRepository实现类即可。

##基于数据库存储配置的例子

       下面是基于数据库配置扩展的加载配置的代码,@Profile(“db”)表示如果spring.profiles.active=db,将会以扩展的数据库配置模式启动

public class DbEnvironmentRepositoryConfiguration {
	
	@Configuration
	@Profile("db")
	protected static class NativeRepositoryConfiguration {

		@Autowired
		private JdbcTemplate jdbcTemplate;

		@Bean
		public DbEnvironmentRepository nativeEnvironmentRepository() {
			return new DbEnvironmentRepository(jdbcTemplate);
		}
	}
}

       下面是基于数据库配置实现EnvironmentRepository接口的环境配置库读取配置的对象

public class DbEnvironmentRepository implements EnvironmentRepository{

	private final static String DEFAULT_VERSION = "1";
	
	private PropertiesStore propertiesStore;
	private String version = DEFAULT_VERSION;
	
	public DbEnvironmentRepository(JdbcTemplate jdbcTemplate) {
		this.propertiesStore = new DbPropertiesStore(jdbcTemplate);
	}

	@Override
	public Environment findOne(String application, String profile, String label) {
		ConfigurableEnvironment environment = getEnvironment(profile);
		return fillEnviroment(new PassthruEnvironmentRepository(environment).findOne(application,
				profile, label));
	}
	
	private ConfigurableEnvironment getEnvironment(String profile) {
		ConfigurableEnvironment environment = new StandardEnvironment();
		environment.getPropertySources()
				.addFirst(new MapPropertySource("profiles",
						Collections.<String, Object>singletonMap("spring.profiles.active",
								profile)));
		return environment;
	}
	
	private Environment fillEnviroment(Environment value){
		Environment environment = new Environment(value.getName(), value.getProfiles(),
				value.getLabel(), this.version, value.getState());
		environment.addAll(value.getPropertySources());
		
		environment.addAll(propertiesStore.loadProperties(environment));
		
		return environment;
	}

}

       启动后访问http://localhost:8080/{具体应用的application.name}/default,将会从数据库读取指定应用的默认配置数据。
       读取数据库方面的代码没有提供,可以根据自己的实际环境实现。