實戰中的asp.net core結合Consul集羣&Docker實現服務治理

0、目錄


 

總體架構目錄:ASP.NET Core分佈式項目實戰-目錄html

1、前言


 

在寫這篇文章以前,我看了不少關於consul的服務治理,但發現基本上都是直接在powershell或者以命令工具的方式在服務器上面直接輸入consul agent .... 來搭建啓動consul集羣,一旦把命令工具關掉,則consul沒法再後臺啓動,尤爲是在linux系統中。node

若是在window系統中,採用bat文件到時能夠作成開機自啓,或者在linux中把命令作成一個service 服務文件來啓動就能夠實現後臺運行。linux

所以爲了社區能更好的發展技術,且能把consul應用在生產環境中,我認真回顧了在公司項目中的應用,特此把我開發及總結的分享給你們,此篇文章採用docker引擎,而且只涉及到consul集羣部署以及結合asp.net core微服務註冊。web

固然若是內容有涉及安全隱患的,你們能夠積極留言,共同進步。docker

 注:如下所涉及到部署過程所有通過樓主我反覆的驗證,總結得來。你們在應用的過程當中若是出現問題,能夠留言諮詢。shell

2、部署consul集羣


 

一、介紹一下Consul

consul 關鍵特性
  服務發現:支持服務發現。你能夠經過 DNS 或 HTTP 的方式獲取服務信息。
  健康檢查:支持健康檢查。能夠提供與給定服務相關聯的任何數量的健康檢查(如 web 狀態碼或 cpu 使用率)。
  K/V 存儲:鍵/值對存儲。你可用經過 consul 存儲如動態配置之類的相關信息。
  多數據中心:支持多數據中心,開箱即用。
  WEB UI:支持 WEB UI。點點點,你就可以瞭解你的服務如今的運行狀況,一目瞭然,對開發運維是很是友好的。json

 

說明:bootstrap

在Consul方案中,每一個提供服務的節點上都要部署和運行Consul的Client Agent,全部運行Consul Agent節點的集合構成Consul Cluster。
Consul Agent有兩種運行模式:Server和Client。這裏的Server和Client只是Consul集羣層面的區分,與搭建在Cluster之上的應用服務無關。以Server模式運行的Consul Agent節點用於維護Consul集羣的狀態,官方建議每一個Consul Cluster至少有3個或以上的運行在Server Mode的Agent,Client節點不限。api

Consul支持多數據中心,每一個數據中心的Consul Cluster都會在運行於Server模式下的Agent節點中選出一個Leader節點,這個選舉過程經過Consul實現的raft協議保證,多個 Server節點上的Consul數據信息是強一致的。處於Client Mode的Consul Agent節點比較簡單,無狀態,僅僅負責將請求轉發給Server Agent節點。瀏覽器

 

Consul與其餘工具的比較

 

consul的端口解釋

好了,該介紹的已經介紹了,接下來就是正式部署吧

 

二、Docker上運行Consul

第一步:安全配置,適用受權和數據加密傳輸(生產環境是必須的)

爲了consul的安全,須要進行gossip加密以及RPC加密結合TLS。
Gossip加密:主要用於節點間的接收發送集羣信息安全。
RPC加密:主要用於Agent之間調用RPC受權的安全性。

 

此處你們能夠參考官網或者一下資料:

https://www.jianshu.com/p/3d074ed76a68
https://www.consul.io/docs/agent/encryption.html

 

第二步:consul集羣部署

準備服務器(能夠採用虛擬機部署)

  名稱 IP
CentOS7-1 server1 192.168.216.160
CentOS7-2 server2 192.168.216.161
CentOS7-3 server3 192.168.216.162
CentOS7-4 client1 192.168.216.163
vs 2017 project部署在docker上 192.168.216.163

部署server1

docker run -d --net=host -v $PWD/data:/consul/data -v $PWD/config:/consul/config --restart always --name consulServer1 consul agent -server -bind=192.168.216.160 -node=server1 -bootstrap-expect 3 -data-dir=/consul/data -config-file=/consul/config -client 0.0.0.0 -ui

 

