.Net Core with 微服務 – Consul 配置中心

上一次我們介紹了Elastic APM組件。這一次我們繼續介紹微服務相關組件配置中心的使用方法。本來打算介紹下攜程開源的重型配置中心框架 apollo 但是體系實在是太過於龐大,還是讓我愛不起來。因為前面我們已經介紹了使用Consul 做為服務註冊發現的組件,那麼乾脆繼續使用 Consul 來作為配置中心吧。Consul 除了服務註冊發現功能,還有個 Key/Value 存儲的功能,我們把本地的 appsettings.json 文件的內容搬到 Key/Value 上就可以實現配置中心了。

把服務的配置遷移至 Consul

讓我們來改造一下前面系列文章里的 member_center 項目,把配置文件都遷移到 consul 上面去。

在 consul 控制台點擊 「Key/Value」 菜單,點擊 「create」 按鈕新建一個 Key/Value 對象。

Key/Value 支援按文件夾分類,當我們的 Key 以 / 結尾的時候,consul 會認為這是一個文件夾。
我們在這裡輸入 「member_center/」 在創建文件夾。

在創建的文件夾目錄下繼續點擊 「create」 按鈕。

在 key 文本框里輸入 「confing.json」 。
在 Value 文本框內把原來 appsettings.json 文件的全部內容複製粘貼進去。

{
  "consul_server": "//192.168.18.164:8500"
}

把原來 appsettings.json 文件的內容全部刪除,只輸入一行 consul_server 的配置,用來指示 consul 服務的地址。

Install-Package Winton.Extensions.Configuration.Consul 

在 member_center 項目上通過nuget安裝 Winton.Extensions.Configuration.Consul 這個組件。

    public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.ConfigureAppConfiguration((ctx,cfg)=> {
                        var localconfig = new ConfigurationBuilder()
                                    .SetBasePath(Directory.GetCurrentDirectory())
                                    .AddJsonFile("appsettings.json").AddEnvironmentVariables().Build();
                        var consul_server = localconfig["consul_server"];

                        cfg.AddConsul("member_center/config.json",op=> {
                            op.ConsulConfigurationOptions = cco =>
                            {
                                cco.Address = new Uri(consul_server);
                            };
                            op.ReloadOnChange = true;
                        });
                    });
                    webBuilder.ConfigureKestrel(options =>
                    {
                        options.ListenAnyIP(6002);
                    });
                    webBuilder.UseStartup<Startup>();
                });

