- 前言
- 第一部分 基础应用开发
- 第 1 章 Spring Boot 入门
- 第 2 章 在 Spring Boot 中使用数据库
- 第 3 章 Spring Boot 界面设计
- 第 4 章 提高数据库访问性能
- 第 5 章 Spring Boot 安全设计
- 第二部分 分布式应用开发
- 第 6 章 Spring Boot SSO
- 第 7 章 使用分布式文件系统
- 第 8 章 云应用开发
- 第 9 章 构建高性能的服务平台
- 第三部分 核心技术源代码分析
- 第 10 章 Spring Boot 自动配置实现原理
- 第 11 章 Spring Boot 数据访问实现原理
- 第 12 章 微服务核心技术实现原理
- 附录 A 安装 Neo4j
- 附录 B 安装 MongoDB
- 附录 C 安装 Redis
- 附录 D 安装 RabbitMQ
- 结束语
8.1 使用配置管理
一个项目工程总是需要一些配置,例如,要配置服务器的端口、访问数据库的参数或其他一些项目需要的参数等。而一个大型的分布式系统可能存在很多这样需要配置的项目工程,这时,配置管理就将是一个庞大的工程,所以弄不好很容易出错。因此对于一个分布式系统来说,迫切需要一个单独的系统来专门管理各个项目的配置。Spring Cloud 的配置管理就是这样的一个工具包。
使用 Spring Cloud 的配置管理开发工具包,只要创建一个简单的工程,就可以实现分布式配置管理服务,它还支持在线更新,即如果更新了配置文件,使用这个配置文件的客户端不用重启就可以使用最新的配置。
8.1.1 创建配置管理服务器
为了给客户端提供配置管理的服务,要创建一个工程,用来构建一个配置管理服务器。首先,在工程的 Maven 管理中引用如代码清单 8-1 所示的依赖配置。
代码清单 8-1 配置管理服务器依赖配置
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency>
然后,创建一个主程序,如代码清单 8-2 所示。这是这个工程中我们创建的唯一一个类,其中注解 @EnableConfigServe 启用了配置管理服务的功能,注解 @Enable-DiscoveryClient 启用了发现服务的客户端功能,表明这是使用发现服务的一个客户端。
代码清单 8-2 配置管理服务器主程序
@SpringBootApplication @EnableConfigServer @EnableDiscoveryClient public class ConfigApplication{ public static void main(String[] args) { SpringApplication.run(ConfigApplication.class, args); } }
这样,就创建了一个配置管理服务器。它能为客户端提供配置文件的管理和更新等服务。
配置管理服务器中使用的文件格式与工程的本地配置文件格式一样,既可以使用“.properties”扩展名,也可以使用“.yml”扩展名。配置文件的存储目前支持使用本地存储、Git 以及 Subversion 等方式。在实例中,将使用 Git 的方式来存取配置文件,这需要在 Git 服务器上创建一个资源库,并将配置文件上传到创建的资源库中。为了方便演示配置管理服务的功能,将配置文件存放在 GitHub 中。如果是实际应用,建议使用自主创建的 Git 服务器。
在配置管理服务器的本地工程配置文件中,进行如代码清单 8-3 所示的设置,其中“uri”指定资源库的位置。
代码清单 8-3 文件资源库配置
spring: cloud: config: server: git: uri: https://github.com/chenfromsz/spring-cloud-config -repo
该资源库包含如下文件,并且为了演示目的,文件中有一些简单的配置内容。要查看配置文件的内容,可以在浏览器中输入如代码清单 8-3 所示的 uri。关于如何使用这些配置文件,将在下一小节中介绍。
Application.yml web.yml web-development.yml data.yml data-development.yml
8.1.2 使用配置管理的客户端
客户端要使用配置管理服务,首先要在工程中的 Maven 依赖管理中加入配置管理组件 spring-cloud-starter-config 的依赖,如代码清单 8-4 所示。使用配置管理服务之后,如果本地的配置文件与配置管理服务器的配置文件有相同的配置项,将优先使用配置管理服务器的配置项,也就是说本地的配置项将会被覆盖。
代码清单 8-4 使用配置管理的客户端依赖配置
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency>
其次,使用配置管理的客户端必须在本地的配置中,事先做好连接配置管理服务器,以及需要使用由配置管理服务器提供的配置文件等参数的设定。
各个使用配置管理的客户端项目中一个名为 bookstrap.yml 的本地配置文件,就是用来设定连接配置管理服务器、应用的名称,以及需要由配置管理服务器提供的配置文件等参数的,如代码清单 8-5 所示。配置中的一些参数解释如下:
uri:设定连接配置管理服务器的地址和端口。
name:用来指定应用的名称和配置文件的名称。
profiles:可以理解为使用配置文件名称的后缀部分。例如这个配置本身,因为 profiles 设定了 development,所以它使用的配置文件将是 web-development.yml 或 web-development.properties。如果不使用 profiles 这个参数,即使用没有文件名后缀部分的配置文件,例如,这个配置将使用 web.yml 或 web.properties 配置文件。
如果在资源库中有 application.yml 或 application.properties 文件,则默认加载。
另外,也可以在 config 参数下面使用 name 和 profiles 来指定配置文件的名称和后缀,即与上面的应用名称分开进行配置。这里使用上面的配置方法。
使用 name 和 profiles 这两个参数,可以设定不同环境使用不同的配置文件,这对于在开发环境中和在生产环境中使用不同的配置文件来说,是很方便的,只要更改 profiles 参数即可。
代码清单 8-5 客户端使用配置管理的设置
spring: application: name: web profiles: active: development cloud: config: uri: http://localhost:8888
设定这些配置参数之后,就可以使用配置管理服务器提供的服务了。可以像下面的程序片段那样,在需要用到配置的地方引用配置文件中的配置项,这个引用假设配置文件中包含 cloud.sample.msg 这个配置。
@Value("${cloud.sample.msg}") String msg; String configValue = environment.getProperty("cloud.sample.msg", "undefined");
注意 对于客户端中的一些启动参数的配置,如应用服务的端口设定、数据库的连接地址、用户和密码等配置是在工程启动时加载,并且中途不能变更,所以这些启动参数虽然可以使用配置管理的配置,但不能使用自动更新功能,这应该是可以理解的。
测试上述一些配置的功能,首先启动实例工程的 config 模块,然后启动 web 模块,这时在它们的控制台上都可以看到加载了下列配置文件:
web-development.yml web.yml application.yml
虽然 web.yml 也被加载了,但是因为只是调用了 web-development.yml,所以只有这个文件的配置内容才会被读取。可以使用一个测试程序来验证一下,如代码清单 8-6 所示,我们设计了一个控制器。控制器提供了一个链接地址“/test”,当访问这个地址时,将从配置文件中读取配置参数“cloud.sample.msg”的值,并做出相应输出,如果读取失败,将取默认值 World。
代码清单 8-6 使用配置管理的测试程序 1
@RestController public class TestController { @Value("${cloud.sample.msg:World}") String msg; @RequestMapping("/test") String test() { return "Hello " + msg + "!"; } }
在浏览器上输入网址 http://localhost:9001/test ,因为在同一台机器上演示,web 项目使用了 9001 的端口。
假如在配置文件 web-development.yml 或 application.yml 中包含“cloud.sample.msg”配置项,就会输出它的值,否则输出:Hello World!现在 web-development.yml 包含如下的内容:
cloud: sample: msg: web-development
即上面浏览器正确的输出结果应该是如下的结果,这正是我们期望得到的输出结果。
Hello web-development!
提示 如果暂时不需要使用配置管理服务器提供的配置,只想使用本地的配置文件,可以只把代码清单 8-4 中的依赖注释掉即可。
8.1.3 实现在线更新
上一小节对配置管理服务器的配置文件的读取,只有在应用启动时才会加载。这显然是不够理想的,能不能在应用不重启的情况下,在线更新配置呢?当然是可以的。要实现在线更新,必须在需要使用更新配置的 Bean 中增加一个注解:@RefreshScope,即将代码清单 8-6 改成代码清单 8-7。
代码清单 8-7 使用配置管理的测试程序 2
@RestController @RefreshScope public class TestController { @Value("${cloud.sample.msg:World}") String msg; @RequestMapping("/test") String test() { return "Hello " + msg + "!"; } }
通过这样更改之后,再来测试一下。启动实例工程的 web 模块之后,再将上面配置文件的内容修改成如下,并提交到 Git 服务器上。
cloud: sample: msg: web-develop
现在刷新上面的浏览器还不能读取到最新的配置,因为在线更新还必须使用一个指令来触发。使用下列的指令才能触发更新,使用这个指令之后,可以在 web 模块的控制台上看到重新加载了配置文件。这时候再刷新浏览器,就可以看到输出了我们期望的结果:Hello web-develop!
curl – X POST http://localhost:9001/refresh
提示 curl 是 UNIX 系统的指令,上面指令需要使用 POST 方式传送,执行上面指令需要有 Linux 类型的系统。如果你的机器是 Windows 系统,也不用担心,如果已经安装了 Git 客户端,打开 Git Bash 窗口,同样也能使用 UNIX 指令。注意上面指令参数的大小写敏感。
8.1.4 更新所有客户端的配置
使用上面的方法,如果有很多应用,就需要一个一个地触发更新配置,相当麻烦。有没有一种方法,可以更新所有使用配置管理的客户端配置呢?使用事件总线 Spring-cloud-bus,就可以在线更新所有连接配置管理服务器的客户端。这样,仅仅使用一条指令就可以更新所有客户端的配置。
因为 spring-cloud-bus 是使用分布式消息发布机制,通过 RabbitMQ 使用消息分发的方法来执行更新的。所以还必须安装 RabbitMQ 服务器,才能实现消息分发。RabbitMQ 服务器的安装可以参照附录 D。
要启用 spring-cloud-bus 的功能,首先在配置管理服务器和所有使用配置管理的客户端的 Maven 依赖管理中,都要增加如代码清单 8-8 所示的依赖配置。
代码清单 8-8 spring-cloud-bus 依赖配置
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency>
其次,在配置管理服务器和所有连接配置管理服务器的客户端的本地配置文件中,增加如代码清单 8-9 所示的配置,即设定连接 RabbitMQ 服务器的 IP、端口、用户名和密码等参数。
代码清单 8-9 连接 RabbitMQ 服务器的配置
spring: rabbitmq: addresses: amqp://192.168.1.214:5672 username: alan password: alan
上面配置假设你已经安装了 RabbitMQ 服务器,安装的 IP 地址为 192.168.1.214,使用默认端口为 5672,增加了一个用户,用户名和密码都为 alan,并且为用户赋予了可以使用消息服务的权限。
通过网址 http://192.168.1.214:15672 使用浏览器打开 RabbitMQ 服务器,并使用管理员用户登录进去,就可以打开 RabbitMQ 服务器的控制台,在这里可以查看连接的客户端和通道等信息,如图 8-1 所示。
图 8-1 RabbitMQ 服务器连接通道情况
现在可以使用下列指令,更新所有在线的使用配置管理的客户端了,假设配置管理服务器的端口为 8888。
curl – X POST http://localhost:8888/bus/refresh
执行指令后,可以在配置管理服务器的控制台中看到它重新加载了一些客户端的配置文件。在连接配置管理服务器的客户端的控制台中同样可以看到重新加载了配置文件。
在本章的实例工程中,可以使用 web 和 data 两个模块来测试这个更新指令。执行指令后,可以看到两个模块的配置文件都被重新加载了,不管配置文件有没有更改。这样其实也就可以证明客户端的配置已经被更新了。如果你还不放心,也可以使用上一小节的测试程序来验证一下,两个模块都有相同的测试程序,即在浏览器中使用“/test”链接来测试。
上面这个指令跟上一小节的更新指令有点不同,主要体现在两点:第一,它必须使用配置管理服务器的地址来执行,第二,它的 URL 中多了一个“bus”。
但是,有时我们并不想一下子就更新所有的客户端,可能只需要更新一个客户端,这时既可以使用上一小节的更新指令,也可以在配置管理服务器中使用指定目标客户端来更新一个客户端的配置。例如,下面的指令指定更新名称为 web 的应用的所有更新,它使用了 destination 参数。
curl -X POST http://localhost:8888/bus/refresh?destination=web:**
上面所有的在线更新都必须要求需要使用更新的 Bean 中包含 @RefreshScope 注解的才能适用,这一点是毋庸置疑的。
关于配置管理的其他一些内容,比如,对配置文件的读取还可以使用安全措施和策略,如设置数字签名、用户名和密码等,可参考官方文档: http://projects.spring.io/spring-cloud/spring-cloud.html#_security_2 。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论