Tip: 此篇已加入.NET Core微服务基础系列文章
一、关于Spring Cloud Config
在分布式系统中,每一个功能模块都能拆分成一个独立的服务,一次请求的完成,可能会调用很多个服务协调来完成,为了方便服务配置文件统一管理,更易于部署、维护,所以就需要分布式配置中心组件了,在Spring Cloud中,就有这么一个分布式配置中心组件 — Spring Cloud Config。
Spring Cloud Config 为分布式系统中的外部配置提供服务器和客户端支持。使用Config Server,我们可以为所有环境中的应用程序管理其外部属性。它非常适合spring应用,也可以使用在其他语言的应用上。随着应用程序通过从开发到测试和生产的部署流程,我们可以管理这些环境之间的配置,并确定应用程序具有迁移时需要运行的一切。服务器存储后端的默认实现使用git,因此它轻松支持标签版本的配置环境,以及可以访问用于管理内容的各种工具。
Spring Cloud Config的原理图大致如下图(此图来自mazen1991)所示:
我们将配置文件放入git或者svn等服务中,通过一个Config Server服务来获取git中的配置数据,而我们需要使用的到配置文件的Config Client系统可以通过Config Server来获取对应的配置。
二、快速构建Config Server
示例版本:Spring Boot 1.5.15.RELEASE,Spring Cloud Edgware.SR3
(1)添加Spring Cloud Config相关依赖包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 1 <dependencies>
2 <dependency>
3 <groupId>org.springframework.boot</groupId>
4 <artifactId>spring-boot-starter</artifactId>
5 </dependency>
6
7 <!-- 热启动,热部署依赖包,为了调试方便,加入此包 -->
8 <dependency>
9 <groupId>org.springframework.boot</groupId>
10 <artifactId>spring-boot-devtools</artifactId>
11 <optional>true</optional>
12 </dependency>
13
14 <!-- spring cloud config -->
15 <dependency>
16 <groupId>org.springframework.cloud</groupId>
17 <artifactId>spring-cloud-config-server</artifactId>
18 </dependency>
19 </dependencies>
20
21 <!-- spring cloud dependencies -->
22 <dependencyManagement>
23 <dependencies>
24 <dependency>
25 <groupId>org.springframework.cloud</groupId>
26 <artifactId>spring-cloud-dependencies</artifactId>
27 <version>Edgware.SR3</version>
28 <type>pom</type>
29 <scope>import</scope>
30 </dependency>
31 </dependencies>
32 </dependencyManagement>
33
(2)启动类添加注解
1
2
3
4
5
6
7
8 1@SpringBootApplication
2@EnableConfigServer
3public class ConfigServiceApplication {
4 public static void main(String[] args) {
5 SpringApplication.run(ConfigServiceApplication.class, args);
6 }
7}
8
(3)Config相关配置项
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 1server:
2 port: 8888
3
4spring:
5 application:
6 name: config-server
7 cloud:
8 config:
9 server:
10 git:
11 # 配置Git仓库地址
12 uri: https://github.com/EdisonChou/Microservice.PoC.Steeltoe
13 # 配置搜索目录
14 search-paths: config
15 # Git仓库账号(如果需要认证)
16 username:
17 # Git仓库密码(如果需要认证)
18 password:
19
1
2
3 1info.profile=default-1.0
2info.remarks=this is a remarks of default profile
3
此外,对于Spring Cloud Config,端点与配置文件的映射规则如下:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
其中,application: 表示微服务的虚拟主机名,即配置的spring.application.name
profile: 表示当前的环境,dev, test or production?
label: 表示git仓库分支,master or relase or others repository name? 默认是master
三、ASP.NET Core中集成Config Server
(1)快速准备一个ASP.NET Core WebAPI项目(示例版本:2.1),这里以上一篇示例代码中的AgentService为例
(2)通过NuGet安装Config相关包:
PM>Install-Package Steeltoe.Extensions.Configuration.ConfigServerCore
(3)改写Program类
1
2
3
4
5
6
7
8
9
10
11
12
13
14 1 public class Program
2 {
3 public static void Main(string[] args)
4 {
5 CreateWebHostBuilder(args).Build().Run();
6 }
7
8 public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
9 WebHost.CreateDefaultBuilder(args)
10 .AddConfigServer() // Add config server via steeltoe
11 .UseUrls("http://*:8010")
12 .UseStartup<Startup>();
13 }
14
(3)改写Starup类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 1 public class Startup
2 {
3 public Startup(IConfiguration configuration)
4 {
5 Configuration = configuration;
6 }
7
8 public IConfiguration Configuration { get; }
9
10 // This method gets called by the runtime. Use this method to add services to the container.
11 public void ConfigureServices(IServiceCollection services)
12 {
13 services.AddOptions();
14 // Add Steeltoe Discovery Client service client
15 services.AddDiscoveryClient(Configuration);
16 // Add Steeltoe Config Client service container
17 services.AddConfiguration(Configuration);
18 services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
19 // Add Configuration POCO
20 services.Configure<ConfigServerData>(Configuration);
21 }
22
23 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
24 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
25 {
26 if (env.IsDevelopment())
27 {
28 app.UseDeveloperExceptionPage();
29 }
30
31 app.UseMvc();
32 // Add Steeltoe Discovery Client service
33 app.UseDiscoveryClient();
34 }
35 }
36
(4)为自定义配置内容封装一个类
1
2
3
4
5
6
7
8
9
10
11 1 public class ConfigServerData
2 {
3 public Info Info { get; set; }
4 }
5
6 public class Info
7 {
8 public string Profile { get; set; }
9 public string Remarks { get; set; }
10 }
11
对应:info.profile 以及 info.remarks
(5)改写Controller,通过依赖注入获取Config内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 1 [Route("api/[controller]")]
2 [ApiController]
3 public class ValuesController : ControllerBase
4 {
5 private IOptionsSnapshot<ConfigServerData> IConfigServerData { get; set; }
6
7 private IConfigurationRoot Config { get; set; }
8
9 public ValuesController(IConfigurationRoot config, IOptionsSnapshot<ConfigServerData> configServerData)
10 {
11 if (configServerData != null)
12 {
13 IConfigServerData = configServerData;
14 }
15
16 Config = config;
17 }
18
19 [HttpGet]
20 [Route("/refresh")]
21 public IActionResult Refresh()
22 {
23 if (Config != null)
24 {
25 Config.Reload();
26 }
27
28 return Ok("Refresh Config Successfully!");
29 }
30
31 // GET api/values
32 [HttpGet]
33 public ActionResult<IEnumerable<string>> Get()
34 {
35 var config = IConfigServerData.Value;
36 return new string[] { $"Profile : {config.Info.Profile}",
37 $"Remarks : {config.Info.Remarks}" };
38 }
39 }
40
这里提供了一个刷新Config的方法Refresh,由于在没有借助消息总线的情况下,Config Server的Config刷新之后不会推送到各个Config Client,因此需要各个Config Client手动Refresh一下,如下图所示:
这里也提一下Spring Cloud Config推荐的刷新配置的方式,即集成Spring Cloud Bus,如下图所示:
从上图中我们可以看出,它将Config Server加入消息总线之中,并使用Config Server的/bus/refersh端点来实现配置的刷新(一个观察者模式的典型应用)。这样,各个微服务只需要关注自身的业务逻辑,而无需再自己手动刷新配置。但是,遗憾的是,Pivotal目前在Steeltoe中还没有为.NET应用程序提供Spring Cloud Bus的集成,不过可以研究其机制,通过消息队列的客户端如RabbitMQ.Client去自己定制响应事件。
四、快速验证
(1)从Config Server中获取sampleservice-foo.properties配置文件
(2)启动AgentService,验证是否能从ConfigServer获取到正确的配置内容
(3)修改配置文件的属性值:info.profile改为default-1.1
(4)验证Config Server是否已经获取到最新的info.profile
(5)手动刷新AgentService的Config对象
(6)验证是否能够获取最新的info.profile
五、小结
本文极简地介绍了一下Spring Cloud Config,并快速构建了一个用于演示的Config Server,然后通过Steeltoe OSS提供的Config客户端将ASP.NET Core与Spring Cloud Config进行集成,最后进行了验证能够正常地从Config Server中获取最新的配置内容。当然,关于Spring Cloud Config的内容还有许多,如果要真正使用Spring Cloud Config还需要考虑如何实现自动刷新的问题。从Spring Cloud Config与Apollo的使用体验上来说,本人是更加喜欢Apollo的,无论是功能的全面性和使用的体验来说,Apollo更胜一筹,而且国内的落地案例也更多。因此,如果项目中需要使用或集成统一配置中心,Apollo会是首选。
示例代码
Click => https://github.com/EdisonChou/Microservice.PoC.Steeltoe/tree/master/src/Chapter3-ConfigServer
参考资料
Steeltoe官方文档:《Steeltoe Doc》
Steeltoe官方示例:https://github.com/SteeltoeOSS/Samples
蟋蟀,《.NET Core 微服务架构 Steeltoe的使用》
周立,《Spring Cloud与Docker 微服务架构实战》
mazhen1991,《使用Spring Cloud Config来统一管理配置文件》
冰与火IAF,《Spring Cloud:分布式配置中心 Config》