English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

სტუმარი
1 / ?
უკან გაკვეთილებზე

სამი ჩავარდნის კონცეფცია, რომლის ცოდნაც ღირს

კეთილი იყოს თქვენი მობრძანება

განაწილებული სისტემები ჩავარდნებს გარკვეული ნიმუშებით ახდენენ. როგორც კი ამ ნიმუშებს ისწავლით, ყველა პოსტმორტემი საინტერესო ამოცნობის სავარჯიშოდ იქცევა, და აღარ არის საიდუმლო.

სამი კონცეფცია ფარავს წარმოების გარემოში ჩავარდნების ანალიზის უმეტეს ნაწილს:

Single point of failure (SPOF): კომპონენტი, რომლის ჩავარდნაც მთელ დიდ სისტემას აჩერებს. ხშირად დამალულია: DNS სერვერი, რომელზეც ყველაა დამოკიდებული; სერტიფიკატი, რომლის წინააღმდეგაც ყველაფერი განახლდება; ერთადერთი მთავარი მონაცემთა ბაზა.

კასკადური ჩაშლა: ერთი კომპონენტის ჩაშლა იწვევს მეორის ჩაშლას, რომელიც იწვევს მესამისას. ნელი მონაცემთა ბაზა იწვევს API-ის დონეზე ტაიმაუტებს, რაც იწვევს რიტრაიებს, რომლებიც კიდევ უფრო ტვირთავენ მონაცემთა ბაზას, რაც იწვევს კიდევ მეტ ტაიმაუტს. აფეთქება ვრცელდება.

აფეთქების რადიუსი: რამდენი ნაწილი სისტემის გამოდის მწყობრიდან, როდესაც ერთი ნაწილი ცუდად მუშაობს. არქიტექტურული გადაწყვეტილებები ან ზღუდავენ ამ რადიუსს, ან უშვებენ. SPOF-ს აქვს უსაზღვრო აფეთქების რადიუსი. Bulkhead-ით დაცულ სერვისს აქვს შეზღუდული რადიუსი.

ამ გაკვეთილის დასასრულს თქვენ შეძლებთ:

- არქიტექტურაში SPOF-ების იდენტიფიცირება მხოლოდ ინსპექციით

- კასკადური ჩაშლის ნიმუშების ამოცნობა: thundering herd, retry storm, queue of death

- რეალური ინციდენტის timeline-ის წაკითხვა და ტრიგერის გამიჯვნა იმ latent defect-ისგან, რომელიც ტრიგერმა გამოავლინა

- უდანაშაულო (blameless) სამოქმედო პუნქტების შედგენა, რომლებიც მიზანში იღებენ სისტემებს და არა ადამიანებს, და მოიცავენ პრევენციას / აღმოჩენას / აღდგენას

- მსჯელობა bulkheads-სა და circuit breakers-ზე, როგორც აფეთქების რადიუსის შემზღუდველ ინსტრუმენტებზე

ერთი წერტილის (Single Point of Failure) აღმოჩენა

ფენიანი არქიტექტურის ინსპექცია

განიხილეთ მცირე ვებ არქიტექტურა:

- DNS: api.example.com -> ერთი nameserver IP 203.0.113.10, რომელიც მხოლოდ ერთი DNS პროვაიდერის მიერაა ჰოსტირებული

- CDN: api.example.com-ის წინ მდგარი ერთი CDN ვენდორი

- Ingress: ლოდბალანსერის მიღმა ორი რევერს პროქსი მანქანა

- Backend: ექვსი API რეპლიკა ორ availability zone-ში (სამი თითო ზონაში)

- Database: ერთი primary + ერთი read replica, ორივე ერთსა და იმავე availability zone-ში

- ქეში: Redis კლასტერი, სამი 노드ი განლაგებული იმავე ორ availability zone-ში

კითხვა: რომელი კომპონენტებია SPOF-ები? მინიშნება: SPOF-ები ყოველთვის არ არის აშკარა „ერთი მანქანის“ ტიპის. სამი მანქანის კლასტერი, რომელიც მთლიანად ერთ availability zone-შია, არის SPOF ამ zone-ის გათიშვის შემთხვევაში.