在 program 文件的 CreateHostBuilder 方法內配置使用 Consul 做為配置的提供源。首先從本地讀取 consul_server 的地址。通過 AddConsul 方法指示需要從 consul 讀取的配置文件的路徑。完成以上操作後我們的服務已經可以讀取到 Consul 存儲的配置了。

   [ApiController]
    [Route("[controller]")]
    public class ConsulController : ControllerBase
    {
        IConfiguration _configuration;
        public ConsulController(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        [HttpGet("getConfig")]
        public string GetConfig(string key)
        {
            return _configuration[key];
        }
    }

我們新建一個GetConfig方法來演示下能否讀取到配置。
直接在 Controller 構造函數注入 IConfiguration 來讀取配置,這跟我們普通本地配置的讀取方式完全一致。

//localhost:6002/consul/getconfig?key=hotreload_test



在瀏覽器上訪問一下這個action對應的url,並且指定一個key=hotreload_test,可以看到輸出的結果跟我們在 consul 上配置的值是一致的。


修改一下 consul 上面的配置值,重新讀取一下這個配置,可以看到新的值已經被讀取到了,證明我們的熱更新也可以運行了。

把 Ocelot 網關的配置遷移至 Consul

上面我們演示了如何把普通服務的配置遷移至 consul,下面演示下如何把 Ocelot 的配置遷移到 Consul 上。
Ocelot 網站其實也就是一個 webapi 項目,本質上跟上面的服務沒啥區別。我們根據上面的演示,其實可以很容易的把 Ocelot 項目的配置遷移到 Consul 上。那麼為什麼需要單獨說一下 Ocelot 網關的遷移呢?
本來 Ocelot 的路由配置需要把下游服務的地址跟埠在配置文件里寫死,那樣的話,我們的 Consul 服務註冊發現就沒有意義了,我們的下游服務都是可能動態變化的。所以我們需要讓 Ocelot 結合 Consul 的服務註冊發現功能來把下游伺服器的配置動態化。這就導致 Ocelot 項目跟 Consul 的融合會比一般的服務複雜一點。

Install-Package Ocelot.Provider.Consul

首先我們在項目上使用 nuget 安裝 Ocelot.Provider.Consul 這個組件。

{
  "consul_server": "//192.168.18.164:8500"
}

同樣我們需要在本地的 appsettings.json 文件內指定 consul_server 的地址。再把 routes.json 文件的內容全部遷移至 consul 的 key/value 上去,這個不在贅述。

注意,這裡不是簡單的複製粘貼 routes.json 文件的內容。
我們需要把原來的 DownstreamHostAndPorts 配置全部刪掉,替換成服務名,並且指定負載均衡的演算法。

"ServierName" : "hotel_base",
"LoadBalanceOptions": {
    "Type": "LeastConnection"
}

在 “GlobalConfiguration” 節點指定 “ServiceDiscoveryProvider”:

"ServiceDiscoveryProvider": {
    "Scheme": "http",
    "Host": "192.168.18.164",
    "Prot": 8500,
    "Type": "Consul"
}

ServiceDiscoveryProvider 節點指示了使用 Consul 做為服務發現的組件及Consul服務的基本資訊。

        public static void Main(string[] args)
        {
            new WebHostBuilder()
              .UseKestrel()
              .UseContentRoot(Directory.GetCurrentDirectory())
              .ConfigureAppConfiguration((hostingContext, config) =>
              {
                  var localconfig = new ConfigurationBuilder()
                                .SetBasePath(Directory.GetCurrentDirectory())
                                .AddJsonFile("appsettings.json").AddEnvironmentVariables().Build();
                  var consul_server = localconfig["consul_server"];

                  config.AddConsul("gateway/routes.json", op => {
                      op.ConsulConfigurationOptions = cco =>
                      {
                          cco.Address = new Uri(consul_server);
                      };
                      op.ReloadOnChange = true;
                  });

                  config.AddEnvironmentVariables();
              })
              .ConfigureServices(s => {
                  s.AddOcelot()
                  .AddConsul()
                  .AddTransientDefinedAggregator<HotelDetailInfoForMobileAggregator>();
              })
              .ConfigureLogging((hostingContext, logging) =>
              {
                  logging.AddConsole();
               })
              .UseIISIntegration()
              .Configure(app =>
              {
                  app.UseOcelot().Wait();
              })
              .Build()
              .Run();
        }

我們改造一下 program 文件的 main 方法,在ConfigureAppConfiguration的配置方法內首先獲取 consul_server 的地址。通過AddConsul方法指示獲取配置文件的地址。
以上跟服務的配置遷移都是一致的,除了以上操作使用 Consul 作為 ServiceDiscoveryProvider 還需要在 ConfigureServices 方法的配置函數內指定 consul 相關的依賴注入。

   s.AddOcelot()
    .AddConsul()


我們運行起來所有的服務跟網關項目,訪問一下 /api/hotel 這個路由,可以看到請求被正確的轉發到了對應的服務上了。

總結

以上我們演示了如何把服務的配置遷移到 Consul 的 Key/Value 對象上並且實現了配置的讀取及熱更新。演示了 Ocelot 網關的路由配置如何遷移到 Consul 的 Key/Value 對象上並且不再寫死下游服務的配置資訊,而是使用 Consul 的服務發現能力動態獲取下游服務的配置資訊。通過以上演示我們可以發現整個過程還是非常簡單易用的,雖然 Consul 做為配置中心功能相對於 apollo 等功能還不夠強大,比如沒有版本管理,用戶許可權,審計等功能,但是對於一些小的微服務項目也已經足夠了。如果你的微服務體系中使用了 Consul 做為服務註冊發現的組件,那麼可以直接使用 Consul 來做為配置中心,這樣在能夠獲得基本的配置中心能力同時也省去了再部署一套單獨的配置中心的繁瑣操作。

廣告時間

如果你覺得 Consul 的配置中心功能過於簡單,那麼還可以試試由本人開源的 AgileConfig 輕量級配置中心項目。它部署簡單,使用簡單,支援配置管理,熱更新,版本管理,基本的用戶許可權管理等功能,歡迎試用。
項目地址: //github.com/kklldog/AgileConfig

演示項目地址

//github.com/kklldog/myhotel_microservice

相關文章

NET Core with 微服務 – 什麼是微服務
.Net Core with 微服務 – 架構圖
.Net Core with 微服務 – Ocelot 網關
.Net Core with 微服務 – Consul 註冊中心
.Net Core with 微服務 – Seq 日誌聚合
.Net Core with 微服務 – Elastic APM

關注我的公眾號一起玩轉技術