menu icer's blog
more_vert
chevron_right 首页 » Spring Cloud » 正文
第4章 微服务太多,配置文件怎么维护
2020-04-25 | Spring Cloud | 暂无评论 | 227 次阅读 | 2111字

在前面有提到,微服务系统是一种典型的分布式系统,我们会将每个功能都尽可能地拆分一个可独立部署、运行的服务,服务部署完成后,每一次请求的完成,都可能涉及到多个服务的协调作业,面对越来越多的微服务,我们需要有一个东西可以方便地管理配置文件、最好可以在一个地方管理所有微服务的配置,这个就是我们接下来要说的分布式配置组件了。在接下来的内容中,简称这个分布式配置组件为配置中心。

4.1 初识分布式配置

在开始介绍Spring Cloud的配置中心实现之前,我们可以先回忆下以前我们的系统配置是怎么做的。

最开始学习的时候,很多东西都是没有配置的,基本上都是硬编码,简单、快速,系统很快构建起来了,可是随着系统的功能越来越复杂,代码量越来越大,很多地方进行硬编码已经不能满足我们的需求,我们需要在不同的环境、不同的场景下通过修改配置项来达到不一样的效果,配置项放在代码里面难找,而且修改起来会很麻烦。

于是,我们将可能频繁变动的项目提出来放在了xml、properties文件中,方便修改,这个时候修改配置的时候已经不需要再去碰业务代码,只要找到对应的配置文件,修改、打包、重新部署就可以了。这样子看起来已经不错了,但是随着分布式架构逐渐流行,一个一个的集群被搭建起来,这个时候再给每个集群实例搭配一个配置文件,维护的工作量就变得很大了。

这种情况运维人员一般都有一个config list,记录了每个实例的配置文件放在哪里、叫什么名字、现在的配置项是什么等等。这个清单如果维护出错,对整个系统来说都会是一个灾难。基于这种情况,分布式系统需要一个中心化的配置中心来替代这个config list,并且可以方便地从不同维度来进行配置,最好支持配置项的随时,并且最好能够实时生效。

4.2 Spring Cloud Config

Spring Cloud作为一个完善的微服务框架,提供了Spring Cloud Config作为推荐的分布式配置组件。

Spring Cloud Config提供了服务端和客户端,可以很好地支持分布式系统的配置需求。使用服务端可以快速构建一个独立于业务服务之外的配置中心,配置存储默认使用git,因此它拥有git所拥有的一切优点。同时,它还原生支持使用Spring的Environment和PropertySource来获取配置项。接下来,我们将使用Spring Cloud Config构建一个配置中心。

4.2.1 Config Server

新建Spring Boot工程,引入Spring Cloud Config的服务端maven依赖,为了方便测试,我们同时引入了web和actuator的相关依赖。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>        

pom文件编写完成后,在application.properties中添加配置信息如下:

spring.application.name=config-server
server.port=8888

# 配置git仓库地址
# 这个地址是本书代码所在git仓库地址,这里用到了仓库中的book-config-repo目录
spring.cloud.config.server.git.uri=https://github.com/hanbin/book

# 配置仓库路径
spring.cloud.config.server.git.search-paths=book-config-repo

# 去掉git权限校验
spring.cloud.config.server.git.skip-ssl-validation=true

# 制定远程仓库中配置文件的customer name
spring.config.name=customer

最后,在启动类中添加@EnableConfigServer注解开启Spring Cloud Config的服务端功能,然后启动即可。

我们在book-config-repo目录下新建了配置文件:customer-dev.properties文件。我们可以通过customer-server服务提供的接口来访问这个配置文件。

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties

举例来说,customer-dev.properties中的就是{application}-{profile}.properties的形式,customer即是应用名,profile通常用来标示不同的环境,label在使用git存储时代表的是git的分支,不写则默认为master。

上面这些URI都可以获取到远程配置,可以看到使用上面格式的地址访问可以看到如下内容:

http://localhost:8888/customer/dev
http://localhost:8888/customer/dev/master

通过上面两个链接可以得到下面的结果:

{
    "name": "customer",
    "profiles": [
        "dev"
    ],
    "label": "master",
    "version": "97ffd82376b9ba87c5a1ffcf60b67eb4866f2415",
    "state": null,
    "propertySources": [
        {
            "name": "https://github.com/hanbin/book/book-config-repo/customer-dev.properties",
            "source": {
                "name": "icer123",
                "age": "1001"
            }
        }
    ]
}

通过其他格式接口可以直接获取到的结果都是:

age: 1001
name: icer123

age和name就是我们需要的配置项。

构建完成配置中心后,接下来我们看看如何将微服务构建成为“配置中心客户端”,来获取配置中心的配置项。

4.2.2 Config Client

前面我们创建了customer服务,这节我们会将customer服务作为config-server的client,通过远程获取的方式拿到customer-dev.properties中的配置项。

