天天看點

ASP.NET Core微服務之基于Steeltoe使用Spring Cloud Config統一管理配置一、關于Spring Cloud Config二、快速建構Config Server三、ASP.NET Core中內建Config Server四、快速驗證五、小結示例代碼參考資料

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相關依賴包

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!-- 熱啟動,熱部署依賴包,為了調試友善,加入此包 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- spring cloud config -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
    </dependencies>

    <!-- spring cloud dependencies -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Edgware.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>           

  (2)啟動類添加注解

@SpringBootApplication
@EnableConfigServer
public class ConfigServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServiceApplication.class, args);
    }
}           

  (3)Config相關配置項

server:
  port: 8888

spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          # 配置Git倉庫位址
          uri: https://github.com/EdisonChou/Microservice.PoC.Steeltoe
          # 配置搜尋目錄
          search-paths: config
          # Git倉庫賬号(如果需要認證)
          username:
          # Git倉庫密碼(如果需要認證)
          password:           

  這裡我在GitHub中(

https://github.com/EdisonChou/Microservice.PoC.Steeltoe/config

目錄中)放了一個sample-service-foo.properties的配置檔案,裡面隻有兩行内容:

info.profile=default-1.0
info.remarks=this is a remarks of default profile           

  此外,對于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類

public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .AddConfigServer()  // Add config server via steeltoe
                .UseUrls("http://*:8010")
                .UseStartup<Startup>();
    }           

  (3)改寫Starup類

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddOptions();
            // Add Steeltoe Discovery Client service client
            services.AddDiscoveryClient(Configuration);
            // Add Steeltoe Config Client service container
            services.AddConfiguration(Configuration);
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            // Add Configuration POCO 
            services.Configure<ConfigServerData>(Configuration);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMvc();
            // Add Steeltoe Discovery Client service
            app.UseDiscoveryClient();
        }
    }           

  (4)為自定義配置内容封裝一個類

public class ConfigServerData
    {
        public Info Info { get; set; }
    }

    public class Info
    {
        public string Profile { get; set; }
        public string Remarks { get; set; }
    }           

  對應:info.profile 以及 info.remarks

  (5)改寫Controller,通過依賴注入擷取Config内容

[Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        private IOptionsSnapshot<ConfigServerData> IConfigServerData { get; set; }

        private IConfigurationRoot Config { get; set; }

        public ValuesController(IConfigurationRoot config, IOptionsSnapshot<ConfigServerData> configServerData)
        {
            if (configServerData != null)
            {
                IConfigServerData = configServerData;
            }

            Config = config;
        }

        [HttpGet]
        [Route("/refresh")]
        public IActionResult Refresh()
        {
            if (Config != null)
            {
                Config.Reload();
            }

            return Ok("Refresh Config Successfully!");
        }

        // GET api/values
        [HttpGet]
        public ActionResult<IEnumerable<string>> Get()
        {
            var config = IConfigServerData.Value;
            return new string[] { $"Profile : {config.Info.Profile}",
                $"Remarks : {config.Info.Remarks}" };
        }
    }           

  這裡提供了一個重新整理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