2. 配置中心

配置中心将配置从各应用中剥离出来,对配置进行统一管理,应用自身不需要自己去管理配置。

微服务系统配置域名 微服务的配置中心_微服务系统配置域名

配置中心的服务流程如下:

1、用户在配置中心更新配置信息。

2、服务A和服务B及时得到配置更新通知,从配置中心获取配置。

总得来说,配置中心就是一种统一管理各种应用配置的基础服务组件。

在系统架构中,配置中心是整个微服务基础架构体系中的一个组件,它的功能看上去并不起眼,无非就是配置的管理和存取,但它是整个微服务架构中不可或缺的一环。

总结一下,在传统巨型单体应用纷纷转向细粒度微服务架构的历史进程中,配置中心是微服务化不可缺少的一个系 统组件,在这种背景下中心化的配置服务即配置中心应运而生,一个合格的配置中心需要满足如下特性:

  • 配置项容易读取和修改
  • 分布式环境下应用配置的可管理性,即提供远程管理配置的能力
  • 支持对配置的修改的检视以把控风险
  • 可以查看配置修改的历史记录
  • 不同部署环境下应用配置的隔离性

2.1 主流配置中心对比

目前市面上用的比较多的配置中心有:Spring Cloud Config、Apollo、Nacos和Disconf等。 由于Disconf不再维护,下面主要对比一下Spring Cloud Confifig、Apollo和Nacos。

对比项

Spring Cloud Config

Apollo

Nacos

配置实时推送

支持(Spring Cloud Bus)

支持(HTTP长轮询1s内)

支持(HTTP长轮询1s内)

版本管理

支持(Git)

支持

支持

配置回滚

支持(Git)

支持

支持

灰度发布

支持

支持

支持

权限管理

支持(依赖Git)

支持

不支持

多集群

支持

支持

支持

多环境

支持

支持

支持

监听查询

支持

支持

支持

多语言

只支持java

主流语言,提供了Open API

主流语言,提供了Open API

配置格式校验

不支持

支持

支持

单机读(QPS)

7(限流所致)

9000

15000

单机写(QPS)

5(限流所致)

1100

1800

3节点读 (QPS)

21(限流所致)

27000

45000

3节点写(QPS)

5(限流所致)

3300

5600

从配置中心角度来看:

  • 性能方面Nacos的读写性能最高,Apollo次之,Spring Cloud Config依赖Git场景不适合开放的大规模自动化运维API。
  • 功能方面Apollo最为完善,nacos具有Apollo大部分配置管理功能,而Spring Cloud Config不带运维管理界面,需要自行开发。
  • Nacos的一大优势是整合了注册中心、配置中心功能,部署和操作相比 Apollo都要直观简单,因此它简化了架构复杂度,并减轻运维及部署工作。

综合来看,Nacos的特点和优势还是比较明显的,下面我们一起进入Nacos的世界。 Nacos除了可以做注册中心,同样可以做配置管理来使用。

2.2 Nacos 统一配置管理

微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务,由于每个服务都需要必要的配置信息才能运行, 当微服务部署的实例越来越多,达到数十、数百时,逐个修改微服务配置就会让人抓狂,而且很容易出错。所以一套集中式的、动态的配置管理是必不可少的。

微服务系统配置域名 微服务的配置中心_spring cloud_02

Nacos一方面可以将配置集中管理,另一方可以在配置变更时,及时通知微服务,实现配置的热更新。

2.2.1 在nacos中添加配置文件

到我们的nacos管理页面的配置管理界面来添加配置文件:

微服务系统配置域名 微服务的配置中心_微服务_03

然后在弹出的表单中,填写配置信息:

微服务系统配置域名 微服务的配置中心_java_04


注意:

项目的核心配置,需要热更新的配置才有放到nacos管理的必要。基本不会变更的一些配置还是保存在微服务本地比较好。

2.2.2 从微服务拉取配置

微服务要拉取nacos中管理的配置,并且与本地的application.yml配置合并,才能完成项目启动。

但如果尚未读取application.yml,又如何得知nacos地址呢?

因此spring引入了一种新的配置文件:bootstrap.yaml文件,会在application.yml之前被读取,流程如下:

