همانطور که از یک برنامه کاربردی یکپارچه به معماری میکروسرویس ها حرکت می کنیم، با چالش های جدیدی روبرو هستیم.
در یک برنامه یکپارچه، معمولاً تشخیص خطا در کدام بخش از سیستم بسیار آسان است. به احتمال زیاد مشکل در کد خود monolith یا در پایگاه داده است. اما وقتی شروع به جستجوی مشکل در معماری میکروسرویس می کنیم، دیگر همه چیز چندان واضح نیست. ما باید کل مسیری را که درخواست از ابتدا تا انتها طی کرده است، پیدا کرده و آن را از میان صدها میکروسرویس انتخاب کنیم. علاوه بر این، بسیاری از آنها همچنین دارای امکانات ذخیره سازی خاص خود هستند که می تواند باعث خطاهای منطقی و همچنین مشکلات عملکرد و تحمل خطا شود.
من مدت زیادی است که به دنبال ابزاری هستم که به مقابله با چنین مشکلاتی کمک کند (در مورد این در Habré نوشتم:
ردیابی توزیع شده یک راه حل رایج برای مشکل یافتن خطا در سیستم های توزیع شده است. اما اگر این رویکرد برای جمعآوری اطلاعات در مورد تعاملات شبکه هنوز در سیستم پیادهسازی نشده باشد، یا بدتر از آن، در بخشی از سیستم از قبل به درستی کار میکند، اما تا حدودی این کار را نمیکند، زیرا به سرویسهای قدیمی اضافه نشده است. ? برای تعیین دقیق علت اصلی یک مشکل، لازم است تصویر کاملی از آنچه در سیستم اتفاق می افتد داشته باشید. به ویژه مهم است که بدانیم کدام میکروسرویس ها در مسیرهای کلیدی حیاتی کسب و کار دخیل هستند.
در اینجا رویکرد مش خدمات می تواند به کمک ما بیاید، که با تمام ماشین آلات جمع آوری اطلاعات شبکه در سطحی پایین تر از خود سرویس ها سروکار دارد. این رویکرد به ما اجازه می دهد تا تمام ترافیک را رهگیری کرده و آن را در لحظه تجزیه و تحلیل کنیم. علاوه بر این، برنامه ها حتی نیازی به دانستن چیزی در مورد آن ندارند.
رویکرد مش خدمات
ایده اصلی رویکرد مش سرویس اضافه کردن یک لایه زیرساخت دیگر بر روی شبکه است که به ما امکان می دهد هر کاری را با تعامل بین سرویس انجام دهیم. اکثر پیادهسازیها به شرح زیر عمل میکنند: یک محفظه جانبی اضافی با یک پروکسی شفاف به هر میکروسرویس اضافه میشود که از طریق آن تمام ترافیک ورودی و خروجی سرویس منتقل میشود. و اینجا همان جایی است که میتوانیم تعادل مشتری را انجام دهیم، سیاستهای امنیتی را اعمال کنیم، محدودیتهایی بر تعداد درخواستها اعمال کنیم و اطلاعات مهمی در مورد تعامل خدمات در تولید جمعآوری کنیم.
راه حل ها
در حال حاضر چندین پیاده سازی از این رویکرد وجود دارد:
در نتیجه، ما دقیقاً به چه قابلیت هایی در حال حاضر نیاز داشتیم و به این نتیجه رسیدیم که دلیل اصلی اجرای چنین راه حل هایی، توانایی جمع آوری اطلاعات ردیابی از کل سیستم به صورت شفاف است. همچنین میخواستیم بر تعامل سرویسها کنترل داشته باشیم و دستکاریهای مختلفی را با هدرهایی که بین سرویسها منتقل میشوند انجام دهیم.
در نتیجه به تصمیم خود رسیدیم:
نترامش
اهداف اصلی راه حل جدید سربار منابع کم و عملکرد بالا بود. در میان ویژگیهای اصلی، ما بلافاصله میخواستیم بتوانیم بهطور شفاف دهانههای ردیابی را به سیستم Jaeger خود ارسال کنیم.
امروزه اکثر راه حل های ابری در Golang پیاده سازی می شوند. و البته دلایلی برای این امر وجود دارد. نوشتن برنامه های شبکه در Golang که به صورت ناهمزمان با I/O کار می کنند و در صورت نیاز در هسته ها مقیاس می شوند، راحت و بسیار ساده است. و آنچه نیز بسیار مهم است، عملکرد برای حل این مشکل کافی است. به همین دلیل ما نیز گلنگ را انتخاب کردیم.
کارایی
ما تلاش خود را بر دستیابی به حداکثر بهره وری متمرکز کرده ایم. برای راه حلی که در کنار هر نمونه از سرویس مستقر می شود، مصرف کمی از زمان RAM و CPU مورد نیاز است. و البته تاخیر پاسخ نیز باید کم باشد.
ببینیم چه نتایجی گرفتیم.
رم
نترامش 10 مگابایت بدون ترافیک و حداکثر 50 مگابایت با بار تا 10000 RPS در هر نمونه مصرف می کند.
پروکسی فرستاده Istio همیشه 300 مگابایت در خوشه های ما با هزاران نمونه مصرف می کند. این اجازه نمی دهد که آن را به کل خوشه مقیاس کنید.
با Netramesh ما 10 برابر کاهش مصرف حافظه داشتیم.
پردازنده
استفاده از CPU تحت بار نسبتاً برابر است. این بستگی به تعداد درخواستها در واحد زمان به ماشین کناری دارد. مقادیر 3000 درخواست در ثانیه در اوج:
یک نکته مهم دیگر وجود دارد: Netramesh - یک راه حل بدون صفحه کنترل و بدون بار زمان CPU را مصرف نمی کند. با ایستیو، سایدکارها همیشه نقاط پایانی سرویس را به روز می کنند. در نتیجه، ما می توانیم این تصویر را بدون بار مشاهده کنیم:
ما از HTTP/1 برای ارتباط بین سرویس ها استفاده می کنیم. افزایش زمان پاسخ برای Istio هنگام پروکسی از طریق envoy تا 5-10 میلی ثانیه بود که برای سرویس هایی که آماده پاسخگویی در یک میلی ثانیه هستند بسیار زیاد است. با Netramesh این زمان به 0.5-2ms کاهش یافته است.
مقیاس پذیری
مقدار کمی از منابع مصرف شده توسط هر پروکسی امکان قرار دادن آن را در کنار هر سرویس فراهم می کند. نترامش عمداً بدون یک جزء هواپیمای کنترلی ایجاد شد تا به سادگی وزن هر یک از خودروهای جانبی را سبک نگه دارد. اغلب در راه حل های مش سرویس، صفحه کنترل اطلاعات کشف سرویس را به هر یک از چرخ های کناری توزیع می کند. همراه با آن اطلاعاتی در مورد وقفه ها و تنظیمات تعادل ارائه می شود. همه اینها به شما امکان می دهد کارهای مفید زیادی انجام دهید، اما، متأسفانه، سایز کارها را باد می کند.
کشف خدمات
Netramesh هیچ مکانیزم اضافی برای کشف سرویس اضافه نمی کند. تمام ترافیک به طور شفاف از طریق نترا سایدکار پراکسی می شود.
Netramesh از پروتکل برنامه HTTP/1 پشتیبانی می کند. برای تعریف آن، یک لیست قابل تنظیم از پورت ها استفاده می شود. به طور معمول، سیستم دارای چندین پورت است که ارتباط HTTP از طریق آنها انجام می شود. به عنوان مثال، ما از 80، 8890، 8080 برای تعامل بین سرویس ها و درخواست های خارجی استفاده می کنیم، در این حالت می توان آنها را با استفاده از یک متغیر محیطی تنظیم کرد. NETRA_HTTP_PORTS
.
اگر از Kubernetes به عنوان ارکستراتور و مکانیسم نهاد سرویس آن برای ارتباط درون خوشه ای بین سرویس ها استفاده می کنید، مکانیسم دقیقاً یکسان باقی می ماند. ابتدا میکروسرویس یک آدرس IP سرویس را با استفاده از kube-dns دریافت می کند و یک اتصال جدید به آن باز می کند. این ارتباط ابتدا با netra-sidecar محلی برقرار می شود و تمام بسته های TCP ابتدا به netra می رسند. در مرحله بعد، netra-sidecar با مقصد اصلی ارتباط برقرار می کند. NAT در IP pod روی گره دقیقاً مانند بدون netra باقی می ماند.
ردیابی توزیع شده و ارسال متن
Netramesh عملکرد مورد نیاز برای ارسال بازه های ردیابی در مورد تعاملات HTTP را فراهم می کند. Netra-sidecar پروتکل HTTP را تجزیه می کند، تاخیرهای درخواست را اندازه گیری می کند و اطلاعات لازم را از هدرهای HTTP استخراج می کند. در نهایت، ما تمام ردیابی ها را در یک سیستم Jaeger به دست می آوریم. برای پیکربندی دقیق، می توانید از متغیرهای محیطی ارائه شده توسط کتابخانه رسمی نیز استفاده کنید
اما یک مشکل وجود دارد. تا زمانی که سرویسها یک هدر ویژه uber را ایجاد و ارسال نکنند، ما شاهد گسترههای ردیابی متصل در سیستم نخواهیم بود. و این همان چیزی است که برای یافتن سریع علت مشکلات به آن نیاز داریم. در اینجا نیز نترامش یک راه حل دارد. پروکسی ها سرصفحه های HTTP را می خوانند و اگر حاوی شناسه ردیابی uber نباشند، یکی را ایجاد می کنند. Netramesh همچنین اطلاعات مربوط به درخواستهای ورودی و خروجی را در یک sidecar ذخیره میکند و با غنیسازی آنها با سرصفحههای درخواست خروجی لازم، آنها را مطابقت میدهد. تنها کاری که باید در سرویس ها انجام دهید ارسال یک هدر است X-Request-Id
، که می تواند با استفاده از یک متغیر محیطی پیکربندی شود NETRA_HTTP_REQUEST_ID_HEADER_NAME
. برای کنترل اندازه زمینه در Netramesh، می توانید متغیرهای محیطی زیر را تنظیم کنید: NETRA_TRACING_CONTEXT_EXPIRATION_MILLISECONDS
(زمانی که متن برای آن ذخیره خواهد شد) و NETRA_TRACING_CONTEXT_CLEANUP_INTERVAL
(فرکانس پاکسازی زمینه).
همچنین می توانید چندین مسیر را در سیستم خود با علامت گذاری با یک نشانه جلسه خاص ترکیب کنید. Netra به شما امکان نصب را می دهد HTTP_HEADER_TAG_MAP
برای تبدیل سرصفحههای HTTP به تگهای فاصله ردیابی مربوطه. این می تواند به ویژه برای آزمایش مفید باشد. پس از گذراندن تست عملکرد، می توانید ببینید که کدام قسمت از سیستم تحت تأثیر فیلتر کردن توسط کلید جلسه مربوطه قرار گرفته است.
تعیین منبع درخواست
برای تعیین اینکه درخواست از کجا آمده است، میتوانید از قابلیت افزودن خودکار هدر با منبع استفاده کنید. استفاده از متغیر محیطی NETRA_HTTP_X_SOURCE_HEADER_NAME
می توانید نام سرصفحه ای را تعیین کنید که به طور خودکار نصب شود. با استفاده از NETRA_HTTP_X_SOURCE_VALUE
می توانید مقداری را که هدر X-Source برای همه درخواست های خروجی تنظیم می شود، تنظیم کنید.
این اجازه می دهد تا توزیع این هدر مفید به طور یکنواخت در سراسر شبکه توزیع شود. سپس میتوانید از آن در سرویسها استفاده کنید و آن را به گزارشها و معیارها اضافه کنید.
مسیریابی ترافیک و داخلی نترامش
نترامش از دو جزء اصلی تشکیل شده است. اولین مورد، netra-init، قوانین شبکه را برای رهگیری ترافیک تنظیم می کند. او استفاده میکند INBOUND_INTERCEPT_PORTS, OUTBOUND_INTERCEPT_PORTS
.
این ابزار همچنین دارای یک ویژگی جالب است - مسیریابی احتمالی. اگر از Netramesh به طور انحصاری برای جمع آوری بازه های ردیابی استفاده می کنید، در یک محیط تولید می توانید منابع را ذخیره کنید و مسیریابی احتمالی را با استفاده از متغیرها فعال کنید. NETRA_INBOUND_PROBABILITY
и NETRA_OUTBOUND_PROBABILITY
(از 0 تا 1). مقدار پیش فرض 1 است (تمام ترافیک متوقف می شود).
پس از رهگیری موفقیت آمیز، netra sidecar اتصال جدید را می پذیرد و استفاده می کند SO_ORIGINAL_DST
گزینه سوکت برای دریافت مقصد اصلی. سپس Netra یک اتصال جدید به آدرس IP اصلی باز می کند و ارتباط TCP دو طرفه را بین طرفین برقرار می کند و به تمام ترافیک عبوری گوش می دهد. اگر پورت به عنوان HTTP تعریف شود، Netra سعی می کند آن را تجزیه و ردیابی کند. اگر تجزیه HTTP ناموفق باشد، Netra به TCP برمی گردد و به طور شفاف بایت ها را پراکسی می کند.
ساخت نمودار وابستگی
پس از دریافت حجم زیادی از اطلاعات ردیابی در Jaeger، می خواهم یک نمودار کامل از تعاملات در سیستم را دریافت کنم. اما اگر سیستم شما کاملاً بارگذاری شده باشد و میلیاردها بازه ردیابی در روز انباشته شود، تجمیع آنها کار آسانی نیست. یک راه رسمی برای انجام این کار وجود دارد:
اگر از Elasticsearch برای ذخیره دهانه های ردیابی استفاده می کنید، می توانید استفاده کنید
نحوه استفاده از نترامش
Netra را می توان به راحتی به هر سرویسی که هر ارکستراتور اجرا می کند اضافه کرد. می توانید یک نمونه را ببینید
در حال حاضر نترا قابلیت پیادهسازی خودکار سایدکارها در سرویسها را ندارد، اما برنامههایی برای پیادهسازی وجود دارد.
آینده نترامش
هدف اصلی
در آینده، Netramesh از پروتکل های لایه کاربردی دیگر به جز HTTP پشتیبانی خواهد کرد. مسیریابی L7 در آینده نزدیک در دسترس خواهد بود.
در صورت برخورد با مشکلات مشابه از نترامش استفاده کنید و سوالات و پیشنهادات خود را با ما بنویسید.
منبع: www.habr.com