Kian
Kian
خواندن ۶ دقیقه·۴ سال پیش

پایش (monitoring) در یک #سیستم_همیشه_بالا

(ویرایش: یک سیستم نمونه در نوشتار دیگری ارائه شده که برخی مفاهیم نوشتار زیر را ملموس‌تر می‌کند.)

۱. دیدپذیری برای پایش - monitoring visibility

(این نوشته پیش‌تر به شکل رشته توییت نوشته شده بوده و سپس در ویرگول رونوشت شده)

سرویس ما اگر قراره موفق باشه، زود یا دیر پایش سطح بالا خواهد داشت. مثلا اگر یک سرویس خرید اینترنتی داریم، فقط سالم بودن سرورها و مصرف پردازش و حافظه رو پایش نخواهیم کرد بلکه نمودار تعداد خرید بر ثانیه و تعداد نمایش فلان پیشنهاد بر ثانیه و نتایجی که به دلیل الف و ب فیلتر می‌کنیم و غیره و غیره رو هم خواهیم پایید تا (دلیل اول) اگر یک bugی فعال شده یا یک مدل یادگیری پس‌رفت کرده یا به هر دلیلی داریم خراب می‌کنیم، خبردار شیم - بدیهتا روی هر چیزی هشدار تعریف نمی‌کنیم و شاید بعدتر از مساله‌ی لوث شدن هشدار بنویسم.

خوب خبردار شدیم، حالا چه طور کند و کاو می‌کنیم؟ (دلیل دوم) از طریق همون داده‌های پایشی - چندین برابر شاخص(metric)هایی که برای هشداردهی تعریف کردیم معمولا شاخص برای کند و کاو تعریف کردیم.

(دلیل سوم) همین شاخص‌ها هستن که یک قناری موفق رو ممکن می‌کنن: هنگام بیرون دادن (release) هر نسخه‌ی کُد یا داده یا مدل یادگیری جدید، چی رو می‌خوایم در محیط تست تجمیع (integration) یا تست صحنه (staging) یا تست الف/ب (A/B) یا در مراحل قناری وارسی کنیم تا پیش از مستقر کردن نسخه‌ی جدید خاطرجمع شیم؟ همین شاخص‌ها.

تا این‌جا مقدمه بود.

نکته‌ی این فصل اینه که دیدپذیری (visibility) شاید در آغاز، دغدغه‌ی توسعه‌دهندگان یک سرویس نباشه، ولی اگر زود بهش فکر بشه--و تقریبا هم که رایگانه--بسیار بهتره تا این که بعدها برگردیم و کُدها رو از نو بخونیم و دیدپذیری اضافه کنیم - چیزی که از برخی تیم‌های ما رو خوب آزار داده.

دیدپذیری یعنی چی؟ یعنی هنگام نوشتن کُد، خیلی دست و دل باز شاخص تعریف کنیم و دل و روده‌ی منطق تجاری (business logic) رو بریزیم روی دایره تا مثل یک جعبه‌ی شفاف باشه. تا آیندگان به اموات ما آمرزش بفرستن. ورودی این مولفه‌ی کُد از نوع الف است یا ب؟ یک شاخص تعریف کنیم که بشماره. سر فلان if مهم تصمیم گرفتیم کار الف رو بکنیم یا ب؟ یک شاخص. تعداد عناصر فلان مجموعه‌ی بازیابی شده از فلان‌جا؟ یک شاخص. هر حالت خلاف انتظار: یک شاخص. شاخص همون‌هاست که از سرور صادر می‌کنیم و سیستم‌های پایش مثل Prometheus اون‌ها رو گردآوری و تجمیع می‌کنن و به اون ۳ مصرف گفته شده (و بیشتر) میان.

یک روش نادرست برای همین هدف‌ها، مقوله‌ی log نویسی (info و warning و ...) است که عادت برخی توسعه‌دهنده‌هاست. ولی به دلایل واضح، log برای پایش نیست و تنها برای کند و کاوه (مثلا پس از دریافت هشدار). یک کاربرد نادرست دیگر log، برای trace کردن تک تک درخواست‌هاست که فراتر از این نوشتاره.

۲. پایش بُرش‌ها - slice monitoring

