现如今我们经常在讨论服务端开发(主要是API服务)的时候谈及“微服务”。微服务设计方法逐渐成为了API开发的新业界标准。几乎所有的组织都在推广它。
在这篇教程当中,我们将探讨并且完成一个叫做配置服务(Config Server)的微服务特性。所有微服务的可配置参数都在配置服务中写入和维护。它更像是将属性/资源文件从项目的代码中统一抽离到一个外部服务,这样的话如果某个属性发生了改变,那么使用它的服务并不需要重新部署。在不重新部署微服务的情况下,所有的属性改变将可以体现出来。
为什么要使用Spring cloud配置服务器
配置服务器的想法来自于12-factor app宣言。这份宣言与开发现代原生云应用的最佳实践指导相关。它建议将属性/资源保存在服务器的环境当中。在这个环境里,这些资源会在服务运行的时候发生变化——不同的配置通常在每个环境当中有所不同。
举个例子,如果一个服务依赖与另一个服务(由于特定业务场景被调用),并且被依赖的服务的URL发生了改变,那么我们必须用新的地址构建和部署我们的服务。但是如果我们现在运用了12 factor app方法,并且从一个运行在不同进程里的外部服务读取配置,我们就只需要刷新配置服务了。
所以,这个想法非常清晰以及有效。现在让我们来看看如何创建配置服务器。
例子中使用到的技术栈
我们将使用基于spring-boot的spring-cloud API,它非常易于使用和流行。在spring framework的命名中,它被称作Config Server。同时我们也会通过git来托管属性文件。
所以我们最终用于这个demo的技术栈是:
- Java 1.8E
- clipse IDE
- Spring cloud
- Spring boot
- Spring Rest
- GitHub as resource repository
- Maven
- REST client
我们首先将开发2个基于spring boot的微服务。
- 一个是提供运行配置的配置服务器
- 一个是使用配置服务器暴露的配置的配置客户端服务
配置服务器——服务器端配置
首先我们通过给定的步骤构建配置服务器部分。
-
生成项目结构
从spring boot初始化程序门户开始,这是创建任何基于Spring Boot的应用的一个特别好的起点。在这里我们只会选用Config Server starter pom。通过使用此配置,只要我们生成项目,就可以下载一个zip文件,然后解压缩后导入eclipse。
-
将项目导入Eclipse
一旦你从spring初始化器门户获得了zip文件,我们需要将它解压缩到我们选择的目录并将其作为maven项目导入eclipse
-
在Eclipse中构建
下一步是选择你喜欢的方式,从命令提示符或eclipse运行mvn clean install。
-
添加Config Server注解
现在打开spring已经提供的Spring Application类,并在类之前添加@EnableConfigServer注解并再次构建项目。在使用这个注解之后,这个artifact将会表现得像一个spring配置服务器。
此类被添加这个注解之后看起来会像下面那样——类名由你生成的项目名决定,当然你也可以手动更改一个你喜欢的名称。
package com.howtodoinjava.example.springconfigserver; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.config.server.EnableConfigServer; @EnableConfigServer @SpringBootApplication public class SpringConfigServerApplication { public static void main(String[] args) { SpringApplication.run(SpringConfigServerApplication.class, args); } } 复制代码
-
创建git仓库
下一个非常重要的步骤是建立一个本地git仓库。它可以很轻松地通过在属性文件里配置URL被替换成远程仓库。我们将放置被配置
服务器微服务
使用的外部属性文件来提供外部属性配置。我们需要跟着下面的步骤来创建一个本地git仓库并且检查样例属性文件。-
首先请确保在你的机器上已经安装了git shell,而且你可以通过命令行运行git bash。可以通过打开命令行,输入git命令来确认。
-
在桌面创建一个目录config-server-repo。
-
然后在config-server-repo目录中创建一个文件
config-server-client.properties
,并在文件中添加内容msg = Hello world - this is from config server
。 -
然后在config-server-repo目录中创建一个文件
config-server-client-development.properties
,并在文件中添加内容msg = Hello world - this is from config server - development environment
。 -
然后在config-server-repo目录中创建一个文件
config-server-client-production.properties
,并在文件中添加内容msg = Hello world - this is from config server - production environment
。 -
在这里我们为不同的环境维护了同样名称的配置,因为我们通常维护不同环境的属性,如urls,credentials,数据库详细信息等。最重要的一点是我们需要在每个属性文件中附加带有环境名称的连字符( - ),以便配置服务器理解它。此外,我们需要使用我们将在此之后创建的配置客户端服务名称命名属性文件。
-
现在从config-server-repo目录打开命令提示符并运行命令git init,使该目录成为git存储库。
-
运行git add。将所有内容添加到仓库中。
-
最后我们需要通过运行命令git commit -m“initial checkin”来提交属性文件。下面是全部命令操作的截图(译者注:你也可以用git bash操作。原作者使用的是windows命令行)。
-
-
从配置服务器指向git仓库
在spring-config-sever项目的
src\main\resources
目录中创建一个名为bootstrap.properties
的文件,并添加以下行。#服务器端 server.port = 8888 #Git 仓库地址。可以替换成你本地git仓库的绝对路径 spring.cloud.config.server.git.uri=${USERPROFILE}\\Desktop\\config-server-repo #关闭Management endpoint的安全检验 management.security.enabled=false #译者注,在springboot的2.x版本当中, #management.security.enabled已经被废弃。 #应该该成以下配置,才可以访问刷新配置的url /actuator/refresh #management.endpoints.web.exposure.include=refresh 复制代码
现在让我们了解这些属性。
server.port
定义嵌入式服务器将启动的端口spring.cloud.config.server.git.uri
将绑定git位置以查找配置。这里我们使用本地git仓库,但只需更改此配置即可切换到远程仓库。management.security.enabled = false
将禁用/env,/refresh等上management endpoint的安全性。这是针对开发设置的,在生产环境当中应该启用安全性。
-
验证服务器端配置
为了确认服务器是否可以识别这些属性,我们首先在项目根目录运行以下命令:
java -jar target\spring-config-server-0.0.1-SNAPSHOT.jar 复制代码
现在打开浏览器并检查下面的Urls,它将返回JSON输出。在
propertySources
部分,我们可以看到我们在属性文件中添加的所有属性内容。这确保配置服务器成功运行,它已识别git的位置,并且正在为不同环境提供配置。此外,我们来看看在项目运行的时候,对属性文件中的任何更改是否在服务器没有重新启动的情况下生效——修改环境属性文件当中的值,将它提交到git仓库,然后通过查看对应环境的endponit(浏览器打开对应的url)来检查配置是否在服务没有重启的情况下生效——这就是配置服务器的魔法。
配置服务器——客户端配置
现在我们将继续进行客户端实现。我们将从一个单独的微服务中获取属性。这是我们的最终目标 - 将配置外部化到不同的服务。
-
创建Maven项目
打开https://start.spring.io/,并使用以下选定的依赖生成客户端项目:
- Actuator
- Config Client
- Web
- Rest Repositories
屏幕将如下所示。像Spring-Config-Server一样,将生成的zip文件解压缩到某个目录并导入eclipse。
-
创建REST资源
首先添加一个RestController以查看响应中的服务器端属性值。为此,打开已生成的@SpringBootApplication类文件,并在该文件的末尾添加一个该类。这非常简单和直接,我们仅仅只是在/message上暴露一个方法,用它返回由配置服务器微服务提供的msg属性值。该配置服务器指向本地git仓库(在生产环境它将会被替换为一个远程git仓库)。
package com.howtodoinjava.example.springconfigclient; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication public class SpringConfigClientApplication { public static void main(String[] args) { SpringApplication.run(SpringConfigClientApplication.class, args); } } @RefreshScope @RestController class MessageRestController { @Value("${msg:Hello world - Config Server is not working..pelase check}") private String msg; @RequestMapping("/msg") String getMsg() { return this.msg; } } 复制代码
-
与配置服务器绑定
在src\main\resources目录中创建一个名为bootstrap.properties的文件,并添加以下属性以及一些必需的配置与配置服务器连接。
spring.application.name=config-server-client #Active Profile配置与环境有关。 #如果它为空,则配置服务器将会使用末尾没有环境变量的配置文件 #如 config-server-client.properties spring.profiles.active=development spring.cloud.config.uri=http://localhost:8888 management.security.enabled=false 复制代码
上述主要的配置与配置服务器的配置意义一致。
Demo
让我们来测试配置服务器应用。
-
构建与运行配置服务器项目
从spring-config-server文件夹打开命令行工具并运行mvn clean install命令。在构建完成之后,运行
java -jar target\spring-config-server-0.0.1-SNAPSHOT.jar
配置服务器将会在本地的8888端口启动。
-
构建与运行配置客户端项目
同样的, 从spring-config-clienet文件夹打开命令行工具并运行mvn clean install命令。在构建完成之后,运行
java -jar target\spring-config-client-0.0.1-SNAPSHOT.jar
配置服务器将会在本地的8080端口启动。
-
测试Rest Endpoint(端点)
现在打开浏览器,通过访问
http://localhost:8080/msg
打开/msg
的rest endpoinit。它将会返回Hello world - this is from config server - Development environment
。它之前出现在config-server-client-development.properties
文件当中。 -
测试属性更改
现在我们将进行属性更改并测试是否可以在配置客户端服务中反映,而无需重新启动任何微服务。
对
config-server-client-development.properties
中的msg
值进行更改然后提交到本地git,接着在浏览器中再次点击http//localhost:8080/msg
,你将仅仅得到旧值。要获得新值,我们需要通过从任意
REST
客户端使用POST
方法访问http://localhost:8080/refresh
端点来刷新配置。一旦配置客户端服务被成功刷新后,新值就应该会出现在服务响应体中。这是因为Rest Controller暴露的@RefreshScope注解。
如果遇到错误需要检查的事项
- 属性文件名与客户端服务名称
spring.application.name=config-server-client
需要保持一致,否则属性将无法被检测到。 - 确保你已经通过使用
git add/commit
命令来提交代码到git仓库。 - 确保你已经调用
POST
方法访问http://localhost:8080/refresh
来刷新配置客户端服务。 - 确保在你启动配置客户端服务的时候,配置服务器服务已经启动。否则由于需要花费一些时间注册客户端服务,有的时候在测试的时候将会产生混乱。
这就是创建配置服务器微服务的全部了。如果你有遇到任何的困难请在这篇文章的评论当中提出,我们会很高兴帮助你解决这些问题。
Happy Learning !!