天天看点

Spring Cloud 微服务之配置中心解决方案

关于配置中心这一篇博文,本来想分很多篇去介绍的,但是仔细想想,觉得太繁复而且啰嗦,所以还是写一篇介绍其中的核心原理,并不做任何示例,如果想要查看具体用法可以自行查看官方文档或者度娘。因为配置中心太多了,不说其他的Spring Cloud就集成了好几种框架作为配置中心比如:Spring Cloud Config, Archaiu,Consul, Spring Cloud Zookeeper ,Alibaba Nacos等。每个公司都有不同的选择,不可能一一的去列举,重点是掌握核心,当遇到新的配置中心的时候能够快速入手。

在讲解核心原理之前,我们先介绍下为什么会引入配置中心的模块。在微服务架构中,一个服务可能被部署在成百上千甚至上万的节点上(服务器上),如果将配置全部配置在应用的application.yaml或者application.properties中,一旦我们需要修改某个配置,我们需要手动需修改每一个服务的配置,如果动手一个一个的修改,想想都会头大吧。当然也可以使用脚本的方式修改,但是如果脚本修改失败,就会造成有的更新成功,有的更新失败,最关键的是我们不能做到实时更新,需要重启应用才能使用最新的配置。而且每个应用维护自己的配置显得配置冗杂。为了解决该问题,于是提示了配置中心的概念。那么什么是配置中心呢?

配置中心顾名思义,就是所有配置的中心。就是我们将所有服务的配置,通过配置中心存储到数据库或者其他地方,而应用服务则是从配置中心拉取去配置。在这里它一般分为服务端和客户端,服务端用于我们添加修改配置,客户端用于应用从配置服务拉取配置。一般情况下配置服务分为两种模式,一种为拉取配置,第二种为推送配置。就是客户端定时从配置服务器拉取最新的配置,推送配置则是配置更新后,配置服务器将更新的配置推送到对应的应用服务。

前面说了一堆的废话,我想大多数人喜欢看的是如何使用配置中心,而不是配置中心是怎么来的,写一个配置中心。下面我们结合Zookeeper和Spring Cloud Config 介绍配置中心的使用。关于Zookeeper,它是一个分布式的,开放源码的分布式应用程序协调服务,它提供的其中的一个功能就是配置维护,也就是说我们可以将配置存储在Zookeeper中。下面我们简单描述Zookeeper在配置中心的使用。

Spring Boot应用中都有一个实例名称即spring.application.name的配置,还有一个spring.profiles.active配置,可以说这两个配置是配置中心的基础,也使用这两个配置从配置中心获取配置。假如在Zookeeper中配置的根节点为 /config,那么应用的配置节点可以设置为/config/serviceId/profile/,应用ZooKeeper客户端监听节点/config/serviceId/profile/,一旦节点发生变化,会通知给应用服务,应用服务则更改配置为最新的配置。这就是ZooKeeper作为配置中心的基本原理,具体实现跟使用不再这里不再讲解,如果后续使用到ZooKeeper作为配置中心,再补充相关博客内容。

其他的配置中心我们不再介绍,如果使用到再补充相关使用的博文,其实不管是使用哪个作为配置中心,他们的实现都基本是类似的,下面我们来讲述Spring Cloud 配置中心的原理,说到这里我们不得不回到Spring Boot中,因为Spring Cloud就是基于Spring Boot为核心。在前面Spring Boot原理一篇我们介绍了Spring Boot 创建实例的原理,没有有讲解关于配置的原理。这里我们简单的介绍Spring Cloud 是如何结合Spring Boot实现配置中心的。同样是SpringApplication提供的run方法内部代码如下:

public ConfigurableApplicationContext run(String... args) {
    ......
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    ......
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
        .......
        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
    configureIgnoreBeanInfo(environment);
    Banner printedBanner = printBanner(environment);
    ......
}
           

上面的代码中prepareEnvironment方法用于为Spring Boot运行环境提供配置,在Spring中所有的配置最终由Environment实例管理。我们查看prepareEnvironment方法的源码如下:

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) {
    // Create and configure the environment
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    //解析和配置application.properties中的配置和运行时传入的参数配置
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    //在SpringApplicationRunListeners 解析和处理配置
    listeners.environmentPrepared(environment);
    bindToSpringApplication(environment);
    if (!this.isCustomEnvironment) {
        environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
    }
    ConfigurationPropertySources.attach(environment);
    return environment;
}
           

在上面的代码中,一部分是处理配置文件中的配置,另一部分是通过SpringApplicationRunListeners 处理配置,SpringApplicationRunListeners 是配置中心的基础,客户端可以通过实现SpringApplicationRunListeners 的environmentPrepared方法,在该方法中可以将配置设置到Environment实例中。不同的配置中心比如Zookeeper,Spring Cloud Config、Alibaba Nacos等有着不同的实现。实现的基础则是SpringApplicationRunListeners 接口。

本篇博客只是介绍Spring Cloud 配置中心的原理,以及实现方式,并不介绍配置中心的使用,后续在介绍Spring Cloud Alibaba时会简单的介绍Alibaba Nacos配置中心的使用。不管怎么说配置中心的实现都是万变不离其宗,包括服务的拉取、推送和更新。而这些又都是结合Spring Boot进行的。上面的两部分代码是核心。

继续阅读