Bioyino - توزیع‌کننده معیارهای مقیاس‌پذیر

بنابراین شما معیارها را جمع آوری می کنید. همانطور که ما هستیم. ما همچنین معیارها را جمع آوری می کنیم. البته برای تجارت ضروری است. امروز ما در مورد اولین پیوند سیستم نظارت خود صحبت خواهیم کرد - یک سرور تجمع سازگار با statsd بیوینو، چرا آن را نوشتیم و چرا بروبک را رها کردیم.

Bioyino - توزیع‌کننده معیارهای مقیاس‌پذیر

از مقالات قبلی ما (1, 2) می توانید دریابید که تا مدتی ما با استفاده از علائم جمع آوری کردیم بروبک. این به زبان C نوشته شده است. از نقطه نظر کد، به سادگی یک دوشاخه است (این مهم زمانی است که می خواهید مشارکت داشته باشید) و از همه مهمتر، حجم 2 میلیون متریک در ثانیه (MPS) ما را در اوج کنترل می کند. بدون هیچ مشکلی. اسناد پشتیبانی از 4 میلیون MPS را با یک ستاره بیان می کند. این بدان معنی است که اگر شبکه را به درستی در لینوکس پیکربندی کنید، رقم ذکر شده را دریافت خواهید کرد. (ما نمی دانیم اگر شبکه را همانطور که هست ترک کنید می توانید چند MPS دریافت کنید). علیرغم این مزایا، ما چندین شکایت جدی در مورد بروبک داشتیم.

ادعای 1. Github، توسعه‌دهنده پروژه، پشتیبانی از آن را متوقف کرد: انتشار وصله‌ها و اصلاحات، پذیرش روابط عمومی ما و (نه تنها ما) در چند ماه گذشته (حدود فوریه تا مارس 2018) فعالیت از سر گرفته شده است، اما قبل از آن تقریباً 2 سال آرامش کامل وجود داشت. علاوه بر این، این پروژه در حال توسعه است برای نیازهای داخلی Gihub، که می تواند به مانعی جدی برای معرفی ویژگی های جدید تبدیل شود.

ادعای 2. دقت محاسبات Brubeck در مجموع 65536 مقدار را برای تجمع جمع آوری می کند. در مورد ما، برای برخی از معیارها، در طول دوره تجمیع (30 ثانیه)، ممکن است مقادیر بسیار بیشتری برسد (1،527،392 در اوج). در نتیجه این نمونه برداری، مقادیر حداکثر و حداقل بی فایده به نظر می رسد. به عنوان مثال، مانند این:

Bioyino - توزیع‌کننده معیارهای مقیاس‌پذیر
آن گونه که بود

Bioyino - توزیع‌کننده معیارهای مقیاس‌پذیر
چگونه باید می بود

به همین دلیل، مبالغ به طور کلی اشتباه محاسبه می شود. در اینجا یک اشکال با سرریز شناور 32 بیتی اضافه کنید، که معمولاً هنگام دریافت یک معیار به ظاهر بی‌گناه، سرور را به خطای Segfault می‌فرستد و همه چیز عالی می‌شود. اتفاقاً باگ برطرف نشده است.

و در نهایت، ادعای X. در زمان نگارش، ما آماده ایم آن را به تمام 14 پیاده سازی statsd کم و بیش فعالی که توانستیم پیدا کنیم، ارائه کنیم. بیایید تصور کنیم که برخی زیرساخت‌ها آنقدر رشد کرده‌اند که پذیرش 4 میلیون MPS دیگر کافی نیست. یا حتی اگر هنوز رشد نکرده است، اما معیارها از قبل آنقدر برای شما مهم هستند که حتی ریزش‌های کوتاه 2 تا 3 دقیقه‌ای در نمودارها می‌توانند از قبل بحرانی شوند و باعث حملات افسردگی غیرقابل حل در بین مدیران شوند. از آنجایی که درمان افسردگی یک کار ناسپاس است، راه حل های فنی مورد نیاز است.

در مرحله اول، تحمل خطا، به طوری که یک مشکل ناگهانی در سرور باعث یک آخرالزمان زامبی روانپزشکی در دفتر نشود. ثانیا، مقیاس پذیری برای پذیرش بیش از 4 میلیون MPS، بدون حفاری عمیق در پشته شبکه لینوکس و رشد آرام "در وسعت" به اندازه مورد نیاز.