(این نوشته پیش‌تر به شکل رشته توییت نوشته شده بوده و سپس در ویرگول رونوشت شده)

از دیگر مهم‌هایی که شاید در آغاز، دغدغه‌ی توسعه‌دهندگان نباشه ولی بعدا که سیستم بزرگ شد پشیمون می‌شن، بُعد دادن به شاخص(metric)هاییه که گفتیم دست و دل‌بازانه در کُدها می‌ذاریم، تا بتونیم بُرش(slice)های ریز رو پایش کنیم نه فقط مجموعِِ فلّه‌ایِ رو.

مثلا در مثال فروشگاه اینترنتی، اگر کالاهایی که پیشنهاد می‌دیم از ۲ جور مخزن A و B میان و کاربر از دو شیوه‌ی app یا web با ما تعامل می‌کنه، به همه‌ی شاخص‌های مهم‌مون بُعد «مخزن» و «محیط کاربر» می‌دیم. اون وقت نه تنها مقدار مجموع شاخص‌ی الف رو می‌بینیم، بلکه مقدار الف در هر بُرش {A:web, A:app, B:web, B:app} رو هم. مثلا اگر app ما دچار bug شد و یک سیگنال لازم برای پیشنهاددهی بهینه به کاربر از مخزن B رو نفرستاد، از بُرش B:app می‌فهمیم. در عمل بعدهای بیشتری هم لازمه مثل سیستم عامل و مرورگر تا مثلا اگر apple یک نسخه جدید داد که به ما نمی‌ساخت و مشتریان آیفونی ما رفتن رو هوا، بفهمیم.

این‌ها شاید بدیهی باشه ولی الان به خاطر عدم رعایت درست و همگِن همین‌ها، ما ناچار شدیم بریم ده‌ها حادثه‌ی مرتبه‌ی X به بالای N ماه گذشته‌مون رو بررسی کنیم و یک مجموعه‌ی استاندارد از ۵ ۶ بُعد مهم درآریم و یه گروه نیرو بذاریم و کد بازخوانی کنیم و بینایی‌پذیری چندبعدی اضافه کنیم.

چرا؟ چون بیشتر مشکل‌ها، به ویژه وقتی سیستم بالغ می‌شه، فقط برای بخشی از سرویس یا بخشی از کاربران رخ می‌دن. شناسایی این مشکل‌ها در شاخص‌های بُرش نخورده غیرممکنه، مثلا یک اُفت ۱۰۰٪ی در مثال B:app، در شاخص‌های مجموع (بُرش نخورده) شاید یک اُفت ۵٪ی هم نباشه و در نویز نمودارها گُمه.

بدون پایش بُرش‌خورده، بیشتر مشکل‌ها رو در هیچ یک از مراحل تست یا قناری یا محیط عملیاتی نخواهیم دید بلکه کسب و کارمون یا (از اون مهم‌تر) کاربرمون خواهد دید.

۳. پایش شاخص(metric)های بی‌درنگ یا logهای تجمیع شده؟

(این نوشته پیش‌تر به شکل رشته توییت نوشته شده بوده و سپس در ویرگول رونوشت شده)

دو فصل بالا درباره‌ی پایش بر اساس شاخص‌های بی‌درنگ (real time) از سرورها بود. یک مکتب موازی در پایش، پایش بر اساس logهاست - نه debug log (مثل info و warning و ...) بلکه log ردگیری (trace) که به ازای هر درخواست ذخیره می‌کنیم.

پایش از روی logهای تجمیع و پردازش شده (که مثلا بر اساسش پرداخت انجام می‌دیم) سودهایی داره مثل:‌ (۱) به اون‌چه نهایتا برای ما مهمه نزدیک‌تره تا شاخص‌های خام از وسط کُد، (۲) با logها می‌شه بُرش(slice)های ریزدانه‌تر (granular) پایش کرد مثلا نمودار فلان چیز بُرش‌شده بر اساس «نسخه»‌ی مرورگر.