იპოვეთ ამ არქიტექტურაში სულ მინიმუმ სამი SPOF. თითოეულისთვის მიუთითეთ: რა ფუჭდება მისი გაუმართავობის შემთხვევაში, და შემოგვთავაზეთ კონკრეტული ცვლილება, რომელიც ამ SPOF-ს აღმოფხვრის (აპლიკაციის გადაწერის გარეშე).

სამი კლასიკური კასკადური ნიმუში

ჩავარდნები გადადის დამოკიდებულებებით

ნიმუში 1: ქარიშხლიანი ჯოგი. საზიარო რესურსი (კეში, ლოკი, მონაცემთა ბაზა) ცუდად მუშაობს ან რესტარტდება. ყველა კლიენტი, რომელიც მასზე იყო დამოკიდებული, ერთდროულად ცდილობს თავიდან. წყალდიდობა აჭარბებს იმას, რაც კვლავ ირთვება; გამეორებები სწრაფად გროვდება, ვიდრე აღდგენას შეუძლია მათი შთანთქმა; აღდგენა ვერასდროს სრულდება.

ნიმუში 2: გამეორებების ქარიშხალი. ქვედა სერვისი ნელდება. ზედა გამომძახებლები, ნაცვლად იმისა რომ შეცდომა დააბრუნონ, თავიდან ცდილობენ. გამეორებები ათასგვარად ზრდის საწყის დატვირთვას. ნელი სერვისი კიდევ უფრო ნელდება, რაც კიდევ მეტ გამეორებას იწვევს. საბოლოოდ დატვირთვა აჭარბებს კი ჯანსაღი ვერსიის სერვისის შესაძლებლობებსაც.

ნიმუში 3: სიკვდილის რიგი. დამუშავების რიგი, რომელსაც არ აქვს backpressure, იღებს მეტს, ვიდრე ახერხებს დამუშავებას. რიგი უსასრულოდ იზრდება. მეხსიერება იწურება; მომხმარებელი კრაშდება; რესტარტდება; პოულობს კიდევ უფრო დიდ რიგს; კვლავ კრაშდება.

საერთო ძაფი: მცირე საწყისი შეფერხება იწვევს დადებითი უკუკავშირის მარყუჟს. სისტემის საკუთარი რეაქცია აძლიერებს ჩავარდნას, ნაცვლად იმისა რომ შეამციროს იგი.

დამამშვიდებელი მექანიზმები

ექსპონენციური დაყოვნება jitter-ით. კლიენტები, რომლებიც ხელახლა ცდიან, ყოველ ჯერზე უფრო დიდხანს ელოდებიან, შემთხვევითი ოფსეტით. ხელს უშლის სინქრონიზებული retry ტალღებს.

ჩამრთველი (Circuit breaker). გამომძახებელი თვალყურს ადევნებს ქვედა სისტემის წარუმატებლობის მაჩვენებელს. ზღვარს გადაცილების შემდეგ გამომძახებელი წყვეტს მის გამოძახებას გარკვეული დროით და თავისივე მოთხოვნებს მაშინვე ამარცხებს. ხელს უშლის ზედმეტ შრომას და აძლევს ქვედა სისტემას გამოჯანმრთელების საშუალებას.

Bulkhead. რესურსების იზოლაცია თითოეული დამოკიდებულებისთვის. მონაცემთა ბაზისთვის კავშირების 풀 A, ქეშისთვის — ცალკე 풀 B. ნელი მონაცემთა ბაზა ვერ გაანადგურებს ყველა კავშირს; ქეშის გამოძახებები გაგრძელდება.

Load shedding. გადატვირთვისას მოთხოვნების ჩამოშორება კიდეზე (edge-ზე), ვიდრე მათი მიღება და ნელი წარუმატებლობა. 429 პასუხი 1 მილიწამში უკეთესია, ვიდრე 500 პასუხი 30 წამში.

Backpressure. შენელება პროდუსერებისთვის, როცა მომხმარებლები ვერ უწევენ ტემპს. რიგები ხდება შეზღუდული; გამგზავნები ბლოკავენ; სამუშაოს საწყისი წყარო გრძნობს წინააღმდეგობას.

კასკადური წარუმატებლობა: ტრიგერი → გაძლიერება → კოლაფსი, დემპფინგის მექანიზმებით

კასკადის დიაგნოსტიკა