از آنجایی که ما فضایی برای مقیاس بندی داشتیم، تصمیم گرفتیم با تحمل خطا شروع کنیم. "در باره! تحمل خطا! ساده است، ما می‌توانیم آن را انجام دهیم، فکر کردیم و ۲ سرور راه‌اندازی کردیم و روی هر کدام یک کپی از brubeck ایجاد کردیم. برای انجام این کار، باید ترافیک را با معیارها در هر دو سرور کپی کرده و حتی برای این کار بنویسیم ابزار کوچک. ما مشکل تحمل خطا را با این حل کردیم، اما... نه خیلی خوب. در ابتدا همه چیز عالی به نظر می رسید: هر Brubeck نسخه خود را از تجمع جمع آوری می کند، داده ها را هر 30 ثانیه یک بار در Graphite می نویسد و بازه قدیمی را بازنویسی می کند (این کار در سمت Graphite انجام می شود). اگر یک سرور به طور ناگهانی از کار بیفتد، ما همیشه سرور دومی داریم که کپی خودش از داده های انباشته است. اما مشکل اینجاست: اگر سرور از کار بیفتد، یک "اره" روی نمودارها ظاهر می شود. این به این دلیل است که فواصل 30 ثانیه‌ای بروبک هماهنگ نیستند و در لحظه سقوط یکی از آنها بازنویسی نمی‌شود. وقتی سرور دوم راه اندازی می شود، همین اتفاق می افتد. کاملا قابل تحمل است، اما من بهتر می خواهم! مشکل مقیاس پذیری نیز برطرف نشده است. همه معیارها هنوز به یک سرور واحد "پرواز می کنند" و بنابراین بسته به سطح شبکه به همان 2-4 میلیون MPS محدود می شویم.