在开始之前,这里要提到一个新的endpoint:env。env端点主要用来显示服务的配置信息。在Spring
Boot2中,env端点默认是关闭的。通过添加下面的代码到application.properties中,可以让env端点能够被访问。

management.endpoints.web.exposure.include=health,info,env

在浏览器中可以看到如图4.1所示的页面。

641684178b7634a02b7f30b7bc56d276.png

图4.1 通过浏览器查看env端点

为customer工程添加Spring Cloud Config的支持,需要在pom.xml文件中添加下面的代码。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

启动项目,可以在启动日志中看到如图4.2所示的内容。

846577e69b6587ce46c18004ff2dc0b8.png

图4.2 微服务启动过程中加载远程配置中心

可以看到,添加了Spring Cloud Config的依赖后,项目在启动过程中会默认向http://localhost:8888请求远程配置,附带的参数name为项目的spring.application.name,profiles为default,label为null。

这里的默认配置不能拿到任何信息,因为profiles传的不对,在customer工程的application.properties配置文件中添加。

spring.cloud.config.uri=http://localhost:8888
spring.cloud.config.name=customer
spring.cloud.config.profile=dev

重新启动程序,可以看到如图4.3所示的启动日志。

4491973b4ead19f163bd1bfb6a1a4dc0.png

图4.3 自定义config配置后的启动日志

通过图4.4可以看到现在customer在启动时读取到了之前我们在config server中的配置文件customer-dev.properties。通过本节最开始打开的env端点可以查看,如图4.4所示。

8e52df65dd190ec80c6f15e520922c12.png

图4.4 微服务成功读取到远程配置文件

这里有两个配置文件需要注意下:spring.application.name 和 spring.cloud.config.name。

spring.application.name一般配置的是微服务的实例名,这个名字是微服务之间调用时候的唯一名称。spring.cloud.config.name配置的是Spring Cloud Config中涉及的application名称,在本节的例子中,对应的就是customer。如果去掉spring.cloud.config.name这个配置项,Spring Cloud Config会使用spring.application.name的配置去配置中心取值。

注意:充分使用label,profile可以完美达到一套代码部署在多个环境,仅通过在启动参数中修改label和profile就将各个环境进行区分的目的。

4.2.3 配置刷新

前面讲的都是在系统启动之前添加配置,那么在系统运行过程中,能否“热刷新”,让配置项在运行期可以被直接改动。

Spring Cloud Config是支持“热刷新”的,这里需要用到refresh端点。

还是以customer工程为例。为了方便测试,我们将application.properties中的:

management.endpoints.web.exposure.include=health,info,env

换成:

management.endpoints.web.exposure.include=*

这样,customer的所有端口就已经全部被放开了。

我们新建UserController.java文件,文件内容如下:

package cn.com.hanbinit.customer.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RefreshScope
@RestController
public class UserController {

    @Value("${name}")
    private String name;

    @Value("${age}")
    private Long age;

    @GetMapping("/showinfo")
    public String showNameAndAge(){
        return "name: " + name + ", age: " + age;
    }

}

上面代码中@RefreshScope注解是实现变量热加载的必需配置。@Value可以获取到配置文件以及环境变量中的配置。上面代码中的name和age就分别对应了配置文件中的name和age。showinfo接口返回了@Value获取到的属性值。

启动项目,访问http://localhost:8001/showinfo接口,可以看到如图4.5的返回。

d4a174c877b5bef20aaf8eb13bb616ce.png

图4.5 通过showinfo接口打印配置项的值

接下来,我们将customer-dev.properties
中的icer改为icer123,100改为1001,push到远程仓库。通过postman工具调用refresh端点,如图4.6所示。

b6fba1211bc103b8f825fe5c5145a615.png

图4.6 调用refresh端点,刷新name和age的值

这个时候,刷新showinfo的调用页面,可以看到如图4.7的结果。

2065ef7bfa4766cb94adf439d183f06e.png

图4.7 调用refresh端点后showinfo接口的返回

这里,就说明我们的热加载已经成功。

注意:这种刷新方式仅适用于非初始化对象的情况下,如果配置项需要在系统启动的时候加载并且使用。那么在这里使用refresh端点是不会生效的。配置项即使刷新过去,但是确没有能真正生效。

截止到这里,我们已经可以通过Spring Cloud Config搭建远程的配置中心,并且可以让微服务获取到配置中心的配置项,且可以通过refresh端点达到热加载的目的。那么能不能实现自动刷新呢?手动调用refresh端点还是比较麻烦的。自动刷新当然是可以的,自动刷新后面有机会再写。

4.3 小结

本章我们使用Spring Cloud Config创建了配置中心,并对之前的customer微服务进行了改造,让customer服务可以远程获取到配置中心的配置。

文章目录

相关文章


第9章 整合前端
第8章 离不开的数据库
第7章 熔断、限流、降级
第6章 微服务的大门谁来守
第5章 微服务之间如何交互
第3章 微服务太多,谁来管理
第2章 构建单个微服务
第1章 微服务初体验

发表评论
暂无评论
textsms
account_circle
email
link