AspNetCore HealthChecks, Sesimi duyan var mı? Ölü ya da diri !!!

Adem Olguner
Devops Türkiye☁️ 🐧 🐳 ☸️
8 min readJul 18, 2020

--

GİRİŞ

Uygulamalarımızın yazılması süreci sonrası yayına alınması ile yüzde 50’lik kısmını başarmış sayılıyoruz, diğer yüzde 50'lik kısım ise uygulamalarımızın devamlılığını ve sağlıklı bir şekilde devam edebilmesini sağlamak. Hangi mimari yaklaşımla yazarsak yazalım, hangi programlama dili kullanırsak kullanalım “uygulamalarımızın sağlıklı bir şekilde devamlılığını sağlamak” ortak bir dikkat ve endişe noktamızdır.

Uygulamalarımızın sağlıklı bir şekilde devamlılığını sağlamak için belirli periyotlarda kontrollerini ve bakımlarını sağlamaya çalışıyoruz. Bazen hata (bug) oluştuğunda, bazen sistemde bir yavaşlık olduğunda, bazen kurguladığımız arka plan işlemleri halletmesi gereken işleri halletmediği zaman fark edebiliyoruz, ancak izleyemiyoruz. İste tam bu noktada HealthCkeck burada bizim imdadımıza yetişiyor.

HealthChecks .net core 2.2 ile hayatımıza giriş yaptı, .net core 3.1 ile olgunlaşan bir yapısı kavuştuğunu söyleyebiliriz.

Dağıtık bir yapımızın olduğunu ve uygulamalarımızın içinde onlarca yada yüzlerce servis olduğunu, birden çok veri tabanına bağlantı kurduğumuzu, mail gönderimi için SMTP sunucumuzun olduğunu, arka planda çalışan kuyruk (queue) işlemlerimizin olduğunu düşünelim. Bu ve buna benzer şekilde mimarimizi destekleyen ve uygulamamızın veya uygulamlarımızın stabil bir şekilde çalışmasını sağlayan işlemlerimizin olduğunu hayal edelim. Bu durumda herhangi bir problemde hangi sebepten dolayı hangi işlem yapması gereken işlemi yapmadığını kontrol etmek için çok fazla argümanımız var. Hepsini aynı anda kontrol edebilmek gittikçe zorlaşır. İşte bu ihtiyaçtan meydana çıkmış ve tüm servislerin durumlarını kontrol eden yapıyı Health Check olarak tanımlayabiliriz.

Tüm bunların dışında, daha farklı kontrol mekanizmalarının da olduğunu bilmenizi isterim.

Health Checks

Sql Server
MySql
Oracle
Sqlite
RavenDB
Postgres
EventStore
RabbitMQ
IbmMQ
Elasticsearch
Solr
Redis
System: Disk Storage, Private Memory, Virtual Memory, Process, Windows
Service
Azure Service Bus: EventHub, Queue and Topics
…….

Health Check ile ilgili işlemler listesini buradan inceleyebilirsiniz.

Her zaman olduğu gibi, teknolojileri teknik olarak anlatmak yerine kod yazarak, kodu düzenleyerek, konfigürasyonlarını yaparak ve hatta bazen özelleştirerek yapma alışkanlığımı devam ettirmek istiyorum. HealthCkecks işlemlerimi için bir proje oluşturup kodlarımızı yazıp, kodların ne anlama geldiğini hangi işlemleri yaptığını ve sonuçlarını görerek devam edeceğiz.

PROJE ☸️

  • Create a new Asp.Net Core Web Application — API (3.0) seçelim.
API Project Asp.Net Core 3.0
API solution

Bir sonraki adımda Nuget paketlerinin yüklenmesi işlemini gerçekleştirelim. Nuget paketlerini yeri geldikçe ve lazım oldukça yükleyip hangi işlemlerin hangi paket içerisinde olduğunuda görmüş olacağız.

Microsoft.AspNetCore.Diagnostics.HealthChecks (v3.0.0)

Microsoft.Extensions.Diagnostics.HealthChecks 3.0.0

Konfigürasyon işlemleri için startup.cs içerisine gidelim. ConfigureServices metodu içerisinde HealthCheck’i ekleyelim.

ConfigureServices — services.AddHealthChecks()

