1. 程式人生 > >.NET Core微服務實施之Consul服務發現與治理

.NET Core微服務實施之Consul服務發現與治理

.post ddr 檢查 dns gui seconds cal heal nvi

原文:.NET Core微服務實施之Consul服務發現與治理

技術分享圖片

Consul官網:https://www.consul.io

Consul下載地址:https://www.consul.io/downloads.html

Consul nuget 命令:Install-Package Consul

  我的理解是,Consul是一個服務管理者,系統中所有使用到的服務他都幫你管理好,促銷高峰需要新增服務的時候,服務開啟來就自動註冊到Consul中,服務下線關閉,也自動從Consul註銷,無縫銜接,對於使用者來說,你只需要跟Consul說我要某某某服務,Consul就會返回當前在Consul上註冊的可用的服務給回你,你也無需像以前那樣將服務的地址配置在系統當中,就好像DNS服務器那樣,你輸入域名,DNS服務器返回其中一個IP地址給你,然後你就可以正常訪問, 另外在集群環境下選擇服務的策略交給調用方,你可以選擇隨機、輪詢、權重等方式,具體視乎你的需求。

一、Windows系統啟動Consul

這裏以Windows系統進行演示,實際項目中可以搭建在Linux上,下載到本地之後解壓,使用命令行模式進入到Consul目錄,輸入命令啟動Consul服務:

consul.exe agent -dev

技術分享圖片

啟動Consul成功,命令行信息中顯示,可以使用地址: http://127.0.0.1:8500 打開UI管理界面進行查看管理操作。

技術分享圖片

技術分享圖片

二、.NET Core+Consul 演示

1、新建一個ASP.NET Core Web 應用程序,nuget安裝Consul:Install-Package Consul

2、增加用於Consul健康監測的Controller,這裏就是一個簡單的Controller、Action,能正常被訪問即可。