اگر کمی در مورد مشکل فکر کنید و در عین حال برف را با بیل حفر کنید، ممکن است ایده بدیهی زیر به ذهنتان خطور کند: به یک statsd نیاز دارید که بتواند در حالت توزیع شده کار کند. یعنی همگام سازی بین گره ها در زمان و معیارها. گفتیم: «البته، احتمالاً چنین راه حلی از قبل وجود داشته است» و به سراغ گوگل رفتیم. و چیزی پیدا نکردند. پس از بررسی اسناد مربوط به آمارهای مختلف (https://github.com/etsy/statsd/wiki#server-implementations از 11.12.2017 دسامبر XNUMX)، ما مطلقاً چیزی پیدا نکردیم. ظاهراً نه توسعه‌دهندگان و نه کاربران این راه‌حل‌ها هنوز با معیارهای بسیار زیادی مواجه نشده‌اند، در غیر این صورت قطعاً چیزی به ذهنشان می‌رسد.

و سپس ما در مورد "اسباب بازی" statsd - bioyino که در هکاتون Just for Fun نوشته شده بود (نام پروژه قبل از شروع هکاتون توسط اسکریپت ایجاد شده بود) به یاد آوردیم و متوجه شدیم که ما به statsd خود نیاز فوری داریم. برای چی؟

  • زیرا کلون های آماری بسیار کمی در جهان وجود دارد،
  • زیرا امکان ارائه تلورانس و مقیاس پذیری مطلوب یا نزدیک به خطای مورد نظر (از جمله همگام سازی معیارهای انبوه بین سرورها و حل مشکل ارسال تداخل) وجود دارد.
  • زیرا می توان معیارها را دقیق تر از بروبک محاسبه کرد،
  • زیرا شما می توانید آمار دقیق تری را خودتان جمع آوری کنید، چیزی که بروبک عملاً در اختیار ما قرار نداد،
  • چون من این فرصت را داشتم که اپلیکیشن آزمایشگاه مقیاس توزیع شده با عملکرد فوق العاده خود را برنامه ریزی کنم، که معماری یک هایپر مشابه دیگر را به طور کامل تکرار نخواهد کرد... خوب، همین است.

روی چه چیزی بنویسیم؟ البته در Rust. چرا؟

  • زیرا قبلاً یک راه حل نمونه اولیه وجود داشت،
  • زیرا نویسنده مقاله قبلاً Rust را در آن زمان می‌شناخت و مشتاق بود چیزی در آن برای تولید بنویسد و فرصتی برای قرار دادن آن در متن باز داشته باشد.
  • زیرا زبان‌های دارای GC به دلیل ماهیت ترافیک دریافتی (تقریبا بی‌درنگ) برای ما مناسب نیستند و مکث GC عملاً غیرقابل قبول است،
  • زیرا شما به حداکثر عملکرد قابل مقایسه با C نیاز دارید
  • زیرا Rust همزمانی بی‌باکانه‌ای را برای ما فراهم می‌کند، و اگر نوشتن آن را در C/C++ شروع می‌کردیم، حتی آسیب‌پذیری‌ها، سرریزهای بافر، شرایط مسابقه و سایر کلمات ترسناک به جز brubeck را افزایش می‌دادیم.

استدلالی هم علیه رست وجود داشت. این شرکت تجربه ایجاد پروژه در Rust را نداشت و اکنون نیز قصد نداریم از آن در پروژه اصلی استفاده کنیم. بنابراین، ترس جدی وجود داشت که هیچ چیز درست نشود، اما ما تصمیم گرفتیم از فرصت استفاده کنیم و تلاش کردیم.

زمان گذشت...

سرانجام پس از چندین بار تلاش ناموفق، اولین نسخه کاری آماده شد. چی شد؟ این چیزی است که اتفاق افتاد.

Bioyino - توزیع‌کننده معیارهای مقیاس‌پذیر

هر گره مجموعه‌ای از معیارهای خود را دریافت می‌کند و آنها را انباشته می‌کند، و معیارها را برای انواعی که مجموعه کامل آنها برای تجمیع نهایی لازم است، جمع نمی‌کند. گره ها توسط نوعی پروتکل قفل توزیع شده به یکدیگر متصل می شوند که به شما امکان می دهد از بین آنها تنها موردی را انتخاب کنید (اینجا ما گریه کردیم) که شایسته ارسال معیارها به Great One است. این مشکل در حال حاضر توسط کنسول، اما در آینده جاه طلبی های نویسنده به خود پیاده سازی Raft، جایی که شایسته ترین آنها، البته، گره رهبر اجماع خواهد بود. علاوه بر اجماع، گره‌ها اغلب (به‌طور پیش‌فرض یک‌بار در ثانیه) بخش‌هایی از معیارهای از پیش انباشته‌شده را که در آن ثانیه جمع‌آوری کرده‌اند، به همسایگان خود ارسال می‌کنند. به نظر می رسد که مقیاس بندی و تحمل خطا حفظ می شود - هر گره هنوز مجموعه کاملی از معیارها را در خود دارد، اما معیارها قبلاً جمع آوری شده اند، از طریق TCP و در یک پروتکل باینری کدگذاری شده اند، بنابراین هزینه های تکرار در مقایسه با UDP به طور قابل توجهی کاهش می یابد. با وجود تعداد نسبتاً زیاد معیارهای ورودی، انباشتگی به حافظه بسیار کمی و حتی CPU کمتری نیاز دارد. برای معیارهای بسیار قابل تراکم ما، این تنها چند ده مگابایت داده است. به عنوان یک امتیاز اضافی، ما هیچ گونه بازنویسی غیرضروری داده در Graphite دریافت نمی کنیم، همانطور که در مورد burbeck بود.

بسته های UDP با معیارها بین گره های تجهیزات شبکه از طریق یک Round Robin ساده نامتعادل هستند. البته، سخت‌افزار شبکه محتویات بسته‌ها را تجزیه نمی‌کند و بنابراین می‌تواند بسیار بیشتر از 4 میلیون بسته در ثانیه بکشد، البته به معیارهایی که اصلاً درباره آن چیزی نمی‌داند. اگر در نظر بگیریم که معیارها یک به یک در هر بسته ارائه نمی شوند، هیچ مشکل عملکردی در این مکان پیش بینی نمی کنیم. اگر یک سرور از کار بیفتد، دستگاه شبکه به سرعت (در عرض 1-2 ثانیه) این واقعیت را تشخیص داده و سرور از کار افتاده را از چرخش خارج می کند. در نتیجه، گره‌های غیرفعال (یعنی غیر رهبر) را می‌توان عملاً بدون توجه به افت در نمودارها روشن و خاموش کرد. حداکثری که از دست می دهیم بخشی از معیارهایی است که در آخرین ثانیه به دست آمد. از دست دادن/خاموش کردن/سوئیچ ناگهانی یک رهبر همچنان یک ناهنجاری جزئی ایجاد می کند (بازه 30 ثانیه ای هنوز همگام نیست)، اما اگر ارتباط بین گره ها وجود داشته باشد، می توان این مشکلات را به حداقل رساند، به عنوان مثال، با ارسال بسته های همگام سازی. .

کمی در مورد ساختار داخلی. البته این برنامه چند رشته ای است، اما معماری نخی با آنچه در بروبک استفاده می شود متفاوت است. موضوعات در بروبک یکسان است - هر یک از آنها مسئول جمع آوری و تجمیع اطلاعات هستند. در bioyino، کارگران به دو گروه تقسیم می شوند: کسانی که مسئول شبکه و کسانی که مسئول تجمع هستند. این تقسیم‌بندی به شما امکان می‌دهد بسته به نوع معیارها، برنامه را با انعطاف‌پذیری بیشتری مدیریت کنید: در جاهایی که به تجمیع فشرده نیاز است، می‌توانید جمع‌کننده‌ها را اضافه کنید، در جایی که ترافیک شبکه زیاد است، می‌توانید تعداد جریان‌های شبکه را اضافه کنید. در حال حاضر، در سرورهای خود ما در 8 جریان شبکه و 4 جریان تجمعی کار می کنیم.

بخش شمارش (مسئول تجمیع) کاملا خسته کننده است. بافرهای پر شده توسط جریان های شبکه در میان جریان های شمارش کننده توزیع می شوند، جایی که متعاقبا تجزیه و تجمیع می شوند. در صورت درخواست، معیارهایی برای ارسال به گره های دیگر داده می شود. همه اینها، از جمله ارسال داده ها بین گره ها و کار با Consul، به صورت ناهمزمان انجام می شود و روی چارچوب اجرا می شود. توکیو.

مشکلات بسیار بیشتری در طول توسعه توسط بخش شبکه مسئول دریافت معیارها ایجاد شد. هدف اصلی از جداسازی جریان های شبکه به موجودیت های مجزا، تمایل به کاهش زمانی بود که یک جریان صرف می کند. هیچ برای خواندن داده ها از سوکت گزینه‌هایی که از UDP ناهمزمان و recvmsg معمولی استفاده می‌کردند به سرعت ناپدید شدند: اولی CPU فضای کاربر زیادی را برای پردازش رویداد مصرف می‌کند، دومی نیاز به سوئیچ‌های زمینه زیادی دارد. بنابراین در حال حاضر استفاده می شود recvmmsg با بافرهای بزرگ (و بافرها، آقایان افسران، برای شما چیزی نیستند!). پشتیبانی از UDP معمولی برای موارد سبک که نیازی به recvmmsg نیست محفوظ است. در حالت چند پیامی، دستیابی به هدف اصلی امکان پذیر است: در اکثر مواقع، رشته شبکه صف سیستم عامل را جمع می کند - داده ها را از سوکت می خواند و به بافر فضای کاربر منتقل می کند، فقط گاهی اوقات به بافر پر شده تغییر می دهد. جمع کننده ها صف در سوکت عملاً جمع نمی شود ، تعداد بسته های رها شده عملاً رشد نمی کند.

یادداشت

در تنظیمات پیش فرض، اندازه بافر کاملاً بزرگ تنظیم شده است. اگر به طور ناگهانی تصمیم گرفتید سرور را خودتان امتحان کنید، ممکن است با این واقعیت مواجه شوید که پس از ارسال تعداد کمی از معیارها، آنها به Graphite نمی‌رسند و در بافر جریان شبکه باقی می‌مانند. برای کار با تعداد کمی از معیارها، باید bufsize و task-queue-size را روی مقادیر کوچکتر در پیکربندی تنظیم کنید.

در نهایت، چند نمودار برای دوستداران نمودار.

آمار تعداد معیارهای ورودی برای هر سرور: بیش از 2 میلیون MPS.

Bioyino - توزیع‌کننده معیارهای مقیاس‌پذیر

غیرفعال کردن یکی از گره ها و توزیع مجدد معیارهای ورودی.

Bioyino - توزیع‌کننده معیارهای مقیاس‌پذیر

آمار مربوط به معیارهای خروجی: فقط یک گره همیشه ارسال می کند - رئیس حمله.

Bioyino - توزیع‌کننده معیارهای مقیاس‌پذیر

آمار عملکرد هر گره با در نظر گرفتن خطاها در ماژول های مختلف سیستم.

Bioyino - توزیع‌کننده معیارهای مقیاس‌پذیر

جزئیات معیارهای دریافتی (نام های متریک پنهان هستند).

Bioyino - توزیع‌کننده معیارهای مقیاس‌پذیر

در آینده با این همه برنامه چه کنیم؟ البته کد بنویس لعنتی...! این پروژه در ابتدا برنامه ریزی شده بود که منبع باز باشد و در طول عمر خود به همین شکل باقی خواهد ماند. برنامه های فوری ما شامل تغییر به نسخه Raft خودمان، تغییر پروتکل همتا به یک پروتکل قابل حمل تر، معرفی آمار داخلی اضافی، انواع جدید معیارها، رفع اشکالات و سایر پیشرفت ها است.

البته، از همه برای کمک در توسعه پروژه استقبال می شود: ایجاد روابط عمومی، مسائل، در صورت امکان پاسخ می دهیم، بهبود می دهیم و غیره.

با این اوصاف، این همه مردم، فیل های ما را بخرید!



منبع: www.habr.com

اضافه کردن نظر