Startup.cs içerisinde Configure metodu içerisinde de HealthCheck’i ekleyelim ve PathString değerini belirleyelim.

PathString : ”/AdemOlguner-HealthChecks

  • Healthy: Her hangi problem yaşanmaz ve cevap dönerse dönmektedir.
  • Unhealthy: Cevap başarılı olmazsa cevap dönmektedir.
  • Degraded: Cevap başarılı fakat belirlenen sürede dönmezse bu cevap dönmektedir.

Health check output’u default olarak “text/plain” dir. Bu nedenle sadece “Healthy” veya “Unhealthy” gibi bir response görürüz. Tüm bağımlılıklar dahil edilmiş detaylı bir health check output’u görebilmek için ise “HealthCheckOptions” üzerinden “ResponseWriter” özelliği ile özelleştirmemiz gerekmektedir.

Custom Response Ekran Görüntüsü

UIResponseWriter ?

HealthChecks varsayılan olarak HealthReport verileri olmadan basit bir Durum Kodu (200 veya 503) döndürüyor. Diğer tüm durum kodlarını etkinleştirmek için ResponseWriter nesnesine ihtiyaç duyarız.

Özel bir kod yazmamak için ise, “AspNetCore.HealthChecks.UI.Client” paketi ile gelen “UIResponseWriter.WriteHealthCheckUIResponse” sınıfını kullanabiliriz.

Bunun için öncelikle projeye “AspNetCore.HealthChecks.UI” paketini NuGet üzerinden dahil edelim.

Nuget paket yöneticisinden AspNetCore.HealthChecks.UI(v3.0.0) kuralım.

using HealthChecks.UI.Client; ekleylim.

Ardından HealthChecks konfigürasyonun ayarlarını değiştirelim.

Görselleştirelim — Health Check UI

HealthChecks response olarak json formatta veriyi dönmesi için ayarladık. Ancak burada kullanacağımız işlemler sonrasında buradaki json format cok okunabilir bir veri olmayacaktır. HealthChecks’in sunmuş olduğu arayüzü kullanacağız.

ConfigureServices metodu içerisinde AddHealthChecksUI ekleyelim.

services.AddHealthChecksUI()

Configure metodu içerisinde UseHealthChecksUI ekleyelim.

Uygulamamızı ayağa kaldırdığımızda AdemOlguner-HealthChecks route ile ayağa kalkacaktır. UI tarafına geçmek için UseHealthChecksUI options olarak ayarladığımız adresten ayağa kalkacaktır.

options.UIPath = “/AdemOlguner-HealthChecks-ui

HealthChecks UI tarafı için bazı ayarlamaları (appsettings.json) yapmamız gerekiyor.

Uri: Şu an çalışan (API) uygulamamızın adresi olmalı !!!

appsettings.json-HealthChecksUI

appsetting.json dosyamızda ayarlamalarımızı yaptıktan sonra arayüzü tekrar ayağa kaldırdığımızda karşılaşacağımız ekran alttaki gibi olacaktır. Tanımlı bir operasyonumuz olmadığı için boş görüntülenmektedir.

Özelleştirmeler ve IHealthCheck

Ilk örneğimizi bir veritabanı (sql) bağlantısı için yapacağız. Desteklenen çeşitli veritabanı bağlantıları için altta bulunan resme bakabiliriz.

https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks

Nuget paket yöneticisinden alttaki paketin kurulumunu yapalım.

AspNetCore.HealthChecks.SqlServer

Veritabanı ile ilgili connection bilgilerini appsetting.json dosyasından okuyacak şekilde düzenliyoruz. Ben burada veritabanı tipleri için ayrı ayrı düzenleme yaptım burada tamamen özgürsünüz nasıl kolayınıza geliyorsa o şekilde ayarlama yapabilirsiniz.

HealthChecks servisimize AddSqlServer ekliyoruz ve gerekli konfigürasyon ayarlarını yapalım.

Uygulamamızı çalıştıralım ve dönen datayı inceleyelim.

Uygulamamızın UI tarafına ( “/AdemOlguner-HealthChecks-ui” ) geçelim.