გუნდის API-ის დონე იშლება ჩვეულებრივი მონაცემთა ბაზის failover-ის დროს. დროის ხაზი:

- 14:00:00 — ოპერატორი აწინაურებს standby მონაცემთა ბაზას. მოსალოდნელი გაუწყობლობა: ~10 წამი.

- 14:00:08 — primary მონაცემთა ბაზა გაუწყობელია. API ტირის მოთხოვნები იწყებენ წარუმატებლობას მონაცემთა ბაზასთან კავშირის შეცდომებით.

- 14:00:08 — API ტირი ახდენს retry-ებს (ნაგულისხმევი კონფიგურაცია: 5 retry, უკუ-ექსპონენციური დაყოვნების გარეშე, 100მწმ ინტერვალით).

- 14:00:11 — standby მონაცემთა ბაზა აწინაურებულია და იღებს ახალ კავშირებს.

- 14:00:11 — API ტირი ხსნის ათასობით ახალ მონაცემთა ბაზის კავშირს ერთდროულად (ყველა რეპლიკა × ყველა პარალელური მოთხოვნა × ყველა retry).

- 14:00:13 — ახალი primary-ის კავშირების პული ამოწურულია; ახალი კავშირები უარყოფილია.

- 14:00:13-14:05:00 — API ტირის რეპლიკები ამოწურავენ კავშირების პულებს, აგდებენ გამონაკლისებს, კრეშავენ, რესტარტავენ და იმეორებენ.

- 14:05:00 — ოპერატორი ხელით აჩერებს API ტირის ტრაფიკს; მონაცემთა ბაზა სტაბილურდება.

- 14:10:00 — თანდათანობითი ტრაფიკის აღდგენა დასრულდა. საერთო გაუმართაობა: ~10 წუთი (ნაცვლად მოსალოდნელი ~10 წამისა).

განსაზღვრეთ მოქმედი კასკადის ნიმუში, დაასახელეთ დემპინგის მექანიზმები, რომლებიც ამას აღკვეთდა (მინიმუმ ორი), და ახსენით, რატომ გადაიქცა პირველადიდან სარეზერვო სისტემაზე გადართვა (რომელიც 10-წამიანი „მცირე გაუმართაობა“ უნდა ყოფილიყო) 10-წუთიან გაუმართაობად.

DNS SERVFAIL: ორი ერთმანეთის გამწვავებული დეფექტი

რეალური ინციდენტის პოსტმორტემი

ქვემოთ მოყვანილია რეალური ინციდენტის გაწმენდილი ვერსია. გამოყენებულია ცვლილება გამყიდველების სახელებზე, IP-ები ანონიმიზებულია; სტრუქტურა, დროის ხაზი და გაკვეთილები — სრულიად რეალურია.

შეჯამება

საიტი example.com დაახლოებით 3-4 საათის განმავლობაში აბრუნებდა SERVFAIL-ს ყველა საჯარო DNS რეზოლვერიდან. იმავე DNS მასტერზე არსებული დანარჩენი 46 ზონა დაზიანებული არ იყო. ძირითადი მიზეზი: ორი ერთმანეთის გამწვავებული დეფექტი.

1. Vendor A (მეორადი DNS პროვაიდერი) დაემატა ახალი შიდა სინქრონიზაციის IP, რომელიც არ იყო პირველადი სერვერის allow-axfr-ips სიაში.

2. ზონა example.com წლების განმავლობაში შეიცავდა RFC-ის დამრღვევ CNAME კონფლიქტს (demo.example.com-ზე ერთდროულად არსებობდა CNAME და MX/TXT ჩანაწერები), რის გამოც Vendor A უარყოფდა ზონას ახალი AXFR-ის დროს.

დროის ხაზი (UTC)

- ~15:00 — გამყიდველი A ამატებს ახალ სინქრონიზაციის IP-ს 198.51.100.42 საკუთარ ინფრასტრუქტურაში

- 15:02 — პირველი AXFR-out denied ჩანაწერი 198.51.100.42-სთვის ჩნდება პირველადი DNS-ის ლოგებში (ამ სიგნალზე ალერტი არ იყო დაყენებული)

- ~18:00 — SOA-ს expire ფანჯარა ამოიწურა; გამყიდველმა A-მ example.com ზონა ქეშიდან წაშალა

