熔斷保護在Consul和Ocelot中都有實現,意思就是當一個服務不正常時(比如我們的一個服務實例掛了,Consul的健康檢查機制檢測到了),應該給系統維護人員給以告警。在Consul中,服務告警也是通過配置文件來實現的。
3.1 添加watch.json配置文件
{ "watches": [ { "type": "checks", "handler_type": "http", "state": "critical", "http_handler_config": { "path": "http://192.168.80.71:9000/notice", "method": "POST", "timeout": "10s", "header": { "Authorization": [ "token" ] } } } ] }
*.有關watch的細節,請參考:https://www.consul.io/docs/agent/watches.html
這里編輯完成之后,就可以放到config目錄下了,后面重啟Consul Client Agent服務時會加載新的watches_config.json配置文件。
3.2 添加NoticeService服務
新寫一個ASP.NET Core WebAPI程序,其主要功能就是接受Consul POST過來的參數並調用方法發送電子郵件。
(1)Controller編寫
[Route("api/[controller]")] public class HomeController : Controller { public IConfiguration Configuration { get; } public HomeController(IConfiguration configuration) { Configuration = configuration; } [HttpPost("/notice")] public IActionResult Notice() { var bytes = new byte[10240]; var i = Request.Body.ReadAsync(bytes, 0, bytes.Length); var content = System.Text.Encoding.UTF8.GetString(bytes).Trim('\0'); EmailSettings settings = new EmailSettings() { SmtpServer = Configuration["Email:SmtpServer"], SmtpPort = Convert.ToInt32(Configuration["Email:SmtpPort"]), AuthAccount = Configuration["Email:AuthAccount"], AuthPassword = Configuration["Email:AuthPassword"], ToWho = Configuration["Email:ToWho"], ToAccount = Configuration["Email:ToAccount"], FromWho = Configuration["Email:FromWho"], FromAccount = Configuration["Email:FromAccount"], Subject = Configuration["Email:Subject"] }; EmailHelper.SendHealthEmail(settings, content); return Ok(); } }
不再解釋這段代碼。
(2)SendHealthEmail方法編寫
public class EmailHelper { public static void SendHealthEmail(EmailSettings settings, string content) { try { dynamic list = JsonConvert.DeserializeObject(content); if (list != null && list.Count > 0) { var emailBody = new StringBuilder("健康檢查故障:\r\n"); foreach (var noticy in list) { emailBody.AppendLine($"--------------------------------------"); emailBody.AppendLine($"Node:{noticy.Node}"); emailBody.AppendLine($"Service ID:{noticy.ServiceID}"); emailBody.AppendLine($"Service Name:{noticy.ServiceName}"); emailBody.AppendLine($"Check ID:{noticy.CheckID}"); emailBody.AppendLine($"Check Name:{noticy.Name}"); emailBody.AppendLine($"Check Status:{noticy.Status}"); emailBody.AppendLine($"Check Output:{noticy.Output}"); emailBody.AppendLine($"--------------------------------------"); } var message = new MimeMessage(); message.From.Add(new MailboxAddress(settings.FromWho, settings.FromAccount)); message.To.Add(new MailboxAddress(settings.ToWho, settings.ToAccount)); message.Subject = settings.Subject; message.Body = new TextPart("plain") { Text = emailBody.ToString() }; using (var client = new SmtpClient()) { client.ServerCertificateValidationCallback = (s, c, h, e) => true; client.Connect(settings.SmtpServer, settings.SmtpPort, false); client.AuthenticationMechanisms.Remove("XOAUTH2"); client.Authenticate(settings.AuthAccount, settings.AuthPassword); client.Send(message); client.Disconnect(true); } } } catch(Exception ex) { Console.WriteLine(ex.Message); } }
這里使用的是MailKit庫(支持.net core),可以通過NuGet搜索並安裝,此外為何接受的參數屬性是這些,大家可以看看Consul官方文檔中watches頁中的checks類型,見下圖所示:
(3)發布NoticeService到192.168.80.71服務器中,同樣也可以加入Consul配置文件中:

發布完成之后,重啟Consul Client節點(192.168.80.71)的Consul服務,可以看到NoticeService也注冊成功:
3.3 測試服務告警
(1)手動在IIS中關閉一個ClientService服務,例如:這里我關閉了ClientService.01
(2)查看自動發送的Email內容:從Email中我們可以知道哪個Server節點的哪個Service出了問題,並且可以大概了解原因(Check Output),這時我們的系統維護人員就該起床加班了。
*.需要注意的是確保你的虛擬機可以訪問外網,不然是發布出來Email的。
4.小結
本篇將上篇中遺留的內容進行了彌補,下篇將開始基於Ocelot+Polly的API網關服務實踐,敬請期待,我要睡了。