一、什麼是consul?

       首先我們來了解什麼是consul,consul是服務註冊與發現的一種常用工具之一,翻閲了網上的部分資料,指把服務地址註冊到consul,然後在consul中讀取來消費;但在我的理解中,consul的作用是服務治理,屬於可以橫向伸縮的註冊中心;為什麼這麼説呢?在以前我們用Nginx做負載時,需要把服務地址一個個手動集成進去的,如果服務多了會有什麼問題呢?1.需要新增一個服務,必須要重新配置Nginx然後重啓;2.感知不了哪個服務停止了;3.如果某個服務停止了,無法自動創建新的服務代替;因為微服務其中一個特點是基礎設施自動化,所以明顯Nginx滿足不了需求,那麼服務註冊與發現就橫空而生了(除了consul外還可以使用etcd,K8S Services等)。

二、consul有幾大核心功能:

1.服務註冊

其他客户端可以使用 Consul 發現給定服務的提供者。使用 DNS 或 HTTP,應用程序可以輕鬆找到它們所依賴的服務(它是通過代理註冊的方式註冊到註冊中心,提供業務代碼的解耦)

2.健康檢查

  其實就是在程序中,建立一個接口,只返回狀態使用,consul通過這個接口來檢查服務是否健康,如果不健康,則通過策略去移除

3.多個數據中心

  其實就是支持集羣,通過3個,或5個的單數服務端的consul來支持高可用(因為單數更適合做選舉算法,如果數量太多又影響性能,所以這是官網標配);

4.安全服務通信

  Consul 可以為服務生成和分發 TLS 證書以建立相互 TLS 連接

consul工作流程圖:


 

consul 能使用mysql麼_List

 

 

 

 

三、consul安裝

  安裝分2種,一種是二進制,以命令行的形式安裝;一種是以exe文件免安裝的形式;

四、consul運行問題

  運行時,最可能出現的問題就是端口占用,可新增文件,修改文件端口號,然後執行命令即可,百度上很多解決,請自行搜索命令

五、net6的代碼實現

  1.服務註冊代碼,目的是把當前服務推送到consul,並且設置健康檢查

依賴組件

consul
1 public static class RegisterToConsul
 2     {
 3         /// <summary>
 4         /// 把本服務註冊到Consul
 5         /// </summary>
 6         /// <param name="config">參數配置</param>
 7         /// <param name="appLifetime">程序生命週期</param>
 8         public static void RegToConsul(this IConfiguration config)
 9         {
10             //Consul地址
11             var address= AppHelper.ReadAppSettings("Consul", "consulAddress"); 
12             var consulClient = new ConsulClient(p => { p.Address = new Uri(address); });
13 
14             //本地IP
15             var localIP = AppHelper.ReadAppSettings("Consul", "currentIp");
16             //本地服務端口
17             var localPort = Convert.ToInt32(AppHelper.ReadAppSettings("Consul", "currentPort")); //端口號從命令行參數獲取(注:目前沒找到直接獲取本服務監聽的端口的方法)
18 
19             //心跳檢測設置
20             var httpCheck = new AgentServiceCheck()
21             {
22                 DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(60), //心跳檢測失敗多久後註銷
23                 Interval = TimeSpan.FromSeconds(10), //間隔多久心跳檢測一次
24                 HTTP = $"http://{localIP}:{localPort}/api/Health/Check", //心跳檢查地址,本服務提供的地址
25                 Timeout = TimeSpan.FromSeconds(5)  //心跳檢測超時時間
26             };
27 
28             //服務名(這裏通過命令行參數傳入不同的服務名,模擬我們有不同的服務[其實只是同一個接口項目的不同運行實例])
29             var serviceName = AppHelper.ReadAppSettings("Consul", "serviceName");
30 
31             //註冊信息
32             var registration = new AgentServiceRegistration()
33             {
34                 ID = $"{localIP}:{localPort}", //服務ID,唯一
35                 Name = serviceName, //服務名(如果服務搭集羣,它們的服務名應該是一樣的,但是ID不一樣)
36                 Address = $"{localIP}", //服務地址
37                 Port = localPort, //服務端口
38                 Tags = new string[] { }, //服務標籤,一般可以用來設置權重等本地服務特有信息
39                 Checks = new[] { httpCheck }, //心跳檢測設置
40             };
41 
42             //向Consul註冊服務
43             consulClient.Agent.ServiceRegister(registration).Wait();
44 
45         }
46     }
1   "Consul": {
 2 
 3     "consulAddress": "http://127.0.0.1:8500",
 4 
 5     "serviceName": "Consultest",
 6 
 7     "currentIp": "127.0.0.1",
 8 
 9     "currentPort": "5247"
10 
11   }

appseting設置

1 public class AppHelper
 2     {
 3         private static IConfiguration _config;
 4 
 5         public AppHelper(IConfiguration configuration)
 6         {
 7             _config = configuration;
 8         }
 9 
10         /// <summary>
11         /// 讀取指定節點的字符串
12         /// </summary>
13         /// <param name="sessions"></param>
14         /// <returns></returns>
15         public static string ReadAppSettings(params string[] sessions)
16         {
17             try
18             {
19                 if (sessions.Any())
20                 {
21                     return _config[string.Join(":", sessions)];
22                 }
23             }
24             catch
25             {
26                 return "";
27             }
28             return "";
29         }
30 
31         /// <summary>
32         /// 讀取實體信息
33         /// </summary>
34         /// <typeparam name="T"></typeparam>
35         /// <param name="session"></param>
36         /// <returns></returns>
37         public static List<T> ReadAppSettings<T>(params string[] session)
38         {
39             List<T> list = new List<T>();
40             _config.Bind(string.Join(":", session), list);
41             return list;
42         }
43     }

獲取appsetting文件類

1  [Route("api/[controller]")]
 2     [ApiController]
 3     public class HealthController : ControllerBase
 4     {
 5         [HttpGet]
 6         [Route("Check")]
 7         public IActionResult Check()
 8         {
 9             return Ok();
10         }
11     }

心跳代碼

 

  2.服務發現代碼,目的是通過調用consul註冊中心的服務

1 private static int index = 0;
 2         [HttpGet]
 3         [Route("Contents")]
 4         public IActionResult Contents()
 5         {
 6             string url = $"http://{AppHelper.ReadAppSettings("Consul", "serviceName")}/api/values";
 7             ConsulClient client = new ConsulClient(c=>
 8             {
 9                 c.Address = new Uri(AppHelper.ReadAppSettings("Consul", "consulAddress"));
10             }
11             );
12             var res = client.Agent.Services().Result.Response;
13             Uri uris = new Uri(url);
14             string groupname = uris.Host;
15             var dic = res.Where(s => s.Value.Service.Equals(groupname, StringComparison.OrdinalIgnoreCase)).ToArray();
16             //輪詢讀取
17             return Content(Newtonsoft.Json.JsonConvert.SerializeObject(dic[index++ % dic.Length].Value));
18         }

服務發現代碼

 

六、Consul集羣,做集羣測試


七、拓展點

  上面的服務發現讀取上,當單個服務達到瓶頸了,這時候我們就要負載均衡來分擔服務器的壓力,那麼我們下一節來講Consul如何進行負載均衡