ولی کاستی‌هایی داره مثل: (۱) تاخیر زیاد، چون logهای نهایی حاصل pipelineهای کُندِ پردازشیه (مثلا ترکیب میلیون‌ها رخداد «نمایش پیشنهاد» توسط ما و «کلیک روی اون» توسط کاربر و سپس تجمیع و سپس خطا/spam زدایی و سپس ...)، (۲) به خوبی عمل‌پذیر (actionable) نیست چون داریم می‌گیم اون تهِ تهِ خط یه چیزی افتاده و اون وسط‌مَسط‌های ده‌ها سرویس، یه جایی یه چیزی خراب شده، حالا پیدا کنید پرتقال‌فروش را. هر دو مکتب--شاخص‌های بی‌درنگ و logهای تجمیع شده--لازم و مکمل همه، ولی اگر ناچاریم یکی رو انتخاب کنیم، مقایسه‌ای که ارائه شد رو می‌ذاریم جلوی نیازمندی‌هامون.

۴. پایش برای شکارِ ناهنجاری - anomaly monitoring

(این نوشته پیش‌تر به شکل رشته توییت نوشته شده بوده و سپس در ویرگول رونوشت شده)

روش سنتی برای هشداردهی روی شاخص(metric)ها، تعریف آستانه‌ی بالا و پایین است که روشی بسیار کارا برای نمودارهایی مانند نرخ خطاست که قراره یک مقدار ثابت (نزدیک صفر) باشن. ولی برای نمودارهایی که در طول روز بالا و پایین می‌رن، چنین روشی یا قادر به کشف بیشتر ناهنجاری‌ها (anomalyها) نخواهد بود یا پر از هشدار غلط.

اولین نکته درباره‌ی راه‌حل‌های این مساله، که شاید بدیهی باشه، اینه که برای نیازمندی «فقط هنگامی هشدار بده که مشکلی هست» پاسخ ۱۰۰٪ی اصلا وجود نداره که بخوایم دنبالش باشیم. مثلا جلوی یک دوربین که قراره تحرکات مشکوک رو تشخیص و هشدار بده، هیچ سیستمی نمی‌تونه «دقیق» باشه. پس هر حرفی بزنیم درباره‌ی «بهبود» هست نه «حل».

نمودارهایی که گفته شد، کم و بیش الگوی روزانه و به ویژه هفتگی دارن. یک روش ساده و سنتی برای تشخیص ناهنجاری (anomaly) روی این نمودارها، مقایسه‌ی هفتگی است: مقایسه‌ی اُفت و خیزِ نسبتِ مقدار در لحظه‌ی کنونی به مقدار در هفته‌ی پیش در همین لحظه. سپس می‌شه آستانه تعریف کرد که این نسبت باید حول و حوش ۱ باشه، یعنی مثلا بین ۰/۵ و ۲.

راه بهتر، سیستم‌هایی است که با یادگیری ماشین (ML)، بازه‌ی مورد انتظار برای نمودار رو در هر لحظه تخمین بزنن. برای این منظور ما دو جور کار می‌کنیم:‌ (۱) دقیق‌تر کردن تخمین بازه‌ی مورد انتظار (هم دقتِ پیش‌بینی و هم confidence interval پیش‌بینی)، (۲)‌ فیلتر کردن بُرش(slice)های کم‌اهمیت - اگر شاخص‌های چندبُعدی با کاردینالیتی بالا دارید نخواهید خواست تک تک بُرش‌ها رو پایش کنید چون بسیاری‌شون مهم نیستند و به حجم هشدارهای حاصل نمی‌ارزن.

برای (۱)، بسته به هزینه‌ی نفر-ساعتی که حاضرید صرف کنید راه‌حل‌هایی آماری و MLی وجود داره مثلا یک کاری که ما می‌کنیم استفاده از «ورودی»های سیستم به شکل feature برای بهبود تخمین «خروجی»هاست یا کاری که یک محصول دیگه می‌کنه بردن نمودار از حوزه‌ی زمانی به حوزه‌ی فرکانسی برای تشخیص افتادگی یا پرِش هست.

پایشباگ
فعال در مهندسی نرم‌افزار با اندکی تجربه از صنعت (عمدتا گوگل) و آکادمی (عمدتا اتلاف عمر). علاقمندم آموخته‌هامون رو رد و بدل کنیم.
شاید از این پست‌ها خوشتان بیاید