- ~18:30 — გარედან აღმოჩენილია SERVFAIL

- ~19:45 — გამოვლენილია ძირითადი მიზეზი

- 20:00 — 198.51.100.42 დაემატა allow-axfr-ips-ში; პირველადი DNS სერვერი გადატვირთეს

- 20:05 — გაიგზავნა NOTIFY; დაიწყო AXFR; ზონა კვლავ აბრუნებს SERVFAIL (CNAME კონფლიქტი)

- 20:07 — check-zone აჩვენებს 1 შეცდომას: CNAME კონფლიქტი demo.example.com-ზე

- 20:09 — CNAME შეიცვალა A ჩანაწერით; ზონის შემოწმება სუფთაა (0 შეცდომა)

- 20:10 — NOTIFY გაიგზავნა; AXFR დასრულდა; Vendor A იწყებს ზონის მომსახურებას

- 20:11 — dig @8.8.8.8 example.com A აბრუნებს სწორ IP-ს — გადაწყვეტილია

რატომ მხოლოდ example.com?

ყველა 47 ზონას აქვს ერთი და იგივე DNS primary. AXFR-ის IP ბლოკმა ყველა ზონაზე იმოქმედა. თუმცა მხოლოდ example.com-ს ჰქონდა CNAME კონფლიქტი და მხოლოდ example.com-ს სჭირდებოდა ახალი AXFR სწორედ იმ მომენტში, როდესაც უარყოფა ამოქმედდა. დანარჩენ ზონებს ან უკვე განახლებული ჰქონდათ მონაცემები უარყოფამდე, ან ჯერ არ სჭირდებოდათ განახლება.

ფარული დეფექტი

CNAME კონფლიქტი demo.example.com-ზე წლების განმავლობაში არსებობდა. ის მუშაობდა, რადგან primary ზონას მისი ბაზიდან აწოდებდა (უფრო ლოიალურია RFC-ის დარღვევების მიმართ), ხოლო Vendor A იყენებდა ძველ, კეშირებულ მონაცემებს, რომლებიც კონფლიქტის წარმოქმნამდე იყო შენახული. როდესაც Vendor A-მ კეში გაასუფთავა და ახალი მონაცემები დასჭირდა, დარღვევა გამოვლინდა.

ტრიგერი

გამყიდველმა A-მ ჩუმად დაამატა ახალი სინქრონიზაციის IP. პრაიმერის allowlist-ში ის არ იყო. AXFR უარყოფილი იქნა. სამი საათის შემდეგ (SOA expire), გამყიდველმა A-მ ჩამოაგდო ზონა. ფარული დეფექტი გამოვლინდა, როდესაც სისტემამ აღდგენა სცადა.

დაწერეთ უდანაშაულო სამოქმედო პუნქტები

უდანაშაულო: სამიზნე უნდა იყოს სისტემები, არა ადამიანები

უდანაშაულო სამოქმედო პუნქტი ასახელებს იმას, რაც სისტემამ უნდა გააკეთოს სხვანაირად, და არა იმას, რაც ადამიანმა უნდა გააკეთოს სხვანაირად. „გადაამზადე ოპერატორი“ — დამნაშავებულია. „დაამატე ავტომატური შემოწმება, რომელიც ამას გაშვებამდე დაიჭერს“ — უდანაშაულოა.

კარგი უდანაშაულო სამოქმედო პუნქტები სამ განზომილებად იყოფა:

- პრევენცია: გახადე ცუდი მოვლენა უფრო რთული ან შეუძლებელი

- გამოვლენა: შენიშნე ის უფრო ადრე, თუ მოხდება

- აღდგენა: შეამცირე ზიანი, როდესაც ის მოხდება

თითოეული პუნქტი უნდა ასახელებდეს (1) კონკრეტულ სისტემურ ცვლილებას, (2) პასუხისმგებელ გუნდს და (3) იმ განზომილებას, რომელსაც ემსახურება.

