【五分鐘的dotnet】是一個利用您的碎片化時間來學習和豐富.net知識的博文系列。它所包含了.net體系中可能會涉及到的方方面面,好比C#的小細節,AspnetCore,微服務中的.net知識等等。 5min+不是超過5分鐘的意思,"+"是知識的增長。so,它是讓您花費5分鐘如下的時間來提高您的知識儲備量。html
在開發AspNet Core應用的時候,咱們常常會爲該應用公佈一個特殊的檢測接口出來。該接口的目的很簡單,告訴某一些外界程序(好比docker,客戶端等)這個程序如今是能夠訪問或者不能訪問的,便於外界作出相應的操做,好比監控報警,頁面通知用戶稍做等待等。git
在AspNet Core 2.2 以前,若是咱們要實現一個這樣的檢測接口,須要創建一個單獨的controller,好比HealthController
。而後爲其實現一個簡單的檢測方法:github
[Route("working")] public ActionResult Working() { using (var connection = new SqlConnection(_connectionString)) { try { connection.Open(); } catch (SqlException) { return new HttpStatusCodeResult(503, "Generic error"); } } return new EmptyResult(); }
該接口目的是檢測應用與數據庫的鏈接可否成功。若是成功鏈接,則返回狀態碼爲200
的空內容,若是失敗則返回503
。 外界程序能夠經過定時訪問 「\working」
路徑,根據返回的對應Code來作出相應的反應。sql
可是在Aspnet Core 2.2 以後,咱們有了新的解決方式。只須要簡單的操做就能夠進行程序運行情況的檢查。docker
咱們只須要在Startup.cs
中添加兩句話就OK了:數據庫
public void ConfigureServices(IServiceCollection services) { //使用該擴展方法 services.AddHealthChecks(); } public void Configure(IApplicationBuilder app) { app.UseRouting(); app.UseEndpoints(endpoints => { //使用該擴展方法 endpoints.MapHealthChecks("/health"); }); }
默認狀況是不須要在額外的引入其它nuget包的,由於AspNet Core自帶了這些功能。json
此時咱們能夠訪問 "/health"
路徑,將會看到對應結果:app
若是程序正常,則返回Http狀態碼爲200
,顯示內容爲"Healthy"的結果。若是程序不正常,則返回Http狀態碼爲503
,顯示內容爲"UnHealthy"的結果。微服務
這就是運行情況檢查的初步使用。學習
看到這裏,可能有些同窗要問:「我引入一個檢測到底有什麼用?什麼狀況下我須要這麼作呢?」
其實,對我們的應用程序來講,作運行狀況檢查是很是有必要的。
就比如去醫院看病的時候,醫生每每會問病人:「你如今是感受哪兒不舒服,對哪些藥物過敏」等等問題。而後才能對症下藥。
更形象的一個例子是作體檢:人們通常會自費花錢按期去醫院作體檢,若是發現哪一檢查項有異常的時候,就會報告給醫院而且去尋找對應的醫生,向醫生說明狀況以後獲得對應的治療方案。
因此我們的應用程序也是同樣的,「按期體檢」有必要嗎? 確定是有必要的。若是不按期體檢,咱們很難知道如今程序運行狀態究竟是什麼樣子,或許它已經「瀕臨崩潰」了,須要當即釋放內存。
還有一點就是:須要如實的報告檢查狀況。就如同醫生問病人:「您哪不舒服?」,病人說:「我沒病。我哪兒都沒問題」 。 那醫生只會認爲病人是來搞笑的,因此放棄對他的治療。
始終要相信一點,沒有人比你本身更懂你本身。雖然外界的程序也會有各類其它方式來判斷應用程序是否正常,可是它只能知道大概,只有程序體自己才能更清楚的知道如今運行的狀況。
最初咱們只是簡單的引入了 AddHealthChecks
。 可是它並無任何特定的邏輯在裏面。而現實場景咱們是須要對各類指標進行檢查的,就比如體檢單上有多個體檢項同樣。因此咱們須要實現自定義的檢查功能。
好比我們如今要實現一個對Sql Server 鏈接狀況的檢查。咱們只須要實現 IHealthCheck
接口,實現CheckHealthAsync
方法就能夠了:
public class SqlServerHealthCheck : IHealthCheck { SqlConnection _connection; public string Name => "sql"; public SqlServerHealthCheck(SqlConnection connection) { _connection = connection; } public Task<HealthCheckResult> CheckHealthAsync( HealthCheckContext context, CancellationToken cancellationToken = default) { try { _connection.Open(); } catch (SqlException) { return Task.FromResult(HealthCheckResult.Unhealthy("From Sql Serve")); } return Task.FromResult(HealthCheckResult.Healthy()); } }
而後在Startup.cs
的AddHealthChecks
進行擴展:
services.AddHealthChecks() .AddCheck<SqlServerHealthCheck>("sql_check");
此時若是我們再次訪問"/health"
路徑,就會發現應用會執行SqlServerHealthCheck
裏面的檢查邏輯。
可是實際狀況,我們每每都會有許許多多的檢查項,好比增長一個叫作MemoryHealthCheck
的檢查項:
public class MemoryHealthCheck : IHealthCheck { public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) { //doing some memory check things. return Task.FromResult(HealthCheckResult.Healthy()); } } // startup.cs public void ConfigureServices(IServiceCollection services) { services.AddHealthChecks() .AddCheck<SqlServerHealthCheck>("sql_check") .AddCheck<MemoryHealthCheck>("memory_check"); // add this line }
或許還有許許多多的檢查項:FileSizeHealthCheck
,RedisHealthCheck
等等。當咱們將它們都添加上以後,則只有當全部的檢查器都返回爲Healthy
的時候,纔會認爲是健康。
可是某些狀況咱們又只想進行單項檢查怎麼辦呢? 咱們能夠在 endpoints 的配置中新增另外的路由映射規則:
// startup.cs app.UseEndpoints(endpoints => { endpoints.MapHealthChecks("/health", new HealthCheckOptions() { Predicate = s => s.Name.Equals("sql_check"), ResponseWriter = WriteResponse }); endpoints.MapHealthChecks("/healthy", new HealthCheckOptions() { Predicate = s => s.Name.Equals("memory_check"), ResponseWriter = WriteResponse }); }); //指定返回格式 private static Task WriteResponse(HttpContext context, HealthReport result) { context.Response.ContentType = "application/json"; var json = new JObject( new JProperty("status", result.Status.ToString()), new JProperty("results", new JObject(result.Entries.Select(pair => new JProperty(pair.Key, new JObject( new JProperty("status", pair.Value.Status.ToString()), new JProperty("description", pair.Value.Description), new JProperty("data", new JObject(pair.Value.Data.Select( p => new JProperty(p.Key, p.Value)))))))))); return context.Response.WriteAsync( json.ToString()); }
咱們在原有的基礎上增長了HealthCheckOptions
的參數,該參數指定了關於狀態檢測的匹配規則,返回狀態碼,返回格式等信息。
上面的代碼咱們指定了兩個路由。當訪問"health"
路徑的時候,則是對sql鏈接的檢查(根據檢查器名來匹配:Name.Equals("sql_check")),而訪問"healthy"
路徑的時候,是對內存的檢查。 最後還爲他們指定了須要返回的內容(WriteResponse)。
接下來咱們再次進行請求"health"
路徑,就會獲得下面的結果:
自定義返回內容對我們定位錯誤和記錄日誌十分有用。(就像看病的例子,病人更清晰的描述病情,醫生就可以更容易定位病因。)。
雖然官方爲咱們提供的運行檢查庫已經足夠輕量和簡單。可是爲了不重複造輪子,咱們可使用AspNetCore.Diagnostics.HealthChecks包,該項目包含了許多狀況的檢查,好比 Sql Server
、MySql
、Elasticsearch
、Redis
、Kafka
等等。
而且還爲咱們提供一個UI界面,可供查看。只須要在原有的基礎上引入對應的代碼就好了:
public void ConfigureServices(IServiceCollection services) { services.AddHealthChecks() .AddCheck<SqlServerHealthCheck>("sql_check") .AddCheck<MemoryHealthCheck>("memory_check"); // add this line services.AddHealthChecksUI(); } app.UseEndpoints(endpoints => { endpoints.MapHealthChecks("/health", new HealthCheckOptions() { Predicate = s => s.Name.Equals("sql_check"), ResponseWriter = WriteResponse }); //add this line endpoints.MapHealthChecksUI(); });
當咱們訪問"/healthchecks-ui"
路徑時,就能夠看到這樣的UI:
默認是沒有任何的檢測配置項的,若是我們須要可視化運行狀態,須要在AddHealthChecksUI
中進行配置:
services.AddHealthChecksUI(setupSettings: setup => { setup.AddHealthCheckEndpoint("endpoint1", "http://localhost:5001/health"); });
再次查看UI界面,就能看到對應的檢查項:
本篇文章主要爲你們介紹了 aspnet core 2.2以後所推出的「HealthCheck」,與使用傳統的Controller 公開API進行檢查不一樣,使用「IHealthCheck」可以更快速的進行訪問(畢竟不須要進行模型綁定等操做),並且IHealthCheck
接口可以更好的進行檢查項擴展。讓咱們可以更快更清楚的瞭解到應用程序運行的狀況。
固然,因爲篇幅有限,原本還想繼續拓展IHealthCheckPublisher
接口和健康檢查的實現原理等內容,就放在之後再說吧。若是您對該功能感興趣能夠查看 《ASP.NET Core 中的運行情況檢查》和第三方HealthChecks擴展。
最後,偷偷說一句:創做不易,點個推薦吧.....
原文出處:https://www.cnblogs.com/uoyo/p/12396644.html