Yazılım sistemlerinde arızalar kaçınılmazdır. Bu arızaların nasıl ele alındığı sistem performansını, güvenilirliğini ve işletmenin kârını önemli ölçüde etkileyebilir. Bu yazıda başarısızlığın iyi taraflarını tartışmak istiyorum. Neden başarısızlığı aramalısınız, neden başarısızlık iyidir ve başarısızlıktan kaçınmak neden uygulamanızın güvenilirliğini azaltabilir? Hızlı arıza ve arıza güvenliği arasındaki tartışmayla başlayacağız; bu bizi genel olarak başarısızlıklarla ilgili ikinci tartışmaya götürecek.
Bir ek not olarak, bunun ve bu serideki diğer gönderilerin içeriğini beğendiyseniz, benim
Arızaya dayanıklı sistemler, beklenmeyen bir durumla karşılaşıldığında çalışmayı derhal durduracak şekilde tasarlanmıştır. Bu ani arıza, hataların erkenden yakalanmasına yardımcı olarak hata ayıklamayı daha kolay hale getirir.
Hızlı arıza yaklaşımı, hataların anında yakalanmasını sağlar. Örneğin programlama dilleri dünyasında Java, null
bir değerle karşılaştığında anında NullPointerException
üreterek, sistemi durdurarak ve hatayı netleştirerek bu yaklaşımı somutlaştırıyor. Bu anında yanıt, geliştiricilerin sorunları hızlı bir şekilde tespit edip çözmelerine yardımcı olarak sorunların daha ciddi hale gelmesini önler.
Arıza hızlı sistemler, hataları erken yakalayıp durdurarak, bir hatanın diğerlerine yol açtığı ardışık arıza riskini azaltır. Bu, sorunların sisteme yayılmadan önce kontrol altına alınmasını ve çözülmesini kolaylaştırarak genel istikrarı korur.
Arıza hızlı sistemler için birim ve entegrasyon testleri yazmak kolaydır. Bu avantaj, test başarısızlığını anlamamız gerektiğinde daha da belirgindir. Arıza hızlı sistemler genellikle doğrudan hata yığın izlemesindeki soruna işaret eder.
Ancak hızlı arızalanan sistemler, özellikle üretim ortamlarında kendi risklerini taşır:
Arıza korumalı sistemler farklı bir yaklaşım benimser ve beklenmedik koşullar karşısında bile toparlanmayı ve devam etmeyi amaçlar. Bu onları özellikle belirsiz veya değişken ortamlar için uygun kılar.
Mikro hizmetler, mimarileri aracılığıyla esnekliği benimseyen, arıza korumalı sistemlerin en iyi örneğidir. Hem fiziksel hem de yazılım tabanlı devre kesiciler, ardışık arızaları önlemek için arızalı işlevlerin bağlantısını keserek sistemin çalışmaya devam etmesine yardımcı olur.
Arıza korumalı sistemler, sistemlerin zorlu üretim ortamlarında bile hayatta kalabilmesini sağlayarak ciddi arıza riskini azaltır. Bu, onları özellikle donanım cihazları veya havacılık sistemleri gibi, hatalardan sorunsuz şekilde kurtulmanın çok önemli olduğu görev açısından kritik uygulamalar için uygun hale getirir.
Ancak arıza korumalı sistemlerin dezavantajları vardır:
Her ikisinin de yararları olduğundan, hangi yaklaşımın daha iyi olduğunu belirlemek zordur. Arıza hızlı sistemler anında hata ayıklama, daha düşük ardışık arıza riski ve hataların daha hızlı tespit edilip çözülmesini sağlar. Bu, sorunları erken yakalayıp düzeltmeye yardımcı olur ve yayılmasını önler.
Arıza korumalı sistemler hataları incelikli bir şekilde ele alarak, onları yıkıcı arızaların yıkıcı olabileceği kritik görev sistemleri ve değişken ortamlar için daha uygun hale getirir.
Her yaklaşımın güçlü yönlerinden yararlanmak için dengeli bir strateji etkili olabilir:
Dengeli bir yaklaşım aynı zamanda kodlama, inceleme, araç oluşturma ve test süreçleri boyunca açık ve tutarlı bir uygulama gerektirir ve bunun sorunsuz bir şekilde entegre edilmesini sağlar. Arıza-hızlı düzenleme ve gözlemlenebilirlik ile iyi bir şekilde bütünleşebilir. Etkili bir şekilde bu, arıza güvenliği özelliğini geliştirici katmanı yerine farklı bir OPS katmanına taşır.
İşlerin ilginçleştiği yer burası. Bu, arızaya karşı güvenli ve hızlı arıza arasında seçim yapmakla ilgili değil. Önemli olan onlar için doğru katmanı seçmektir. Örneğin, bir hata, arıza korumalı bir yaklaşım kullanılarak derin bir katmanda ele alınırsa fark edilmeyecektir. Bu sorun olmayabilir, ancak bu hatanın olumsuz bir etkisi varsa (performans, çöp veriler, bozulma, güvenlik vb.), o zaman daha sonra bir sorunla karşılaşırız ve hiçbir ipucumuz olmaz.
Doğru çözüm tüm hataları tek katmanda ele almaktır, modern sistemlerde en üst katman OPS katmanıdır ve en mantıklısıdır. Hatayı, hatayla baş etmeye en yetkili mühendislere rapor edebilir. Ancak aynı zamanda bir hizmeti yeniden başlatmak, ek kaynaklar tahsis etmek veya bir sürümü geri döndürmek gibi anında azaltma da sağlayabilirler.
Geçtiğimiz günlerde konuşmacıların güncel bulut mimarilerini listelediği bir konferanstaydım. Başarısızlık durumunda yeniden denemelerine olanak tanıyan bir çerçeve kullanarak mikro hizmetlere giden kısayolu kullanmayı seçtiler. Ne yazık ki başarısızlık istediğimiz gibi davranmıyor. Yalnızca test yaparak bunu tamamen ortadan kaldıramazsınız. Yeniden deneme hatasız değildir. Aslında felaket anlamına da gelebilir.
Sistemlerini test ettiler ve üretimde bile "çalışıyor". Ancak felaket bir durumun ortaya çıktığını varsayalım, yeniden deneme mekanizmaları kendi sunucularına yönelik bir hizmet reddi saldırısı olarak işleyebilir. Bunun gibi geçici mimarilerin başarısız olabileceği yolların sayısı akıllara durgunluk vericidir.
Başarısızlıkları yeniden tanımladığımızda bu özellikle önemlidir.
Yazılım sistemlerindeki arızalar sadece çökmelerden ibaret değildir. Bir çökme, basit ve ani bir arıza olarak görülebilir ancak dikkate alınması gereken daha karmaşık konular vardır. Aslında konteyner çağındaki çökmeler muhtemelen en iyi başarısızlıklardır. Sistem neredeyse hiç kesinti olmadan sorunsuz bir şekilde yeniden başlatılır.
Veri bozulması bir çökmeden çok daha şiddetli ve sinsidir. Uzun vadeli sonuçlarını da beraberinde taşır. Bozuk veriler, düzeltilmesi zor olan, kapsamlı yeniden çalışma gerektiren ve potansiyel olarak kurtarılamayan veriler gerektiren güvenlik ve güvenilirlik sorunlarına yol açabilir.
Bulut bilişim, devre kesiciler ve yeniden denemeler gibi defansif programlama tekniklerine yol açarak, arızaları zarif bir şekilde yakalayıp ele almak için kapsamlı test ve günlük kaydına ağırlık verdi. Bu ortam bir bakıma kalite açısından bizi geri gönderdi.
Veri düzeyinde hızlı çalışan bir sistem bunun olmasını engelleyebilir. Bir hatayı ele almak basit bir düzeltmenin ötesine geçer. Bunun temel nedeninin anlaşılması ve yeniden ortaya çıkmasının önlenmesi, kapsamlı günlük kaydı, test ve süreç iyileştirmelerine kadar genişletilmesi gerekir. Bu, hatanın tam olarak ele alınmasını sağlar ve tekrarlanma olasılığını azaltır.
Üretimde bir hata varsa ve üretimi anında geri döndüremiyorsanız muhtemelen geri dönmelisiniz. Bu her zaman mümkün olmalı ve eğer mümkün değilse bu üzerinde çalışmanız gereken bir şeydir.
Bir düzeltme yapılmadan önce arızaların tam olarak anlaşılması gerekir. Kendi şirketlerimde, affedilebilir küçük bir girişimde, baskı nedeniyle bu adımı sıklıkla atladım. Daha büyük şirketlerde temel nedeni anlamamız gerekir. Hatalar ve üretim sorunları hakkında bilgi alma kültürü esastır. Düzeltme aynı zamanda benzer sorunların üretime ulaşmasını engelleyen süreç azaltmayı da içermelidir.
Arıza hızlı sistemlerde hata ayıklamak çok daha kolaydır. Doğaları gereği daha basit bir mimariye sahiptirler ve belirli bir alandaki bir sorunu tespit etmek daha kolaydır. Küçük ihlaller (örn. doğrulamalar) için bile istisnalar oluşturmak çok önemlidir. Bu, gevşek sistemlerde ortaya çıkan ardışık hata türlerini önler.
Bu, tanımladığımız sınırları doğrulayan ve uygun istisnaların atıldığını doğrulayan birim testleriyle daha da güçlendirilmelidir. Hata ayıklamayı son derece zorlaştırdıklarından ve doğru yerleri OPS katmanında olduğundan kodda yeniden denemelerden kaçınılmalıdır. Bunu daha da kolaylaştırmak için zaman aşımlarının varsayılan olarak kısa olması gerekir.
Başarısızlık kaçınabileceğimiz, tahmin edebileceğimiz veya tamamen test edebileceğimiz bir şey değildir. Yapabileceğimiz tek şey, bir arıza meydana geldiğinde darbeyi yumuşatmaktır. Genellikle bu "yumuşatma", uygulamalarımızın zayıf noktalarını bulma hedefiyle aşırı koşulları mümkün olduğunca çoğaltmayı amaçlayan uzun süreli testler kullanılarak elde edilir. Bu nadiren yeterlidir. Sağlam sistemlerin çoğu zaman bu testleri gerçek üretim hatalarına göre revize etmesi gerekir.
Arıza güvenliğine harika bir örnek, bir hizmet kapalıyken bile çalışmaya devam etmemizi sağlayan REST yanıtlarının önbelleği olabilir. Ne yazık ki bu, önbellek zehirlenmesi gibi karmaşık niş sorunlara veya yasaklı bir kullanıcının önbellek nedeniyle hâlâ erişime sahip olduğu bir duruma yol açabilir.
Arıza güvenliği en iyi şekilde yalnızca üretim/hazırlamada ve OPS katmanında uygulanır. Bu, üretim ve geliştirme arasındaki değişiklik miktarını azaltır; bunların mümkün olduğunca benzer olmasını istiyoruz, ancak bu yine de üretimi olumsuz etkileyebilecek bir değişiklik. Bununla birlikte, gözlemlenebilirlik sistem arızalarının net bir resmini elde edebildiğinden faydaları çok büyüktür.
Buradaki tartışma, gözlemlenebilir bulut mimarileri oluşturma konusundaki daha yeni deneyimim nedeniyle biraz renklendi. Ancak aynı prensip, ister gömülü ister bulutta olsun, her türlü yazılım için geçerlidir. Bu gibi durumlarda genellikle kodda arızaya karşı korumayı uygulamayı tercih ederiz; bu durumda bunu tutarlı ve bilinçli bir şekilde belirli bir katmanda uygulamanızı öneririm.
Ayrıca bu durumlarda genellikle tutarsız ve kötü belgelenmiş davranışlar sağlayan özel bir kitaplık/çerçeve durumu da vardır. Bazı çalışmalarımda bu tür tutarsızlıklardan ben de suçluyum. Yapılması kolay bir hata.
Bu, hata ayıklama hakkındaki kitabımın/kursumun bir parçası olan hata ayıklama teorisi serisi hakkındaki son yazımdır. Hata ayıklamayı genellikle bir şey başarısız olduğunda gerçekleştirdiğimiz eylem olarak düşünürüz. Değil. Hata ayıklama, kodun ilk satırını yazdığımız anda başlar. Kodlama yaparken hata ayıklama sürecini etkileyecek kararlar veririz, genellikle başarısızlıkla karşılaşana kadar bu kararların farkında olmayız.
Umarım bu yazı ve seri bilinmeyene yönelik hazırlanmış kod yazmanıza yardımcı olur. Hata ayıklama doğası gereği beklenmeyen durumlarla ilgilenir. Testler yardımcı olamaz. Ancak daha önceki yazılarımda da belirttiğim gibi, hazırlanmayı kolaylaştıracak birçok basit uygulama var. Bu tek seferlik bir süreç değil, başarısızlıkla karşılaştığımızda alınan kararların yeniden değerlendirilmesini gerektiren yinelenen bir süreçtir.