დაწერეთ სამი უდანაშაულო (blameless) სამოქმედო პუნქტი DNS-SERVFAIL-ის ზემოთ მოყვანილი პოსტმორტემისთვის. გადანაწილეთ ისინი პრევენცია / დეტექცია / რიკავერის მიხედვით (თითოეული განზომილება ერთი პუნქტი). თითოეული პუნქტი უნდა ასახელებდეს კონკრეტულ სისტემურ ცვლილებას და პასუხისმგებელ გუნდს. **არ** მიუთითოთ ადამიანი როგორც პრობლემის მიზეზი.

კუპეები, რომლებიც ჩაეძირვებიან გემის გარეშე

ნასესხები საზღვაო ინჟინერიიდან

გემები ატარებენ წყალგაუმტარ ბალკჰედებს: ვერტიკალურ კედლებს, რომლებიც ჰალს კუპეებად ყოფენ. ერთი კუპე შეიძლება წყლით შეივსოს და გემი არ ჩაიძიროს; სხვა შეიძლება გაფუჭდეს დანარჩენებზე გავლენის გარეშე.

განაწილებული სისტემები იღებენ იგივე სიტყვას და იგივე იდეას.

ბალკჰედის ნიმუში: რესურსების იზოლაცია თითოეული დამოკიდებულების მიხედვით. სერვისი, რომელიც სამ ქვედა API-ს უწოდებს, იყენებს სამ ცალკე კავშირის 풀ს, სამ ცალკე თრედის 풀ს და სამ ცალკე retry ბიუჯეტს. ნელი ან გაუმართავი ქვედა დამოკიდებულება ვერ მოიხმარს რესურსებს, რომლებიც გამოყოფილია დანარჩენი ორისთვის.

ბალკჰედების გარეშე: ერთი ნელი დამოკიდებულება ამოწურავს საერთო თრედის 풀ს; სხვა დამოკიდებულებების გამოძახებები ბლოკავენ თრედების მოლოდინში; მთლიანი სერვისი უპასუხოდ რჩება.

ბალკჰედებით: ერთი ნელი დამოკიდებულება ამოწურავს მხოლოდ საკუთარ 풀ს; მისი გამოძახებები სწრაფად ვერ მუშაობენ; სხვა დამოკიდებულებების გამოძახებები ნორმალურად გრძელდება; აფეთქების რადიუსი რჩება შეზღუდული მხოლოდ გაუმართავ დამოკიდებულებაზე.

ციკლური გამრთველები (Circuit Breakers)

ჩართვის გამრთველის ნიმუში (Circuit Breaker): მდგომარეობის მქონე გადატანა (wrapper) ქვედა დონის დამოკიდებულებაზე, რომელიც თვალს ადევნებს წარუმატებლობის მაჩვენებელს. აქვს სამი მდგომარეობა:

- დახურული (ნორმალური): გამოძახებები თავისუფლად გადის. წარუმატებლობები ითვლება.

- ღია (გამორთული): წარუმატებლობის ზღვარს გადაჭარბების შემთხვევაში (მაგ. 50% წარუმატებლობა ბოლო 30 წამში), ჩართვის გამრთველი იხსნება. გამოძახებები მაშინვე ვერ ხერხდება დამოკიდებულების გამოძახების გარეშე. იცავს გამომძახებელს ზედმეტი სამუშაოსგან და იცავს დამოკიდებულ სერვისს დატვირთვისგან, სანამ ის არაჯანსაღ მდგომარეობაშია.

- ნახევრად ღია (ტესტირების რეჟიმი): გაგრილების პერიოდის შემდეგ, ჩართვის გამრთველი მცირე წილ გამოძახებებს უშვებს. თუ ისინი წარმატებულია, ის კვლავ იხურება ნორმალურ მდგომარეობაში. თუ ისინი წარუმატებელია, ის კვლავ იხსნება ახალი გაგრილების პერიოდისთვის.

მთავარი აზრი: ჩართვის გამრთველი ხელს უშლის ზედმეტ ძალისხმევას ცნობილად არაჯანსაღ პერიოდში და აძლევს ქვედა დონის სერვისს შანსს გამოჯანმრთელდეს დამატებითი დატვირთვის გარეშე.

Bulkheads ზღუდავს აფეთქების რადიუსს. Circuit Breakers კი ხელს უშლის აფეთქებას გაგრძელდეს.

შეზღუდე აფეთქების რადიუსი