部署server2
docker run -d --net=host -v $PWD/data:/consul/data -v $PWD/config:/consul/config --restart always --name cs2 consul agent -server -bind=192.168.216.161 -node=server2 -bootstrap-expect 3 -data-dir=/consul/data -config-file=/consul/config -client 0.0.0.0 -ui -retry-join=192.168.216.160

 

部署server3
docker run -d --net=host -v $PWD/data:/consul/data -v $PWD/config:/consul/config --restart always --name cs3 consul agent -server -bind=192.168.216.162 -node=server3 -bootstrap-expect 3 -data-dir=/consul/data -config-file=/consul/config -client 0.0.0.0 -ui -retry-join=192.168.216.160


部署client-鏈接server
docker run -d --net=host -v $PWD/data:/consul/data -v $PWD/config:/consul/config --restart always --name cc1 consul agent -bind=192.168.216.163 -node=client1 -data-dir=/consul/data -config-file=/consul/config -client 0.0.0.0 -retry-join=192.168.216.160

 

注:(針對以上的參數以及配置解釋)
一、此處的數據掛載就是把容器內的data以及配置掛載到外部地址,$PWD表明當前目錄即你運行docker命令時的目錄,固然$PWD能夠替換爲具體的路徑
二、-data-dir=/consul/consul -config-file=/consul/config :這兩個地方表明在consul啓動後會把數據以及配置文件放到指定的目錄下,這個對於在服務器模式下運行的代理尤爲重要,由於它們必須可以保持羣集狀態。
三、總結,以上兩點結合就是說明 consul產生的數據而後掛載在外部地址進行持久化存儲。
四、server端 的-client 參數能夠不用,官方推薦是 服務註冊到client端,由client端再把數據統一提交到server端。

 

參數說明

-client : 0.0.0.0 表明綁定到全部接口的選項,若是沒有此選項,則asp.net core沒法進行服務註冊使用

-bind :該地址用來在集羣內部的通信,集羣內的全部節點到地址都必須是可達的

--net=host 使得docker容器越過了net namespace的隔離,免去手動指定端口映射的步驟

-retry-join 容許你在第一次失敗後進行嘗試,加入一個已經啓動的agent的ip地址

-bootstrap-expect 提供的server節點數目

-ui 啓動自有主機的界面

-data-dir :提供一個目錄用來存放agent的狀態,全部的agent容許都須要該目錄,該目錄必須是穩定的,系統重啓後都繼續存在

CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true}:在0.7版本以後默認是true,所以不是必須的。

CONSUL_LOCAL_CONFIG={"leave_on_terminate": true}:在0.7版本以後默認是true,所以不是必須的。若是啓用,當代理收到TERM信號時,它將向Leave羣集的其他部分發送消息並正常離開

 

打開瀏覽器器查看 consul :

看全部consul節點狀況
docker exec -t cs1 consul members

 

查看server的狀態,以及哪個節點是leader

docker exec -t cs1 consul operator raft list-peers

注:

若是其中一臺或者多臺server端掛掉,則Consul集羣就會從新選舉新的Leader,
可是一旦掛掉阿的節點數量超過一半,則Consul集羣就沒法工做了。

3、asp.net core微服務進行服務註冊


 

一、新建一個項目asp.net core webapi項目

引入 consul ,nuget包

二、在控制器中新建一個控制器Health,表明健康檢查

[Produces("application/json")]
    [Route("api/Health")]
    public class HealthController : Controller
    {
        [HttpGet]
        public IActionResult Get() => Ok("ok");
    }

 

三、而後在appsetting.json中添加配置文件

須要手動配置一下地址和端口號。

