Merhaba arkadaşlar.
Bu makale konumda sizlere Trendyol.com çatısı altında geliştirip, bazı uygulamalarımızda kullandığımız Loki kütüphanesinden bahsetmek istiyorum.
Loki’yi kısaca tanımlamak gerekirse:
Distributed sistemler üzerinde kolay bir şekilde lock işlemlerini handle etmeye yarayan bir library’dir.
Loki’yi biraz daha açmak gerekirse eğer, shared bir resource üzerinden işlem yapan uygulamalarımız var ise ve bu uygulamalarımızı performans ve network split problemlerinden dolayı kolay bir yoldan scale etmek istiyorsak, işte bu noktada bize yardımcı olmaktadır.
Loki’nin çalışma mantığı aslında oldukça basit. Sizden sadece querying yaptığınız kısımı, “Locking.Instance.ExecuteWithinLock” method’u ile wraplemenizi istemektedir. Loki, şuan altyapısında primary locking handler olarak Redis ile çalışmaktadır. Secondary locking handler olarak ise MSSQL implementasyonu bulunmaktadır. Loki’nin gerçekleştirdiği işlem ise wrap’lenen code bloğunu execute etmeden önce, initialize sırasında belirteceğimiz bir “serviceKey” ile Redis locking handler’ı üzerinde bir key persist etmektedir. Eğer key’i persist edebildi ise ilgili code bloğunu execute etmektedir ve işlem sonunda ise ilgili key’i Redis üzerinden kaldırmaktadır. Dolayısıyla key’i persist edemez ise, bu key ile ilgili bir işlem sürdüğünü anlamaktadır ve ilgili code bloğunu execute etmemektedir.
Secondary kısmına geçmeden önce dilerseniz bir sequence diyagramına bakalım.
Burada primary olan Redis üzerine gelen “Lock()” ve “Release()” isteklerine dikkat çekmek istiyorum.
Yukarıdaki senaryolar doğrultusunda x bir uygulama n tane makine üzerinde çalışırken, aynı datalar üzerinde işlem yapmadan kolay bir şekilde multiple olarak distributed çalışmaları sağlanmış oluyor. Tabi bunun için ilgili business doğrultusunda işlediğiniz dataları, bir şekilde flaglemeniz gerekmektedir.
Şuan nuget.org üzerinde iki adet paket mevcuttur. Bunlardan birisi “LokiNet” diğeri ise “LokiNet.MSSQL” paketleridir. Nuget Package Manager üzerinden erişebilir ve kurulumu gerçekleştirebilirsiniz. Loki’nin kullanımı, mantığında da olduğu gibi gayet basit. İlk olarak uygulama ayağa kalkarken, “LokiConfigurationBuilder” ile aşağıdaki gibi initialize etmek gerekiyor.
List<EndPoint> redisEndPoints = new List<EndPoint> { new DnsEndPoint("redisUri", redisPort) }; LokiConfigurationBuilder.Instance.SetServiceKey("SimpleTestClient") .SetPrimaryLockHandler(new RedisLokiLockHandler(redisEndPoints.ToArray())) .Build();
Loki’ye burada “SimpleTestClient” key’i ile lock işlemlerini gerçekleştirmesi gerektiğini, “SetPrimaryLockHandler()” method’u ile de lock işlemlerini Redis üzerinden gerçekleştirmesi gerektiğini söylüyoruz. Secondary handler set etme mecburiyeti bulunmamakta fakat mevcutta bulunan MSSQL locking handler’ı da kullanmak isterseniz eğer:
LokiConfigurationBuilder.Instance.SetServiceKey("SimpleTestClient") .SetPrimaryLockHandler(new RedisLokiLockHandler(redisEndPoints.ToArray())) .SetSecondaryLockHandler(new MSSQLLokiLockHandler("connectionString")) .Build();
şeklinde configure etmeniz yeterli olacaktır. Bununla birlikte MSSQL handler’ı için ihtiyaç duyacağı tablo script’i ise aşağıdaki gibidir.
CREATE TABLE [dbo].[LokiLockings]( [ServiceKey] [varchar](50) NOT NULL, [CreationDate] [datetime] NOT NULL, CONSTRAINT [PK_LokiLockings] PRIMARY KEY CLUSTERED ( [ServiceKey] ASC ))
Initialization işlemleri bu kadar. Artık tek yapmamız gereken uygulamamızdaki business akışına göre ister function bazında ister application bazında locking işlemini gerçekleştirmektedir.
Bunun için ise “Locking.Instance.ExecuteWithinLock()” method’unu aşağıdaki gibi kullanmamız yeterli olacaktır.
Locking.Instance.ExecuteWithinLock(() => { //do somethings.. }, expiryFromSeconds: 2);
“expiryFromSeconds” parametresi ile ise, isminden de anlaşılabileceği üzere ilgili lock işleminin belirli bir saniye sonunda otomatik olarak release olması sağlanmaktadır.
Bunlar dışında eğer secondary olarak sizde farklı bir persistence store kullanmak istiyorsanız, tek yapmanız gereken “LokiLockHandler” base class’ını aşağıdaki gibi inherit edecek yeni bir handler yazmaktır.
public class FooLockHandler : LokiLockHandler { public override bool Lock(string serviceKey, int expiryFromSeconds) { //Lock operations } public override void Release(string serviceKey) { //Release operations } }
Proje geliştirmeye açık olup, sizler de github üzerinden katkıda bulunabilirsiniz.
Umarım keyifli bir makale konusu olmuştur.
Proje adresi: https://github.com/GokGokalp/Loki
{:tr} Makalenin ilk bölümünde, Software Supply Chain güvenliğinin öneminden ve containerized uygulamaların güvenlik risklerini azaltabilmek…
{:tr}Bildiğimiz gibi modern yazılım geliştirme ortamında containerization'ın benimsenmesi, uygulamaların oluşturulma ve dağıtılma şekillerini oldukça değiştirdi.…
{:tr}Bildiğimiz gibi bir ürün geliştirirken olabildiğince farklı cloud çözümlerinden faydalanmak, harcanacak zaman ve karmaşıklığın yanı…
{:tr}Bazen bazı senaryolar vardır karmaşıklığını veya eksi yanlarını bildiğimiz halde implemente etmekten kaçamadığımız veya implemente…
{:tr}Bildiğimiz gibi microservice architecture'ına adapte olmanın bir çok artı noktası olduğu gibi, maalesef getirdiği bazı…
{:tr}Bir önceki makale serisinde Dapr projesinden ve faydalarından bahsedip, local ortamda self-hosted mode olarak .NET…
View Comments
Selamlar Gökhan,
Yazını çok beyendim. Siteni yeni keşfettim. Valla konular da çok güzel. Eline sağlık. Böyle güzel içerikleri bence daha çok tanıtmalısın ki herkes görsün. Mesela Twitter'ını bulamadım :)
İyi çalışmalar. Hoşçakal..
Selam Bora,
Teşekkür ederim öncelikle yorumun için, vakit buldukça yazmaya çalışıyorum. :) Tanıtım konusunda haklısın. Twitter'ım var fakat biraz goygoy için kullandığımdan dolayı orada paylaşamıyorum pek.:) Sadece Linkedin ve bir kaç Facebook grubu...
Merhaba,
Lock istegi fail edince neden skip ettigini anlamadim. Lock isteyen taraf lock'u alana kadar bekler normalde. Orada fail yerine wait until lock falan gibi bisey olmasi gerekmez miydi ?
Bir de ayni olmayan data uzerinde lock ihtiyaci icin bir real life example cok seker olur.
Merhaba Veysel bey, teşekkür ederim yorumunuz için.
Aslında Loki'nin ilk versiyonunda lock alamama durumunda, lock tekrardan available olana kadar bekleme olayı vardı. Fakat kullandığımız pakette senaryomuza uymayan bir durum oluştuğu için kaldırmak zorunda kaldık. Bu paket üzerinde custom olarak tekrardan implemente edilebilir. Sizlerde GitHub üzerinden contribution'da bulunabilirseniz mutlu oluruz.
İyi günler dilerim.