შენი API სერვისი იძახებს ოთხ ქვედა დონის სერვისს: User Service, Recommendation Service, Notification Service და მესამე მხარის Payment API-ს. გუნდმა გაიგო, რომ „Recommendation Service ცოტა არასტაბილურია“ და უნდა უზრუნველყოს, რომ მისი წარუმატებლობის შემთხვევაში დანარჩენი სისტემა ჯანსაღი დარჩეს.

დღეს სერვისი იყენებს ერთ საზიარო თრედ 풀ს 200 თრედით და ერთ საზიარო HTTP კავშირების 풀ს. ოთხივე downstream კონკურენციას უწევს ამ რესურსებს. წრიული გამრთველები (circuit breakers) არ გამოიყენება.

შემოგთავაზეთ Bulkhead + Circuit Breaker დიზაინი ამ API სერვისისთვის. იყავით კონკრეტული: როგორ გაყოფთ თრედ/კავშირების პულებს ოთხ დამოკიდებულებას შორის, რა circuit-breaker-ის ზღვრებია მ 적ებული არასტაბილური Recommendation Service-ისთვის, და რა უნდა გააკეთოს user-facing API-მ, როდესაც Recommendation Service ღია წრეშია (open-circuited)?

ჩააწყობს წარუმატებლობის რეჟიმების მიმოხილვას (Failure-Mode Review)

სინთეზი

თქვენ ისწავლეთ SPOF-ების ინსპექციით აღმოჩენა, კასკადური წარუმატებლობის შაბლონების ამოცნობა, პოსტმორტემის კითხვისას ტრიგერის გამიჯვნა ლატენტური დეფექტისგან, უდანაშაულო სამოქმედო პუნქტების წერა პრევენცია / დეტექცია / აღდგენის გაყოფით, და blast radius-ის შეზღუდვა bulkheads + circuit breakers + graceful degradation-ის გამოყენებით.

გამოიყენეთ ყველა ხუთივე.

თქვენი გუნდი უშვებს ახალ სერვისს search.example.com, რომელიც დამოკიდებულია სამ დაქვემდებარებულ სერვისზე: ძირითად საძიებო ინდექსზე (index.example.com), ანალიტიკის სერვისზე (analytics.example.com) და რეკომენდაციების სერვისზე (recs.example.com). გუნდი გთხოვთ, რომ გაუძღვეთ ‘failure-mode review’-ს გაშვებამდე.

მონახაზეთ failure-mode review, რომელსაც თქვენ გაუძღვებოდით. შეიტანეთ: როგორ გამოავლენდით SPOF-ებს (ერთი ტექნიკა), როგორ აღკვეთდით კასკადურ წარუმატებლობას საძიებო სერვისსა და მის სამ დაქვემდებარებულ სერვისს შორის (ორი შაბლონი), ერთი კონკრეტული სამოქმედო პუნქტი რეკომენდაციების სერვისისთვის (რომელიც გუნდმა ყველაზე ნაკლებად სანდოდ მონიშნა), და რა მონიტორინგი უნდა იყოს დაყენებული გაშვების მომენტისთვის.

სად მიდის ეს კურსი შემდეგ

სად მიდის ეს კურსი შემდეგ

თქვენ უკვე შეგიძლიათ SPOF-ის ამოცნობა, კასკადის ამოცნობა, პოსტმორტემის პროდუქტიულად წაკითხვა, უდანაშაულო ქმედითი პუნქტების წერა და აფეთქების რადიუსის დიზაინით შეზღუდვა.

ამ კურსის ბოლო გაკვეთილი (cs_distsys_observability_and_capacity) გასწავლით, რა უნდა გაზომოთ, რომ პრობლემა მომხმარებლებამდე აღმოაჩინოთ. ჯანმრთელობის შემოწმებები, ვერსიის ენდპოინტები, ოთხი ოქროსფერი სიგნალი პროქსი დონეზე და როგორ უკავშირდება სურჯის სიმძლავრის გადაწყვეტილებები დაკვირვებულ მონაცემებს.

თანმხვედრი გაკვეთილი: geometry_of_failure_modes_and_blast_radius გამოთვლის betweenness centrality-ს (რომელი გრაფის კვანძია ბოთლნეკი) და min-cut-ს (აფეთქების რადიუსის ზედა ზღვარი).

კარგად შეასრულეთ. წინსვლა.