.NET Core微服務之基於Steeltoe使用Spring Cloud Config統一管理配置

weixin_33912246發表於2019-01-08

Tip: 此篇已加入.NET Core微服務基礎系列文章索引

=>  Steeltoe目錄快速導航

1. 基於Steeltoe使用Spring Cloud Eureka

2. 基於Steeltoe使用Spring Cloud Zuul

3. 基於Steeltoe使用Spring Cloud Hystrix

4. 基於Steeltoe使用Spring Cloud Config

5. 基於Steeltoe使用Zipkin

一、關於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,然後提交到github倉庫

  

  (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

 

相關文章