namespace MsgService.Controllers
{
    [Produces("application/json")]
    [Route("api/Health")]
    public class HealthController : Controller
    {
        [HttpGet]
        public IActionResult Get()
        {
            Console.WriteLine("健康檢查" + DateTime.Now);
            return Content("
ok"); } } }

3、修改應用程序站點的Startup類 ,在函數Configure 中增加多一個參數 IApplicationLifetime appLifeTime,然後在Configure函數中增加註冊、註銷的代碼,這段代碼的意思是,當應用程序站點啟動或者註銷的時候,就會對Consul進行消息通知。這裏ConsulConfig方法裏寫死了我本機運行的Consul地址:http://127.0.0.1:8500,實際項目中肯定是要做成配置的。

    //Consul 新增 IApplicationLifetime appLifeTime參數
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifeTime)
    {
            //註冊Consul 
            string ip = Configuration["ip"];
            string port = Configuration["port"];
            string serviceName = "MsgService";
            string serviceId = serviceName + Guid.NewGuid();
            using (var consulClient = new ConsulClient(ConsulConfig))
            {
                AgentServiceRegistration asr = new AgentServiceRegistration
                {
                    Address = ip,
                    Port = Convert.ToInt32(port),
                    ID = serviceId,
                    Name = serviceName,
                    Check = new AgentServiceCheck
                    {
                        DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
                        HTTP = $"http://{ip}:{port}/api/Health",
                        Interval = TimeSpan.FromSeconds(10),
                        Timeout = TimeSpan.FromSeconds(5),
                    },
                };
                consulClient.Agent.ServiceRegister(asr).Wait();
            }
 
            //註銷Consul 
            appLifeTime.ApplicationStopped.Register(() =>
            {
                using (var consulClient = new ConsulClient(ConsulConfig))
                {
                    Console.WriteLine("應用退出,開始從consul註銷");
                    consulClient.Agent.ServiceDeregister(serviceId).Wait();
                }
            });
        }
       
       //Consul 配置委托
        private void ConsulConfig(ConsulClientConfiguration config)
        {
            config.Address = new Uri("http://127.0.0.1:8500"); //Demo硬編碼Consul的地址
            config.Datacenter = "dc1";
        }

4、修改應用程序站點的Program.BuildWebHost 方法,目的是方便我們在web應用程序bin目錄下以指定的IP地址、指定的端口啟動服務

        /// <summary>
        /// 設置NetCore監聽端口取命令行中的參數
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public static IWebHost BuildWebHost(string[] args)
        {
            var config = new ConfigurationBuilder()
             .AddCommandLine(args)
             .Build();
            string ip = config["ip"];
            string port = config["port"];
            Console.WriteLine($"ip={ip},port={port}");
            return WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .UseUrls($"http://{ip}:{port}")
            .Build();
        }

5、啟動服務

打開應用程序目錄定位在bin目錄下,使用命令行模式輸入命令,以指定的IP、指定的端口啟動服務, 一切正常的話,在consul管理界面可以看到已經註冊上的服務信息。

這裏只註冊一個服務進行演示,在實際微服務項目中,肯定是集群環境的,比如同一個服務,你有4臺機器,那consul上就註冊了4個,服務名字都是一樣的,只是URL地址不一樣,當遇上促銷的時候,服務壓力比較大,這時候當要加多一臺服務器,新的服務就自動加到consul上來,消費者就從consul取其中一個服務進行調用。

dotnet  【應用程序.dll】 --ip 127.0.0.1 --port 6001

技術分享圖片

三、服務消費

1、新建一個.NET Core 控制臺應用程序;

2、nuget安裝Consul組件;

技術分享圖片

3、取出已經在Consul註冊的全部服務

       static void Main(string[] args)
        {
 
            using (var consul = new Consul.ConsulClient(c =>
            {
                c.Address = new Uri("http://127.0.0.1:8500");
            }))
            {
                //取在Consul註冊的全部服務
                var services = consul.Agent.Services().Result.Response;
                foreach (var s in services.Values)
                {
                    Console.WriteLine($"ID={s.ID},Service={s.Service},Addr={s.Address},Port={s.Port}");
                }
            }
 
            Console.ReadKey();
        }
    }

現在在Consul已經註冊了3個MsgService服務,打印在控制臺上。

技術分享圖片

技術分享圖片

4、隨機從註冊的服務中取出其中一個服務

當我們在consul上註冊了N個相同的服務之後,我們肯定不能每次都選取某一個服務的,不然得累死那臺服務,而其他服務卻是空閑的狀態,因此我們加入隨機選取的邏輯,從註冊的N個服務中,隨機選取其中一個服務,另外還有其他比如輪詢,權重等等的策略,使得我們更靈活的調用服務。

using (var consul = new Consul.ConsulClient(c =>
 {
      c.Address = new Uri("http://127.0.0.1:8500"); //Consul地址
  }))
 {
       //取出全部的MsgService服務
       var services = consul.Agent.Services().Result.Response.Values.Where(p => p.Service.Equals("MsgService", StringComparison.OrdinalIgnoreCase));
 
       //客戶端負載均衡,隨機選出一臺服務
        Random rand = new Random();
        var index = rand.Next(services.Count());
        var s = services.ElementAt(index);
        Console.WriteLine($"Index={index},ID={s.ID},Service={s.Service},Addr={s.Address},Port={s.Port}");
 }

5、服務調用

//向服務發送請求
using (var httpClient = new HttpClient())
using (var httpContent = new StringContent("{phoneNum:‘119‘,msg:‘help me‘}", Encoding.UTF8, "application/json"))
{
        var result = httpClient.PostAsync($"http://{s.Address}:{s.Port}/api/SMS/Send_LX", httpContent);
        Console.WriteLine($"調用{s.Service},狀態:{result.Result.StatusCode}");
 }

技術分享圖片

.NET Core微服務實施之Consul服務發現與治理