![Search icon](https://hackernoon.imgix.net/search-new.png?w=19&h=19)
Proqram təminatında dayanıqlıq, gözlənilməz problemlər və ya uğursuzluqlar qarşısında belə tətbiqin rəvan və etibarlı şəkildə işləməyə davam etmək qabiliyyətinə aiddir. Fintech layihələrində davamlılıq bir neçə səbəbə görə xüsusilə yüksək əhəmiyyət kəsb edir. Birincisi, şirkətlər tənzimləyici tələblərə cavab verməyə borcludurlar və maliyyə tənzimləyiciləri sistem daxilində sabitliyi qorumaq üçün əməliyyat davamlılığını vurğulayır. Bundan əlavə, rəqəmsal alətlərin yayılması və üçüncü tərəf xidmət təminatçılarına etibar Fintech bizneslərini yüksək təhlükəsizlik təhdidlərinə məruz qoyur. Dayanıqlıq həmçinin kiber təhdidlər, pandemiyalar və ya geosiyasi hadisələr kimi müxtəlif amillərin yaratdığı kəsilmə risklərini azaltmağa, əsas biznes əməliyyatlarını və kritik aktivləri qorumağa kömək edir.
Davamlılıq nümunələri ilə biz proqram təminatının pozulmalara tab gətirə bilməsini və əməliyyatlarını davam etdirməsini təmin etmək üçün nəzərdə tutulmuş ən yaxşı təcrübə və strategiyalar toplusunu başa düşürük. Bu nümunələr təhlükəsizlik şəbəkələri kimi fəaliyyət göstərir, səhvləri idarə etmək, yükü idarə etmək və uğursuzluqlardan sonra bərpa etmək üçün mexanizmlər təmin edir və bununla da tətbiqlərin mənfi şərtlərdə möhkəm və etibarlı qalmasını təmin edir.
Ən çox yayılmış dayanıqlıq strategiyalarına aralıq, önbellek, geri qaytarma, təkrar cəhd və dövrə açarı daxildir. Bu yazıda mən onları həll etməyə kömək edə biləcək problemlərin nümunələri ilə daha ətraflı müzakirə edəcəyəm.
Yuxarıdakı parametrə nəzər salaq. Bəzi məlumatları əldə etmək üçün arxamızda bir neçə arxa tərəfi olan çox adi bir tətbiqimiz var. Bu backendlərə qoşulmuş bir neçə HTTP müştərisi var. Məlum oldu ki, onların hamısı eyni əlaqə hovuzunu paylaşır! Həm də CPU və RAM kimi digər resurslar.
Backendlərdən biri yüksək sorğu gecikməsi ilə nəticələnən bir sıra problemlərlə üzləşsə nə olacaq? Yüksək cavab vaxtına görə, bütün əlaqə hovuzu backend1-dən cavab gözləyən sorğularla tam məşğul olacaq. Nəticədə, hovuz tükəndiyi üçün sağlam backend2 və backend3 üçün nəzərdə tutulan sorğular davam edə bilməyəcək. Bu o deməkdir ki, arxa planlarımızdan birində uğursuzluq bütün tətbiqdə uğursuzluğa səbəb ola bilər. İdeal olaraq, tətbiqin qalan hissəsi normal işləməyə davam edərkən, yalnız uğursuz backend ilə əlaqəli funksionallığın deqradasiyaya uğramasını istəyirik.
Bulkhead Pattern nədir?
Bulkhead nümunəsi termini gəmiqayırma sözündən götürülmüşdür və gəmi daxilində bir neçə təcrid olunmuş bölmələrin yaradılmasını nəzərdə tutur. Bir bölmədə sızma baş verərsə, o, su ilə doldurulur, lakin digər bölmələr təsirsiz qalır. Bu izolyasiya bütün gəminin tək bir pozuntuya görə batmasının qarşısını alır.
Bulkhead nümunəsi proqram daxilində müxtəlif növ resursları təcrid etmək üçün istifadə oluna bilər, bir hissədəki nasazlığın bütün sistemə təsir etməsinin qarşısını alır. Bunu problemimizə necə tətbiq edə bilərik:
Tutaq ki, bizim backend sistemlərimiz fərdi olaraq səhvlərlə qarşılaşma ehtimalı azdır. Bununla belə, əməliyyat bütün bu arxa uçları paralel olaraq sorğulamağı nəzərdə tutduqda, hər biri müstəqil olaraq səhv qaytara bilər. Bu səhvlər müstəqil şəkildə meydana gəldiyi üçün, tətbiqimizdəki səhvin ümumi ehtimalı hər hansı bir arxa uçun səhv ehtimalından yüksəkdir. Kumulyativ xəta ehtimalı P_total=1−(1−p)^n düsturu ilə hesablana bilər, burada n arxa sistemlərin sayıdır.
Məsələn, hər birinin xəta ehtimalı p=0,001 olan on arxa tərəfimiz varsa (99,9% SLA-a uyğundur), nəticədə səhv ehtimalı belədir:
P_cəmi=1−(1−0,001)^10=0,009955
Bu o deməkdir ki, bizim birləşmiş SLA-mız təxminən 99%-ə enir, bu, paralel olaraq birdən çox backend sorğusu zamanı ümumi etibarlılığın necə azaldığını göstərir. Bu problemi azaltmaq üçün yaddaşdaxili keşi tətbiq edə bilərik.
Yaddaşdaxili keş tez-tez əldə edilən məlumatları saxlayaraq və hər dəfə potensial yavaş mənbələrdən onu əldə etmək ehtiyacını aradan qaldıraraq yüksək sürətli məlumat buferi kimi xidmət edir. Yaddaşda saxlanılan keşlərin şəbəkə üzərindən məlumatların alınması ilə müqayisədə səhv ehtimalı 0% olduğundan, onlar tətbiqimizin etibarlılığını əhəmiyyətli dərəcədə artırır. Üstəlik, keşləmə şəbəkə trafikini azaldır, xəta şansını daha da azaldır. Nəticə etibarilə, yaddaşdaxili keşdən istifadə etməklə, arxa sistemlərimizlə müqayisədə tətbiqimizdə daha da aşağı xəta nisbətinə nail ola bilərik. Bundan əlavə, yaddaşdaxili keşlər şəbəkəyə əsaslanan yükləmədən daha sürətli məlumat əldə etməyi təklif edir və bununla da tətbiqin gecikmə müddətini azaldır - bu, nəzərəçarpacaq üstünlükdür.
İstifadəçi profilləri və ya tövsiyələr kimi fərdiləşdirilmiş məlumatlar üçün yaddaşdaxili keşlərdən istifadə də yüksək effektiv ola bilər. Lakin biz istifadəçidən gələn bütün sorğuların onlar üçün keşlənmiş verilənlərdən istifadə etmək üçün ardıcıl olaraq eyni proqram nümunəsinə getməsini təmin etməliyik ki, bu da yapışqan seanslar tələb edir. Yapışqan sessiyaların həyata keçirilməsi çətin ola bilər, lakin bu ssenari üçün kompleks mexanizmlərə ehtiyacımız yoxdur. Kiçik trafikin yenidən balanslaşdırılması məqbuldur, buna görə də ardıcıl hashing kimi sabit yük balanslaşdırma alqoritmi kifayət edəcəkdir.
Bundan əlavə, node nasazlığı halında, ardıcıl heşinq yalnız uğursuz node ilə əlaqəli istifadəçilərin yenidən balanslaşdırmaya məruz qalmasını təmin edir və sistemdə pozulmaları minimuma endirir. Bu yanaşma fərdiləşdirilmiş keşlərin idarə edilməsini asanlaşdırır və tətbiqimizin ümumi sabitliyini və performansını artırır.
Keşləməyi planlaşdırdığımız məlumatlar kritikdirsə və sistemimizin idarə etdiyi hər sorğuda istifadə olunursa, məsələn, giriş siyasətləri, abunə planları və ya domenimizdəki digər mühüm obyektlər - bu məlumatların mənbəyi sistemimizdə əhəmiyyətli bir uğursuzluq nöqtəsi yarada bilər. Bu problemi həll etmək üçün bir yanaşma bu məlumatları birbaşa tətbiqimizin yaddaşına tam şəkildə təkrarlamaqdır.
Bu ssenaridə, mənbədəki məlumatların həcmi idarə edilə biləndirsə, tətbiqimizin başlanğıcında bu məlumatın snapshotunu endirməklə prosesi başlada bilərik. Sonradan, keşlənmiş məlumatların mənbə ilə sinxronizasiya olunmasını təmin etmək üçün yeniləmə hadisələri ala bilərik. Bu metodu tətbiq etməklə biz bu mühüm məlumatlara daxil olmağın etibarlılığını artırırıq, çünki hər bir axtarış 0% səhv ehtimalı ilə birbaşa yaddaşdan baş verir. Bundan əlavə, məlumatların yaddaşdan çıxarılması olduqca sürətlidir və bununla da tətbiqimizin işini optimallaşdırır. Bu strategiya xarici məlumat mənbəyinə güvənməklə bağlı riski effektiv şəkildə azaldır, tətbiqimizin fəaliyyəti üçün kritik məlumatlara ardıcıl və etibarlı çıxışı təmin edir.
Bununla belə, tətbiqin işə salınması ilə bağlı məlumatların endirilməsi və bununla da işə salınma prosesinin gecikdirilməsi zərurəti tətbiqin sürətli işə salınmasını müdafiə edən “12 faktorlu proqram” prinsiplərindən birini pozur. Lakin, biz keşləmədən istifadənin üstünlüklərini itirmək istəmirik. Bu dilemmanı həll etmək üçün gəlin potensial həll yollarını araşdıraq.
Sürətli başlanğıc, xüsusən də müxtəlif fiziki qovşaqlara sürətli tətbiq miqrasiyasına əsaslanan Kubernetes kimi platformalar üçün çox vacibdir. Xoşbəxtlikdən, Kubernetes başlanğıc zondları kimi xüsusiyyətlərdən istifadə edərək yavaş başlayan tətbiqləri idarə edə bilir.
Qarşılaşa biləcəyimiz digər problem proqram işləyərkən konfiqurasiyaları yeniləməkdir. İstehsal problemlərini həll etmək üçün tez-tez keş vaxtlarını və ya sorğu müddətlərini tənzimləmək lazımdır. Yenilənmiş konfiqurasiya fayllarını tez bir zamanda tətbiqimizə yerləşdirə bilsək belə, bu dəyişiklikləri tətbiq etmək adətən yenidən başlamağı tələb edir. Hər bir tətbiqin uzadılmış işə salınma vaxtı ilə, yuvarlanan yenidən başlatma istifadəçilərimiz üçün düzəlişlərin tətbiqini əhəmiyyətli dərəcədə gecikdirə bilər.
Bunu həll etmək üçün bir həll konfiqurasiyaları paralel dəyişəndə saxlamaq və onu vaxtaşırı yeniləməkdir. Bununla belə, müəyyən parametrlər, məsələn, HTTP sorğusu fasilələri, potensial problem yaradaraq, müvafiq konfiqurasiya dəyişdikdə HTTP və ya verilənlər bazası müştərilərinin yenidən işə salınmasını tələb edə bilər. Bununla belə, Java üçün Cassandra sürücüsü kimi bəzi müştərilər konfiqurasiyaların avtomatik yenidən yüklənməsini dəstəkləyir və bu prosesi asanlaşdırır.
Yenidən yüklənə bilən konfiqurasiyaların tətbiqi uzun tətbiqi işə salma vaxtlarının mənfi təsirini azalda bilər və funksiyaların tətbiqini asanlaşdırmaq kimi əlavə üstünlüklər təklif edə bilər. Bu yanaşma bizə konfiqurasiya yeniləmələrini səmərəli idarə edərkən tətbiqin etibarlılığını və cavabdehliyini qoruyub saxlamağa imkan verir.
İndi başqa bir problemə nəzər salaq: sistemimizdə istifadəçi sorğusu backend və ya verilənlər bazasına sorğu göndərilərək qəbul edildikdə və emal edildikdə, bəzən gözlənilən məlumat əvəzinə səhv cavabı alınır. Daha sonra sistemimiz istifadəçiyə “xəta” ilə cavab verir.
Bununla belə, bir çox ssenarilərdə istifadəçini böyük qırmızı xəta mesajı ilə tərk etməkdənsə, bir qədər köhnəlmiş məlumatları, məlumatın yenilənməsində gecikmə olduğunu göstərən mesajla birlikdə göstərmək daha məqsədəuyğun ola bilər.
Bu problemi həll etmək və sistemimizin davranışını yaxşılaşdırmaq üçün biz Fallback modelini tətbiq edə bilərik. Bu nümunənin arxasında duran konsepsiya, əsas mənbə ilə müqayisədə daha aşağı keyfiyyətli və ya təzəlikdə olan məlumatları ehtiva edən ikinci dərəcəli məlumat mənbəyinə malik olmağı nəzərdə tutur. Əgər əsas məlumat mənbəyi mövcud deyilsə və ya xəta qaytarırsa, sistem səhv mesajı göstərmək əvəzinə istifadəçiyə məlumatın hansısa formasının təqdim olunmasını təmin edərək, bu ikinci mənbədən məlumat əldə etməyə qayıda bilər.
Yuxarıdakı şəklə baxsanız, indi qarşılaşdığımız problemlə keş nümunəsi ilə qarşılaşdığımız problem arasında oxşarlıq görəcəksiniz.
Bunu həll etmək üçün təkrar cəhd kimi tanınan nümunəni həyata keçirməyi düşünə bilərik. Keşlərə etibar etmək əvəzinə sistem xəta baş verdikdə sorğunu avtomatik olaraq yenidən göndərmək üçün dizayn edilə bilər. Bu təkrar cəhd nümunəsi daha sadə alternativ təklif edir və tətbiqimizdə səhvlərin olma ehtimalını effektiv şəkildə azalda bilər. Məlumat dəyişikliklərini idarə etmək üçün tez-tez mürəkkəb önbelleği etibarsız etmə mexanizmlərini tələb edən keşləmədən fərqli olaraq, uğursuz sorğuların təkrar sınanması nisbətən sadədir. Keşin etibarsızlaşdırılması proqram mühəndisliyində ən çətin vəzifələrdən biri kimi qəbul edildiyi üçün təkrar cəhd strategiyasının qəbul edilməsi səhvlərin idarə edilməsini asanlaşdıra və sistemin davamlılığını yaxşılaşdıra bilər.
Bununla belə, potensial nəticələri nəzərə almadan təkrar cəhd strategiyasının qəbul edilməsi əlavə fəsadlara səbəb ola bilər.
Təsəvvür edək ki, arxa tərəflərimizdən biri uğursuzluqla üzləşir. Belə bir ssenaridə, uğursuz backend üçün təkrar cəhdlərə başlamaq trafik həcmində əhəmiyyətli artımla nəticələnə bilər. Trafikdə bu qəfil artım arxa tərəfi alt-üst edə, uğursuzluğu daha da gücləndirə və potensial olaraq sistemdə kaskad effektinə səbəb ola bilər.
Bu problemin öhdəsindən gəlmək üçün təkrar sınama nümunəsini elektrik açarı nümunəsi ilə tamamlamaq vacibdir. Elektrik açarı aşağı axın xidmətlərinin səhv dərəcəsini izləyən qoruyucu mexanizm kimi xidmət edir. Səhv dərəcəsi əvvəlcədən müəyyən edilmiş həddi aşdıqda, elektrik açarı təsirə məruz qalan xidmətə verilən sorğuları müəyyən müddətə kəsir. Bu müddət ərzində sistem uğursuz xidmət müddətinin bərpası üçün əlavə sorğular göndərməkdən çəkinir. Müəyyən edilmiş intervaldan sonra elektrik açarı ehtiyatla məhdud sayda sorğunun keçməsinə icazə verir və xidmətin sabitləşib-sabitləşmədiyini yoxlayır. Xidmət bərpa olunarsa, normal trafik tədricən bərpa olunur; əks halda dövrə açıq qalır və xidmət normal işləməyə başlayana qədər sorğuları bloklamağa davam edir. Elektrik kəsici modelini təkrar cəhd məntiqi ilə birləşdirməklə, biz səhv vəziyyətlərini effektiv şəkildə idarə edə və arxa uç uğursuzluqları zamanı sistemin həddindən artıq yüklənməsinin qarşısını ala bilərik.
Yekun olaraq, bu dayanıqlılıq nümunələrini həyata keçirməklə biz fövqəladə hallara qarşı tətbiqlərimizi gücləndirə, yüksək əlçatanlığı qoruya və istifadəçilərə qüsursuz təcrübə təqdim edə bilərik. Əlavə olaraq vurğulamaq istərdim ki, telemetriya layihənin davamlılığını təmin edərkən nəzərdən qaçırılmamalı olan başqa bir vasitədir. Yaxşı qeydlər və ölçülər xidmətlərin keyfiyyətini əhəmiyyətli dərəcədə artıra və onların performansı haqqında dəyərli fikirlər təqdim edərək, onları daha da təkmilləşdirmək üçün əsaslandırılmış qərarlar qəbul etməyə kömək edə bilər.