← ყველა სტატია

ერთი p99 ალერტი, ხუთი ნელი მარშრუტი, ხუთი სხვადასხვა მიზეზი

სერვისის დონის ლატენტობის ალერტი არც ერთ endpoint-ს არ ასახელებდა. მარშრუტების მიხედვით დაყოფამ აჩვენა გარე შლუზი, captcha-ს შემოწმება, პროვაიდერის გამოძახება — და გაზომვის ხაფანგები, რომლებიც არასწორი გზით წაგვიყვანდა.

Gambchamp-ის ერთ-ერთ პროდუქტის პლატფორმაზე გადახდის სერვისზე p99 ლატენტობის ალერტი ამოქმედდა. ის ამბობდა, რომ სერვისი ნელია, და არაფერს — სად. ალერტის მარშრუტების მიხედვით დაყოფამ ამ კითხვას უპასუხა — და აჩვენა, რომ ყოველ ნელ მარშრუტს თავისი მიზეზი ჰქონდა. ზოგი რეალური პრობლემა იყო, ზოგი — სულაც არ ის, რაც ჩანდა.

რა აღმოჩნდა თითოეული მარშრუტი

  • დეპოზიტის ინიციაცია: მოთხოვნების დაახლოებით ნახევარი 2,5–5 წამს გრძელდებოდა. ეს იყო გარე გადახდის შლუზების სინქრონული გამოძახებები, რომლებიც HTTP 200-ს აბრუნებდნენ რედირექტის URL-ით — შეცდომების გარეშე. განაწილება ბიმოდალური იყო: დაახლოებით 5 ms, როცა შლუზის გამოძახება საჭირო არ არის, და 2,5–5 წმ, როცა საჭიროა. რვაწამიანი p99 უბრალოდ შლუზების ნორმალური სიჩქარე იყო.
  • რეგისტრაცია: მოთხოვნების 84 % წამზე მეტი. ლოგებში ფაზების ტაიმინგებმა აჩვენა, რომ მედიანური მოთხოვნა 1,4 წმ-ს ხარჯავს დამუშავებაზე, უმეტესად — გარე captcha-ს შემოწმებაზე (დაახლოებით 0,5 წმ).
  • თამაშის გაშვება: 6 % ნელი. ერთ ფაზას — თამაშის პროვაიდერის კონექტორის გამოძახებას — ჰქონდა მედიანა 1,2 წმ და p95 1,7 წმ. დანარჩენი ყველაფერი — მილიწამებია.
  • პრომო-გვერდი: მოთხოვნების 10 % წამზე მეტი — მაგრამ თავად handler-ის ტაიმინგი არასოდეს აღემატებოდა 0,95 წმ-ს. დრო handler-ის გარეთ იხარჯებოდა. ეს ბოლომდე ჯერ ვერ დავიჭირეთ.
  • თანხის გატანა: კიდევ ერთი მარშრუტი შლუზით, p99 დაახლოებით 2,5 წმ. ყველა სხვა გადახდის მარშრუტი — დაახლოებით 50 ms.

ხაფანგები

  • ბექენდები ორჯერ scrape-დებოდა, ორი job-ით. კვანტილებს ეს არ აინტერესებს, მაგრამ მთვლელები და increase() ორმაგდება, თუ job-ს არ დააფიქსირებთ. ყოველთვის დააფიქსირეთ, როცა მოთხოვნებს ითვლით.
  • handler-ის ტაიმინგი ლოგში მოთხოვნის ხანგრძლივობა არ არის. ის მხოლოდ handler-ს ზომავს; ჰისტოგრამა ზომავს იმას, რასაც კლიენტი ხედავს. SLO-სთვის ჰისტოგრამას ენდეთ; ლოგები გამოიყენეთ იმის გასაგებად, სად მიდის დრო handler-ის შიგნით.
  • ლოგები შერჩევაა. ლოგის 763 სტრიქონი ჰისტოგრამის 2 419 დაკვირვების წინააღმდეგ იმავე სამ საათში. „ლოგებში ნელი მოთხოვნები არ არის“ მეტრიკას არ უარყოფს.
  • ბაკეტების ბადე 1,0-დან პირდაპირ 2,5 წამზე ხტებოდა. ყველაფერი, რაც ამ შუალედში ხვდება, ზედა საზღვართან ახლოს ინტერპოლირდება, ამიტომ 2,3 წმ-იანი p99 შეიძლება ნიშნავდეს „სადღაც 1-სა და 2,5-ს შორის“. რიცხვს სანამ ენდობით, ბაკეტებს შეხედეთ.
  • კვანტილი ბიმოდალობას მალავს. „p99 — ხუთი წამია“ ჟღერდა როგორც „ყველაფერი ნელია“. ბაკეტებმა კოდში ორი სხვადასხვა გზა აჩვენა.

ერთი შეცდომა მე თვითონ დავუშვი: თავიდან პრომო-გვერდი ბაკეტების არტეფაქტად ჩავთვალე. სხვადასხვა job-ის ბაკეტები ერთმანეთს დაემთხვა — მოთხოვნების დაახლოებით 10 % მართლაც წამზე მეტი იყო. შეამოწმეთ, სანამ არტეფაქტს გამოაცხადებთ.

მოთხოვნები, რომლებმაც საქმე გააკეთეს

sum by (le) (increase(http_request_duration_seconds_bucket{app="X", route="Y"}[30m]))

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

როგორ შეიცვალა ალერტინგი

  • ლატენტობის ალერტი ახლა (app, route)-ით აგრეგირებს, ამიტომ endpoint-ს ასახელებს.
  • ტრაფიკის ზღვარი — 10 წუთში 3-ზე მეტი მოთხოვნა და არა rate: დეპოზიტის მარშრუტი 10 წუთში დაახლოებით ოთხ მოთხოვნას იღებს და მართლაც ნელია, ამიტომ rate-ზე დაფუძნებული ზღვარი მას ტოვებდა.
  • ზღვარი — 1,5 წმ და არა 1 წმ, შერჩეული ბაკეტების ბადის გათვალისწინებით.
  • შლუზის მარშრუტები გამორიცხულია და საკუთარი ალერტი აქვთ 12 წამზე 30 წუთში. იქ ორიდან რვა წამამდე ნორმაა; ალერტის ტექსტი ამას პირდაპირ ამბობს, რომ მორიგე ინჟინერი ჩვენს ინფრასტრუქტურაში ბაგის ძებნას არ დაიწყებს.

დასკვნები

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