{
  "Logging": {
    "IncludeScopes": false,
    "Debug": {
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "Console": {
      "LogLevel": {
        "Default": "Warning"
      }
    }
  },
  "ServiceRegister": { //服務註冊
    "IsActive": true,
    "ServiceName": "testconsul6",
    "ServiceHost": "192.168.216.163",
    "ServicePort": 5006,
    "Register": {
      "HttpEndpoint": "http://192.168.216.163:8500"
    }
  }
}

 

四、這一步是服務註冊的類

ServiceRegisterOptions.cs

public class ServiceRegisterOptions
    {
        /// <summary>
        /// 是否啓用
        /// </summary>
        public bool IsActive { get; set; }
        /// <summary>
        /// 服務名稱
        /// </summary>
        public string ServiceName { get; set; }
        /// <summary>
        /// 服務IP或者域名
        /// </summary>
        public string ServiceHost { get; set; }
        /// <summary>
        /// 服務端口號
        /// </summary>
        public int ServicePort { get; set; }
        /// <summary>
        /// consul註冊地址
        /// </summary>
        public RegisterOptions Register { get; set; }
    }

 

 RegisterOptions.cs

public class RegisterOptions
    {
        public string HttpEndpoint { get; set; }
    }

 

 五、在startup.cs 中的服務註冊

public void ConfigureServices(IServiceCollection services)
        {
            #region 服務註冊基礎信息配置
            services.Configure<ServiceRegisterOptions>(Configuration.GetSection("ServiceRegister"));
            services.AddSingleton<IConsulClient>(p => new ConsulClient(cfg =>
            {
                var serviceConfiguration = p.GetRequiredService<IOptions<ServiceRegisterOptions>>().Value;
                if (!string.IsNullOrEmpty(serviceConfiguration.Register.HttpEndpoint))
                {
                    cfg.Address = new Uri(serviceConfiguration.Register.HttpEndpoint);
                }
            }));
            #endregion

            services.AddMvc();
        }

 

在Configure 方法中配置代碼

private static void RegisterService(IApplicationBuilder app,
            IOptions<ServiceRegisterOptions> serviceRegisterOptions,
            IConsulClient consul,
            IApplicationLifetime appLife)
        {
            var serviceId = $"{serviceRegisterOptions.Value.ServiceName}_{serviceRegisterOptions.Value.ServiceHost}:{serviceRegisterOptions.Value.ServicePort}";

            var httpCheck = new AgentServiceCheck()
            {
                DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服務啓動多久後註冊
                Interval = TimeSpan.FromSeconds(30),//健康檢查時間間隔,或者稱爲心跳間隔
                HTTP = $"http://{serviceRegisterOptions.Value.ServiceHost}:{serviceRegisterOptions.Value.ServicePort}/api/health",//健康檢查地址
            };

            var registration = new AgentServiceRegistration()
            {
                Checks = new[] { httpCheck },
                Address = serviceRegisterOptions.Value.ServiceHost,
                ID = serviceId,
                Name = serviceRegisterOptions.Value.ServiceName,
                Port = serviceRegisterOptions.Value.ServicePort
                //Tags = new[] { $"urlprefix-/{serviceRegisterOptions.Value.ServiceName}" }//添加 urlprefix-/servicename 格式的 tag 標籤,以便 Fabio 識別
            };
            //.GetAwaiter().GetResult()
            consul.Agent.ServiceRegister(registration).GetAwaiter().GetResult();

            appLife.ApplicationStopping.Register(() =>
            {
                consul.Agent.ServiceDeregister(serviceId).GetAwaiter().GetResult();//服務中止時取消註冊
            });
        }
        #endregion

 

自此,能夠把咱們的項目部署到163服務器上面的docker上啦。

咱們看一下效果,成功註冊到了

 

 

參考資料:

Conusl TLS配置:

https://www.jianshu.com/p/3d074ed76a68
https://www.consul.io/docs/agent/encryption.html

consul 參數配置: 

https://blog.csdn.net/zl1zl2zl3/article/details/79622476

consul服務治理:

http://michaco.net/blog/ServiceDiscoveryAndHealthChecksInAspNetCoreWithConsul
https://www.cnblogs.com/myzony/p/9168851.html
https://www.cnblogs.com/edisonchou/p/9124985.html

 


 

asp.net Core 交流羣:787464275 歡迎加羣交流
若是您認爲這篇文章還不錯或者有所收穫,您能夠點擊右下角的【推薦】按鈕精神支持,由於這種支持是我繼續寫做,分享的最大動力!

做者:LouieGuo
聲明:原創博客請在轉載時保留原文連接或者在文章開頭加上本人博客地址,如發現錯誤,歡迎批評指正。凡是轉載於本人的文章,不能設置打賞功能,若有特殊需求請與本人聯繫!

微信公衆號:歡迎關注                                                 QQ技術交流羣: 歡迎加羣

                

相關文章
相關標籤/搜索