Veritabanına bağlantısı için timeout süresi tanımladım 5 dk olarak. TimeSpan.FromMinute(5). Arayüzden baktığımızda bağlantı ile ilgili olarak Duration başlığı altında 00:00:00: 0255691 olarak görüntülenmektedir. Yani bizim tanımladığımız 5 dk dan daha az bir zamanda bağlantı sağladığı için Healthy olarak dönüş sağlamıştı. Şimdi bu timeout süresini değiştirerek sonucun değişip değişmediğini görelim.

timeout: TimeSpan.FromMilliseconds(5))

Burada sadece Sql Servera bağlanmak değil, bağlantı süremiz içinde kontrol sağlayabildiğimizi görebiliyoruz.

Bir başka husus olarak .AddSqlServer() işlemini kendi HealthCheck nesnemizi oluşturarakta yapabiliriz. Bunun için IHealthCheck soyut (interface) sınıfını miras alıp, implemente edilen metodun içeriğini doldurarak yapabiliriz.

Kendi HealthCheck sınıflarımızı .AddCheck<T>(“name”) şeklinde ekleyebiliriz.

EgitimPortalHealthChecksProvider adında bir class oluşturup IHealthCheck interface nesnesini miras alıyorum. CheckHealthAsync isminde bir metod implemente ettiğini görüyoruz bu metodun geri dönüş tipi HealthCheckResult türündedir.

Ek olarak Healthy-UnHealthy-Degraded olarak tanımlanan 3 tip vardı. AddSqlServer olarak eklediğimiz HealthCheck response olarak Healthy-UnHealthy olarak dönmektedir. Ancak özel olarak tanımladığımız IHealthCheck nesnelerinde duruma göre Degraded alanlarını da kullanabiliriz.

Özelleştirdiğimiz HealthCheck sınıfınıda eklediğimizde iki ayrı check işlemi yapalım ve sonuçları inceleyelim.

PingHealthCheck

Belirli bir adrese ping atarak ping atılan adrese erişilip erişilmediği, istenilen sürede erişilebildiği gibi işlemleri yapalım.

Gerekli olan nuget paket yükleyelim.

AspNetCore.HealthChecks.Network

Google adresine ping atalım. google.com adresine 200 ms de erişilip erilmeyeceği çeklinde bir ping atıyoruz.

Dinamik hale getirelim. Kendi HealthChecks sınıfımızı yazalım ve bir adet Ping işlemi için PingHealthCheckProvider sınıfı oluşturalım. Bu sınıf iki ayrı parametre alsın(adres ve süre). Bu şekilde tüm PingHealthChecks işlemlerimizi bu sınıf üzerinden gerçekleştirebiliriz.

Şimdi 3 ayrı ping atalım ve farklı şartlarda bize nasıl bir sonuç döndüğünü inceleyelim.

Bu ve buna benzer şekilde özel HealthCheks oluşturarak kontrollerimizi çoğaltabiliriz.

Custom HealthCheck Middleware

Startup.cs dosyasında HealthCheck için yaptığımız eklemeler ve ayarlardan sonra startup.cs dosyasının okunurluluğuda biraz zorlaştı, gelin bir bu kod karmaşıklığını ortadan kaldıralım.

Middlewares adında bir klasör açıp içerisine CustomHealthChecksMiddleware.cs adında static bir class oluşturalım. Geriye IHealthChecksBuilder türünde veri dönen AddCustomHealthChecksMiddleware adında static metot oluşturalım.

Metodun içeriğini startup.cs de olduğu gibi dolduralım.

startup.cs dosyasını tekrar düzenleyelim.

ÖZELLEŞTİRME İŞLEMLERİ

HealthChecks içerisinde bize bazı konfigürasyon ayarlamalarını yapabilme imkanı sunar.

HealthChecks appsetting.json dosyasında refresh time için ayarlama yapmıştık, arayüzden bunu değiştirme şansımız da bulunuyor.

  • Max endpoint sayısı belirleyebiliriz.
  • Özel Arayüz Tasarımı

Bir yazımızın daha sonuna geldik. HealthChecks ile benim anlatacaklarım bu kadar, ancak kendi github ve dökümantasyon sayfasını inceleyerek daha detaylı bilgi ve örneklerden faydalanabilirsiniz.

Umarım faydalı olmuştur.

Başka bir konu ile görüşmek dileğiyle.

Eleştiri en faydalı besin kaynağıdır benim için.

Kaynak kodlara bu adresten ulaşabilirsiniz.

--

--