引言
What is the Health Check
Health Check(健康狀態檢查)不僅是對自己應用程序內部檢測各個項目之間的健康狀態(各項目的運行情況、項目之間的連接情況等),還包括了應用程序對外部或者第三方依賴庫的狀態檢測。
Why use Health Check
現在我們的項目越來越多的從單體多層架構轉換成多項目多層架構即現在流行的微服務架構。
原來我們的App把各個模塊分層分項目處理,比如Users項目僅僅處理User的一些業務需求,但在整個項目使用的時候,我們僅僅需要引用其類庫即可,不用擔心項目與類庫之間的不兼容問題,如果不兼容在編譯期已經會有提示。但如今,業務規模越來越龐大的時候,我們單獨把Users作為一個service來做,所有一切都在其內部處理,對於外部來說僅僅公開幾個api即可,但與項目之間的連接就從單純的物理引用關系轉換成了網絡調用關系。
當我們架構從單體架構到微服務架構的時候,我們會發現越來越多的引用從物理轉向了網絡,在原來我們不需要考慮之間是否調用成功,但現在我們必須考慮進去,網絡因素、服務器因素、其他因素等都會影響各服務之間的調用,因此Health Check孕育而生,它在微服務架構中是舉足輕重的。
Health Check’s Feathure
Health Check的功能有哪些?在微服務架構中很簡單,就是檢查各services的運行狀態是否正常。在微服務的架構中,所有的一切都是service,db is service,rabbitmq is service,auth is service, shoppingcart is server……我們的架構能夠根據業務需求,橫向的擴容,多個db,多個rabbitmq,多個auth,多個shoppingcart。我們總結下,微服務架構下的Health Check是通過網絡檢查各services是否正常運行,它的功能是:
1、提供外部調用Health Check接口,反饋自身狀態
2、檢測相關service狀態是否正常(比如db server,能否連接到db,能否打開數據庫等)
3、UnHealthly時處理機制
Health Check in eShop
Why in eShop?
之前我們一直都在介紹eShop是微軟基於微服務架構的.Net Core Demo,為了保障各個services之間的調用正常,所以Health Check是必不可少的。
Where is it?
在Demo中,我們可以在各個services中都能看到HealthCheck,可以說是無處不在,在系列【二】和【三】中我們都有見過。在eShop項目中,我們可以看到有個HealthChecks目錄,其中包含了與HealthChecks相關的幾個項目:
Microsoft.Extensions.HealthChecks ------------ Health Check的核心代碼
Microsoft.AspNetCore.HealthChecks ------------ Asp.Net Core注冊擴展類庫
Microsoft.Extensions.HealthChecks.AzureStorage ----- 擴展對Azure Blob Storage的支持
Microsoft.Extensions.HealthChecks.SqlServer ------ 擴展對MsSql Server的支持
通過代碼了解,在eShop中實現了對各Api的通訊檢測和SqlServer、AzureBlobStorage的檢測,但其中並沒有看到對重試機制和UnHealthy時的處理,相信以后會加入這些,目前微軟已經單獨為HealthChecks開了一個Repository,這樣你就可以單獨引用到自己的項目中,非常棒的東西。
在項目中,我們一般只會在Program.cs和Startup.cs看到跟HealthChecks相關的代碼。目前僅在客戶端(其他service或者我們的app)請求我們的HealthChecks的時候,我們會進行相關service的檢測,然后再返回自身的一個狀態碼。
How use the Healthchecks?
接下來我們看下在eShop中代碼是如何使用的,我們以Identity.Api為例,在之前的文章中我們提到過,在Program.cs中,有一段UseHealthChecks("/hc"),我們跟蹤下代碼,你會看到它會先判斷path是否負責規則,如果符合的話就會通過IWebHostBuilder注冊一個HealthCheckStartupFilter,Filter則會把相應的HealthCheckMiddleware注冊到管道中,我們看下主要源碼:
public async Task Invoke(HttpContext context) { if (IsHealthCheckRequest(context)) { var timeoutTokenSource = new CancellationTokenSource(_timeout); var result = await _service.CheckHealthAsync(timeoutTokenSource.Token); var status = result.CheckStatus; if (status != CheckStatus.Healthy) context.Response.StatusCode = 503; context.Response.Headers.Add("content-type", "application/json"); await context.Response.WriteAsync(JsonConvert.SerializeObject(new { status = status.ToString() })); return; } else { await _next.Invoke(context); } } private bool IsHealthCheckRequest(HttpContext context) { if (_port.HasValue) { var connInfo = context.Features.Get<IHttpConnectionFeature>(); if (connInfo.LocalPort == _port) return true; } if (context.Request.Path == _path) { return true; } return false; }
它會先檢測這個請求是不是HealthCheck請求,如果不是則走下面的步驟,如果是,則會進一步進行對相關service的HealthChecks。對相關service的Config實在Startup.cs中進行的:
services.AddHealthChecks(checks => { var minutes = 1; if (int.TryParse(Configuration["HealthCheck:Timeout"], out var minutesParsed)) { minutes = minutesParsed; } checks.AddSqlCheck("Identity_Db", Configuration.GetConnectionString("DefaultConnection"), TimeSpan.FromMinutes(minutes)); });
這里可以看到,在Identity.Api中,僅僅配置了對數據庫的檢測。
ok,我們非常簡單的在項目中引用了HealthCheck,當我們的api運行后,我們只需要通過 http://xxx/hc 就能對這個api進行Health Check了。
寫在最后
今天我們了解了Health Check,並簡單看了它在eShop中的使用。目前看來還不是很完善,只在其他service或者app調用其Health Check接口的時候才能進行檢測,當然我們可以改造下,使其在程序運行的時候先檢測一次。在eShop中我們並沒有看到在UnHealth的時候的處理,這個擴展起來很簡單,你可以通過自身需求,進行日志,email,短信都可以,后面可以找機會實現下。
乘着不忙的時候趕緊學習,如果大家有興趣學習.Net Core的話,可以加QQ群:376248054(通關密碼:cnblogs)。另外喜歡微服務的朋友可以看下園中大神Savorboard的微服務系列