Observability nima?
Dastlab boshqaruv nazariyasida qo‘llangan atama bo‘lgan observability tizimning tashqarisidan chiqayotgan natijalargagina qarab, uning ichki holati haqida qanchalik ko‘p narsani aniqlash mumkinligini anglatadi. Dasturiy ta’minotga nisbatan qo‘llasak, savol quyidagicha bo‘ladi: serverga bevosita ulanmasdan yoki qo‘shimcha loglar qo‘shish uchun kodni o‘zgartirmasdan, ayni paytda hosil bo‘layotgan ma’lumotlargina yordamida muammoni tushuntira olamizmi?
Asosiy jihat shundaki, bu faqat oldindan belgilangan savollarga javob berish bilan cheklanmaydi. “Javob berish vaqti uch soniyadan oshganda menga xabar bering” — oldindan belgilangan savol. Bunga qarama-qarshi ravishda, “Nega kecha tushdan keyin yuklashlar faqat ma’lum bir qurilmada muvaffaqiyatsiz bo‘ldi?” — oldindan belgilab bo‘lmaydigan savol. Agar keyinchalik shunday savollarni bera olsangiz, tizim observability xususiyatiga ega. Agar bera olmasangiz, kodni o‘zgartirib, qayta deploy qilishingiz va muammo yana yuz berishini kutishingiz kerak bo‘ladi.
So‘z bilan ifodalaganda bu ayon tuyulishi mumkin, ammo bu farq qachon amalda muhim bo‘lishini tushunish uchun haqiqiy xizmatni ko‘rib chiqish kerak.
BanJang Note uchun bu nega kerak?
BanJang Note qurilish maydonidagi brigadirlar va jamoa rahbarlarini bog‘laydigan ilova. U avval chat va matnli xabarlar orqali almashilgan ish e’lonlari, arizalar, hujjat topshirishlar va davomat qaydlarini ilovaga ko‘chiradi. Jamoa rahbari ish e’lonini joylaydi, brigadir ariza beradi, jamoa rahbari topshirilgan hujjatlarni ko‘rib chiqib, yetishmayotgan narsalar bo‘lsa tuzatish so‘raydi, so‘ng tanlangan ishchilarni jamoaga biriktiradi va ularning ishga kelgan va ketgan vaqtlari hamda kunlik ish haqini qayd etadi.
Arxitekturadagi muhim jihat shundan iboratki, u foydalanuvchini aniqlash va autentifikatsiya qilish, hujjatlarni saqlash, bildirishnomalar, to‘lovlar va boshqa vazifalar uchun ichki platformadagi boshqa mikroxizmatlardan foydalanadi. BanJang Note serveri o‘z biznes mantiqini bajaradi, biroq murakkabroq funksiyalarni amalga oshirish uchun har bir mikroxizmat oqimini ham muvofiqlashtiradi.
Bir vaziyatni ko‘rib chiqaylik. Bizga “Kecha kundan beri hujjat topshirishlar vaqti-vaqti bilan muvaffaqiyatsiz bo‘lyapti” degan xabar keladi.
Muammo “vaqti-vaqti bilan” degan so‘zda. O‘n marta urinib ko‘rsangiz, to‘qqiz marta ishlaydi. Server ishlayapti, CPU normal holatda va hech qanday xato ogohlantirishi kelmagan. Biz kuzatayotgan metrikalarning hech birida noodatiy holat ko‘rinmaydi. Mahalliy muhitda qayta takrorlashga uringanimizda esa hammasi yaxshi ishlaydi.
Loglarni titkilab chiqsak ham, boshidanoq qaysi kalit so‘zlarni qidirish va qaysi vaqt oralig‘ini tekshirish masalasida boshi berk ko‘chaga kirib qolamiz. Bundan tashqari, bu so‘rovga faqat bizning serverimiz xizmat ko‘rsatmaydi. U autentifikatsiyadan o‘tadi va fayllarni saqlash xizmatini chaqiradi, shuning uchun loglarimizda noodatiy hech narsa ko‘rinmagani muammo yo‘q degani emas. Biz muvaffaqiyatsiz tugagan bitta so‘rovni tanlab, uning qanchagacha yetib borganini va qayerda to‘xtaganini kuzata olishimiz kerak. Buni amalga oshirish vositasi bo‘lmasa, faqat taxmin qilishimiz mumkin.
Bu monitoring nega manzaraning faqat yarmi ekanini ham ko‘rsatadi. Monitoring ma’lum muammolarni kuzatishni anglatadi. Disk to‘lganda menga xabar ber; xatolar darajasi 1% dan oshganda menga xabar ber. Xavfli narsa nima ekanini oldindan bilsangizgina chegara o‘rnatishingiz mumkin. Ammo ko‘plab real hodisalar biz kutmagan kombinatsiyalar natijasida yuzaga keladi. Faqat ma’lum bir ilova versiyasida va ma’lum bir vaqt oralig‘ida yuz beradigan muammoni oldindan belgilangan ogohlantirish bilan qamrab bo‘lmaydi, chunki qaysi kombinatsiyani izlash kerakligini bilmagan edik.
Qisqacha aytganda, monitoring ogohlantirishni ishga tushiradi, observability esa ogohlantirish ishga tushganidan keyin — yoki umuman ogohlantirishni ishga tushirmagan muammo uchun — sababni topishga imkon beradi. Tekshirish uchun ma’lumotlarsiz faqat ogohlantirishlar bo‘lsa, hodisa vaqtida taxmin qilishdan boshqa hech narsa qila olmaysiz. Ogohlantirishlarsiz faqat ma’lumot to‘plasangiz, nimadir noto‘g‘ri ekanini birinchi bo‘lib foydalanuvchi bilib oladi. Sizga ikkalasi ham kerak.
Observability’ning uch ustuni
Metrikalarvaqt o‘qi bo‘ylab to‘planadigan sonli qiymatlardir. Misollarga so‘rovlar soni, javob berish vaqti percentillari va xatolar darajasi kiradi. Ular yengil va uzoq vaqt saqlanishi mumkin, ammo alohida hodisalar yo‘qolib ketadi. Xatolar darajasi 2% ekanini bilishingiz mumkin, biroq kimda xato yuz bergani yoki nima sabab bo‘lganini bilmaysiz. Har bir label kombinatsiyasi uchun vaqt qatori yaratilgani sababli, foydalanuvchi ID’lari kabi kardinaliteti yuqori qiymatlarni kiritmaslik kerak.
Loglarmuayyan vaqtda nima sodir bo‘lganini tasvirlaydigan qaydlardir. Ular eng batafsil ma’lumotlarni beradi, ammo hajmi katta va qimmatga tushadi. Agar faqat odamlar o‘qishi oson bo‘lgan jumlalarni saqlasangiz, keyinchalik shartlar bo‘yicha qidirish qiyinlashadi. Shuning uchun ularni kalitlar va qiymatlar ajratilgan shaklda saqlagan ma’qul.
Treyslarbitta so‘rovning tizim bo‘ylab bosib o‘tgan yo‘lidir. Ular uchala ma’lumot turi orasida so‘rov darajasida ko‘riladigan yagona tur bo‘lib, alohida hodisalarni yo‘qotadigan metrikalar bilan umumiy oqimni yo‘qotadigan loglar orasidagi bo‘shliqni to‘ldiradi.
Alohida olinganda, uchalasining har biri manzaraning faqat yarmini ko‘rsatadi. Amalda ular ketma-ket tarzda bog‘lanadi. Metrikalar xatolar darajasi 0,1% dan 4% gacha oshganini ko‘rsatadi. Treyslar muvaffaqiyatsiz so‘rovlar yo‘llarini ochib, ularning barchasi fayl xizmati segmentida to‘xtaganini ko‘rsatadi. Loglar bizga o‘sha segmentda chaqiruvni amalga oshirish uchun qaysi parametrlar ishlatilgani va qanday javob olinganini aytadi. Nima noodatiy ekani, muammo qayerdaligi va nima sababdan yuz bergani shu tartibda aniqlashtiriladi.
Ushbu uchalasini bog‘laydigan vosita — korrelyatsiya ID’si. So‘rov kelganda trace ID yaratamiz va u o‘tadigan har bir xizmatga hamda har bir log qatoriga ayni ID’ni biriktiramiz. Shunda treysda ko‘ringan sekin segmentdan bevosita o‘sha segment loglariga o‘tishimiz mumkin. Busiz uchalasi shunchaki alohida ma’lumot uyumlaridan iborat bo‘lib qoladi: grafikdagi keskin o‘sishni ko‘rib, log qidiruv maydonida vaqt oralig‘ini qo‘lda taxmin qilamiz. Bu kuzatishdan ko‘ra qidiruvga yaqinroq.
Xizmatlar ajratilganda tracing zarur bo‘ladi
Tizimlar bir nechta xizmatga bo‘lina boshlagach, observability ixtiyoriy imkoniyat emas, balki muhim zaruratga aylandi.
Monolit xizmatda istisno yuz berganda, stack trace butun sabablar zanjirini o‘z ichiga olardi. Ammo xizmatlar ajratilganda, bu imkoniyat yo‘qoladi. Stack trace serverlar o‘rtasidagi chegaralardan o‘ta olmaydi, loglarimizda esa faqat “chaqiruv muvaffaqiyatsiz bo‘ldi” degan yozuv qoladi. Boshqa mikroxizmat loglarini ochishimiz mumkin, ammo muammo shundaki, barcha shu qatorlar orasidan qaysilari bizning so‘rovimizga tegishli ekanini aniqlashning iloji bo‘lmaydi. Gap ularni ko‘rishga ruxsatimiz bor-yo‘qligida emas, balki ularni bog‘lash usuli bor-yo‘qligida.
Bu yerda bir nechta omil ustma-ust keladi. Bitta ekranni chizish uchun beshta xizmatni chaqirishimiz mumkin, ammo ulardan bittasi ishlamasa ham javob 200 sifatida qaytishi va xato xatolar darajasida ko‘rinmasligi mumkin. Har bir xizmatning deploy sikli ham turlicha, shuning uchun kechagacha ishlagan narsa biz hech narsa deploy qilmagan bo‘lsak ham ishlamay qolishi mumkin. Muvaffaqiyatsizlikka bizning kodimizmi yoki boshqa xizmat sabab bo‘lganini ajrata olmasak, hodisaga javob berish sababni kuzatish harakatidan ko‘ra, bir-birimizdan tekshirib ko‘rishni so‘rash almashinuviga aylanadi.
Bundan tashqari, bunday vaziyatda faqat metrikalar va loglarga tayanish qiyin. Har bir xizmatning metrikalari u normal ishlayotganini ko‘rsatadi. Agar beshta xizmatning har biri 200 millisekund sarflasa va bu vaqtlar ketma-ket qo‘shilsa, foydalanuvchi ikki soniya kutishi mumkin, ammo alohida metrikalarga qaralganda umumiy manzara ko‘rinmaydi. Loglar markazlashtirilgan bo‘lsa ham, xronologik ro‘yxat bitta so‘rov oqimidan farq qiladi. Chaqiruvlar parallel bajarilganda yoki asinxron tarzda harakatlanganda, faqat xronologiyaning o‘zi sababiy bog‘liqlikni ochib bera olmaydi.
Tracing bu ikki vosita qila olmaydigan ishni bajaradi. U bitta so‘rovni birlik sifatida olib, qaysi chaqiruvlar qaysi boshqa chaqiruvlarga parent-child munosabatlari orqali olib kelganini va har bir segment qancha davom etganini qayd etadi. U tarqoq faktlarni xronologik emas, sababiy tartibda qayta tiklaydi. Bu bizga quyidagi savollarga javob berish imkonini beradi: Bu so‘rov aslida qayerga bordi? Umumiy ikki soniyadan qaysi segment vaqtni sarfladi? Muvaffaqiyatsizliklar zanjirida eng shovqinli joy emas, haqiqiy kelib chiqish nuqtasi qayerda edi? Bitta so‘rov ichida ayni xizmatni sakkiz marta chaqiryapmizmi?
Buni BanJang Note misolida ko‘rsak, mazmuni yanada aniq bo‘ladi. Bitta hujjat topshirish foydalanuvchini aniqlash uchun autentifikatsiyadan o‘tadigan, faylni fayllarni saqlash xizmatiga yuboradigan, natijani saqlaydigan va keyin boshqa tomonga bildirishnoma yuboradigan bitta so‘rovni o‘z ichiga oladi. Biz yozgan kod buning faqat bir qismini qamrab oladi, ya’ni xatolar “BanJang Note serveri ichida” emas, xizmatlar o‘rtasida yuz beradi. Funksiya hujjatlar va bildirishnomalar kabi alohida mikroxizmatlar oqimiga qanchalik yaqin bo‘lsa, uning amaldagi qayta ishlanishining shunchalik katta qismi bizning jarayonimizdan tashqarida amalga oshadi.
Treyslarsiz biz tomonda faqat “Hujjat topshirish muvaffaqiyatsiz bo‘ldi” degan bitta qator bo‘ladi. Treyslar bilan esa autentifikatsiya 20 millisekundda tugaganini va so‘rov fayllarni saqlash chaqiruvi vaqtida to‘xtaganini darhol ko‘ramiz. O‘sha nuqtani bosish loglarni ochadi va qaysi so‘rov yuborilgani hamda qanday javob olinganini ko‘rsatadi. Sababni topish qaysi jamoa mas’ul ekanini bahslashish emas, balki qaysi segmentdan qanday javob kelganini tekshirish masalasiga aylanadi.
Jarayon uzoq. Ish e’loniga ariza berish, jamoa rahbarining arizani ko‘rib chiqishi, tanlanish, kutish, jamoaga biriktirilish va davomat tasdiqlanishi — bularning barchasi bir nechta bosqichni o‘z ichiga oladi. O‘rtadagi bir bosqich jimgina muvaffaqiyatsiz tugasa, foydalanuvchi ekranida hatto xato ham ko‘rinmasligi mumkin. Shunchaki hech narsa sodir bo‘lmaydi. “Ariza berdim, ammo bir necha kundan beri hech qanday xabar olmadim” degan murojaat kelganda, javobning deyarli butun mazmuni so‘rov qanchagacha yetib borganini va qayerda to‘xtaganini qayta kuzatishdan iborat bo‘ladi. Aynan shu yerda yo‘l so‘rov darajasida qayd etilib qolgan-qolmagani muhim bo‘ladi.
Foydalanuvchidan qo‘shimcha ma’lumot so‘ray olmaysiz. BanJang Note’dan foydalanadiganlar — qurilish maydonida ishlaydigan ishchilar va menejerlar. Ulardan developer tools’ni ochishni yoki qayta urinib ko‘rib, nima sodir bo‘lganini bizga aytishni so‘rash deyarli imkonsiz. Customer Service ishini boshlashi va sababni aniqlashi uchun tizim ayni o‘sha paytda nima sodir bo‘lganini saqlab qolishi kerak.
Xulosa
Bir jumla bilan aytganda, observability — keyinchalik oldindan kutmagan savollaringizni bera olishingiz uchun tizim qurishdir.
E’tibor berish kerak bo‘lgan jihat shuki, tizimga bir nechta vositani ulaganingiz uchungina u observability xususiyatiga ega deb o‘ylamaslik kerak. Kutubxona qo‘shish va collector’ni ishga tushirish — faqat boshlanishi. Signallar haqiqatan ham saqlash tizimiga yetib boradimi, yetib borgach ularga kim qaraydi va nimadir noodatiy ko‘ringanda kimga xabar beriladi — bularning barchasi yagona butunning qismlaridir. Ushbu uchalasidan bittasi bo‘lmasa ham, bu amalda umuman observability yo‘qligi bilan barobar.
Kod yozayotganda, avvalo hamma narsa to‘g‘ri ishlaydigan holatlar haqida o‘ylashga moyil bo‘lamiz. Ammo operatsiyalarda vaqtni iste’mol qiladigan narsalar — vaqti-vaqti bilan noto‘g‘ri ketadigan holatlardir; xizmatlar ajratilganda esa muammo qayerdan boshlanganini aniqlashning o‘zi ham qiyinlashadi. Har safar funksiya qurganingizda o‘zingizga shunday savol berib ko‘rish foydali: Agar bu tungi soat uchda noto‘g‘ri ketsa, sababni topish uchun nimaga qarayman?
Ted