在閱讀本文前我想您應該對微服務架構有一個基本的或者模糊的瞭解html
Consul是一個服務管理軟件,它其實有不少組件,包括服務發現配置共享鍵值對存儲等node
本文主要講解Consul的服務註冊服務發現以及集羣的配置web
參考資料:bootstrap
https://blog.csdn.net/younger_china/article/details/79462530windows
https://www.cnblogs.com/shanyou/p/6286207.htmlapi
假設有服務A,B,C.服務A須要調用服務B和C,傳統的方式咱們須要在服務A中記錄服務B和C的ip及端口號。這些配置通常寫在配置文件等地方存儲。緩存
這種作法有兩個顯而易見的缺點:1.若是未來B的ip改變了就須要修改全部調用者的ip配置。 2.難以作負載均衡服務器
而服務發現就是用來解決這個問題的,怎麼解決呢?請看下面這張圖網絡
這張圖中在服務消費者和服務生產者之間加了一個服務註冊中心的模塊,用上面的服務器ABC來舉例,服務B在發佈的時候會在註冊中心註冊,註冊中心會記錄服務B的名字及ip地址。當服務A請求服務B的時候,只須要帶着服務B的名字來註冊中心查詢便可。集羣狀況下,註冊中心會有多個服務B。同時註冊中心會按期檢查每個服務否能夠正常訪問,移除不可訪問的服務。(健康檢查)架構
總的來講,服務發現就是經過一個標誌來獲取服務列表,而且服務列表可隨着每一個服務的上線或下線動態變動
下面列出幾個consul中出現頻率較高的術語
Agent,Agent是長期運行在每一個consul集羣成員節點上守護進程。經過命令consul agent啓動。Agent有client和server兩種模式。因爲每一個節點都必須運行agent,全部節點要麼是client要麼是server。全部的Agent均可以能夠調用DNS或HTTP API,並負責檢查和維護服務同步。
client 運行client模式的Agent,將全部的RPCs轉發到Server。Client是相對無狀態的。Client惟一所作的是在後臺參與LAN gossip pool。只消耗少許的資源,少許的網絡帶寬。
Server 運行Server模式的Agent,參與Raft quorum,維護集羣的狀態,響應RPC查詢,與其餘數據中心交互WAN gossip,轉發查詢到Leader或遠程數據中心。
datacenter 數據中心的定義彷佛是顯而易見的,有一些細節是必須考慮的。例如,在EC2,多個可用性區域是否被認爲組成了單一的數據中心?咱們定義數據中心是在同一個網絡環境中——私有的,低延遲,高帶寬。這不包括基於公共互聯網環境,可是對於咱們而言,在同一個EC2的多個可用性區域會被認爲是一個的數據中心。
關於client和server我搞了很久才搞明白,實際上client不存儲數據,發送到client的請求,client都會轉發給它綁定的server,也就是說client必須綁定server。server會存儲數據,若是隻有一個server並在上面註冊了一個服務,這個server掛了而後你又重啓了,那麼這個服務的註冊信息仍然保存在server上。
若是你在一臺服務器上運行了一個server,它會默認有一個client綁定到server上,而且地址是127.0.0.1
consul下載地址:https://www.consul.io/downloads.html
我用的win10 系統,因此下載的最後一個windows64位的,下載下來有個exe文件,隨便放個到一個文件夾下就能夠了。
進入cmd,轉到consul的存放目錄,打命令就能夠了。
或者能夠把consul的目錄路徑加入到Path環境變量中,就不用每次到目錄下打命令了
上面說過,consul能夠以client和server的方式啓動
Server:consul agent -server -bootstrap-expect 1 -data-dir=C:\consul -node=n1 -bind=192.168.3.233 -ui-dir=C:\consul\dist -client=0.0.0.0
Client:consul agent -bootstrap-expect 1 -data-dir=C:\consul -node=n1 -bind=192.168.3.233 -ui-dir=C:\consul\dist
把**-server**去掉就是client模式了
- consul agent:啓動consul的命令,要麼是server要麼是client
- -bootstrap-expect:指望的server節點數目,若是集羣中的server節點小於這個數據,集羣則失效,而且該server也失效,一直等到集羣中的數目達到相應的數量才生效,若是是1的話,表明一個server就能夠了
- -data-dir:data存放的目錄,server會保存一些配置緩存等信息,存在此目錄下
- -node:該節點的名稱,急羣衆名稱必須惟一
- -client:表明該server對外暴漏的client地址,0.0.0.0表明我能夠經過:127.0.0.1和192.168.3.233訪問,不設置的話默認是:127.0.0.1
- -bind:這是設置集羣中server之間互相通訊的地址,必須能夠互相訪問到
- -ui-dir:設置webui的界面,理論上經過命令能夠查看到咱們須要的任何信息,可是經過ui來查看更直觀
我開啓了兩臺虛擬機和本機一共是三臺機器,因此我搭建了三個server節點
Ser1:consul agent -server -bootstrap-expect=3 -data-dir=C:\consul -node=node1 -bind=192.168.3.233 -client=0.0.0.0
Ser2:consul agent -server -bootstrap-expect=3 -data-dir=C:\consul -node=node2 -join=192.168.3.233 -bind=192.168.3.201 -client=0.0.0.0
Ser3: consul agent -server -bootstrap-expect=3 -data-dir=C:\consul -node=node3 -join=192.168.3.233 -bind=192.168.3.243 -client=0.0.0.0
-join:表示加入到哪一個集羣內,ser2中咱們指定加入到了ser1中,這時候ser1和ser2組成了集羣,ser3咱們能夠指定加入到ser1和ser2,無論加入哪一個最終這三個server都組成了一個集羣,最終三個server商量了一下選出了一個leader
能夠經過命令來註冊服務,由於最終是要在.net core上使用,因此我就直接貼上.net core中的相關代碼
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifeTime) { string ip = Configuration["ip"]; string port = Configuration["port"]; string serviceName = "MsgService"; string serviceId = serviceName + Guid.NewGuid(); Action<ConsulClientConfiguration> ConsulConfig = (config) => { config.Address = new Uri("http://192.168.3.201:8500"); //服務註冊的地址,集羣中任意一個地址 config.Datacenter = "dc1"; }; 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)) { consulClient.Agent.ServiceDeregister(serviceId).Wait(); //從consul集羣中移除服務 } }); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseHttpsRedirection(); app.UseMvc(); }
運行程序後向consul集羣註冊了一個服務,訪問集羣的任何一個ip均可取到該服務的ip。客戶端查詢服務的代碼以下:
static void Main(string[] args) { using (var consul = new Consul.ConsulClient(c => { c.Address = new Uri("http://192.168.3.233:8500"); //Consul地址 })) { var services = consul.Catalog.Service("MsgService").Result.Response; foreach (var s1 in services) { Console.WriteLine($"ID={s1.ServiceID},Service={s1.ServiceName},Addr={s1.Address},Port={s1.ServicePort}"); } } }
這樣咱們一個基本的consul集羣就能夠正常使用了
對於consul和服務發現目前還只是剛剛開始接觸。仍是有不少問題暫時沒有搞明白。
好比客戶端鏈接的server忽然掛了怎麼辦如何切換到另外一個server?以及一個服務下線瞭如何通知客戶端刪除緩存等等。還請你們不吝賜教