微服务系统配置域名 微服务的配置中心_spring cloud_05

步骤:

1)引入nacos-config依赖

首先,在shop-order服务中,引入nacos-config的客户端依赖:

<!--nacos-config-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

2)添加bootstrap.yaml

然后,在user-service中添加一个bootstrap.yaml文件,内容如下:

spring:
  application:
    name: orderservice # 服务名称
  profiles:
    active: dev #开发环境,这里是dev 
  cloud:
    nacos:
      server-addr: localhost:8848 # Nacos地址
      config:
        file-extension: yml # 文件后缀名

这里会根据spring.cloud.nacos.server-addr获取nacos地址,再根据

${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}作为文件id,来读取配置。

本例中,就是去读取orderservice-dev.yml

启动shop-order,我们可以从控制台查看日志发现,它已经从nacos读取配置文件了:

2022-10-01 08:37:39.523  INFO 29664 --- [           main] b.c.PropertySourceBootstrapConfiguration : Located property source: [BootstrapPropertySource {name='bootstrapProperties-orderservice-dev.yml,DEFAULT_GROUP'}, BootstrapPropertySource {name='bootstrapProperties-orderservice.yml,DEFAULT_GROUP'}, BootstrapPropertySource {name='bootstrapProperties-orderservice,DEFAULT_GROUP'}]
2022-10-01 08:37:39.523  INFO 29664 --- [           main] com.suke.shop.order.OrderApplication     : The following profiles are active: dev
2022-10-01 08:37:40.375  INFO 29664 --- [           main] o.s.cloud.context.scope.GenericScope     : BeanFactory id=db95bdfc-3380-37b0-be7b-eab77e21a2be

我们访问服务,也正常访问

2.3 配置热更新

我们最终的目的,是修改nacos中的配置后,微服务中无需重启即可让配置生效,也就是配置热更新

要实现配置热更新,可以使用两种方式:

2.3.1.方式一

在@Value注入的变量所在类上添加注解@RefreshScope,并且对应的@Bean需要添加@RefreshScope

import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;

@SpringBootConfiguration
@RefreshScope
public class DataSourceConfig {
    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;
    @Value("${spring.datasource.url}")
    private String url;
    @Value("${spring.datasource.username}")
    private String username;
    @Value("${spring.datasource.password}")
    private String password;

    @Bean
    @RefreshScope
    public DataSource getDataSource(){
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setJdbcUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
}
2.3.2 方式二

使用@ConfigurationProperties注解代替@Value注解。

在shop-order服务中,在DataSourceConfig类添加@ConfigurationProperties注解:

student: 
 name: lisi
 age: 21
 sex: 男
@Data
@ConfigurationProperties(prefix = "student")
@Component
public class Student {
    private String name;
    private Integer age;
    private String sex;
}
@GetMapping("/student")
public Student getStudent(){
    return student;
}

微服务系统配置域名 微服务的配置中心_spring_06

当我们把name修改为zhangsan,age修改为22,再访问

微服务系统配置域名 微服务的配置中心_微服务_07

此时,我们发现数据以及热更新了

2.4 配置共享

其实微服务启动时,会去nacos读取多个配置文件,例如:

  • [spring.application.name]-[spring.profiles.active].yaml,例如:orderservice-dev.yaml
  • [spring.application.name].yaml,例如:orderservice.yaml

[spring.application.name].yaml不包含环境,因此可以被多个环境共享。

下面我们通过案例来测试配置共享

2.4.1 添加一个环境共享配置

我们在nacos中添加一个orderservice.yaml文件:

微服务系统配置域名 微服务的配置中心_微服务系统配置域名_08

2.4.2 在Student类中读取共享配置

微服务系统配置域名 微服务的配置中心_java_09

2.4.3 运行shop-order,使用不同的profile

微服务系统配置域名 微服务的配置中心_spring cloud_10

请求controller,我们发现student的id有值:

微服务系统配置域名 微服务的配置中心_微服务_11

这说明我们的orderservice.yml文件已被共享了

注意:

当nacos、服务本地同时出现相同属性时,优先级有高低之分:

微服务系统配置域名 微服务的配置中心_微服务系统配置域名_12