عملکردهای لبه 5 برابر سریعتر: V8 به MicroVMهای Firecracker ایزوله می شود
آدرس مقاله: https://www.netlify.com/blog/edge-functions-firecracker-microvms/ آدرس نظرات: https://news.ycombinator.com/item?id=49912444 امتیاز: 219 # نظرات: 96
این یک چالش فنی مهم است، زیرا ما در تلاش هستیم تا تأخیر را تا حد امکان کم کنیم. برای اجرای دهها و گاهی صدها هزار تابع لبه در ثانیه، باید هر درخواست را پردازش کنیم، آن را به درستی مسیریابی کنیم، ظرفیت محاسباتی را تخصیص دهیم و کد پلتفرم خود و کد مشتری را بوت کنیم. همه اینها باید در چند میلی ثانیه اتفاق بیفتد.
طی چند ماه گذشته، تیم ما زیرساختهای مربوط به Edge Functions را بازسازی کرده است و با تیم Unikraft همکاری نزدیکی داشته است، که در مورد تجربه از طرف خود نوشتند. در گذشته، درخواستها به یک سرویس اجرای میزبان ارسال میشد. امروزه، آنها بر روی MicroVM ها در داخل شبکه لبه خودمان اجرا می شوند - تقریبا 5 برابر سریعتر در میانه. این تغییر همچنین امنیت و قابلیت اطمینان را بهبود می بخشد و امکانات بیشتری را برای اجرای محاسبات پیچیده در لبه باز می کند.
این نحوه نوشتن یا استفاده از توابع Edge را تغییر نمیدهد - وارد کردن URL، بستههای npm، Node داخلی، اعلانهای netlify.toml، توسعه محلی - همه اینها دقیقا مانند قبل کار میکنند. اکنون سریعتر و انعطاف پذیرتر است. در این مقاله میخواهیم اطلاعات بیشتری در مورد معماری جدید و آموختههای خود در ساختن یک پلتفرم محاسباتی جدید به اشتراک بگذاریم که قادر به ارائه حجم بالا با سربار کارایی پایین باشد.
یک تابع لبه در مقابل یک سایت اجرا می شود، در هر درخواستی که با آن مطابقت دارد. زمانی که طول میکشد، زمانی است که یک مشتری در انتظار صرف میکند، بنابراین میلیثانیهها در اینجا بیشتر از هر جای دیگری است.
یک فراخوان گرم - مسیریابی به یک گره محاسباتی، وارد کردن یک MicroVM، اجرای تابع، تولید هدرهای پاسخ - اکنون هزینه دارد:
یک فراخوان سرد نیز ارزش بیان کردن دارد. وقتی درخواستی به منطقه ای می رسد که هیچ گره محاسباتی قبلا آن را ندیده است، قبل از اینکه بتواند هر چیزی را اجرا کند، باید تصاویر مربوطه را واکشی کند. این در حدود 1.2٪ از فراخوانی ها اتفاق می افتد و به طور متوسط حدود 9 میلی ثانیه طول می کشد.
آنچه در ادامه میآید مسیری است که یک درخواست به ترتیب طی میکند: به گره لبه میرسد، به یک مشخصات تبدیل میشود، به یک گره محاسباتی هدایت میشود و سپس به یک MicroVM واگذار میشود که ممکن است بر اساس فراخوانی سرد یا گرم وجود داشته باشد یا نباشد.
هر درخواست در نزدیکترین گره لبه Netlify به مشتری قرار می گیرد. گره اتصال TLS را خاتمه می دهد و مسیر درخواست را در برابر مسیرهای Edge Functions برای آن استقرار بررسی می کند.
اگر هیچ چیزی مطابقت نداشته باشد، درخواست طبق معمول به حافظه پنهان و به مبدا منتقل می شود. اگر مسیری مطابقت داشته باشد، این همان نقطه ای است که درخواست از شبکه ما خارج می شود. با زیرساخت قدیمی ما، از طریق اینترنت خارج شد، تابع edge را اجرا کرد و برای انتقال به ما بازگشت. با پلت فرم محاسباتی جدید، درخواست به یک گره محاسباتی در شبکه ما ارسال می شود.
هنگامی که گره محاسباتی درخواست را با مشخصات ماشین و شناسه سرویس دریافت می کند، ابتدا بررسی می کند که آیا سرویسی با آن شناسه قبلا وجود دارد یا خیر. اگر چنین کند، درخواست را به سرویس ارسال می کند تا به MicroVM ارسال شود. یک سرویس به ما امکان می دهد چندین MicroVM مرتبط با توابع لبه یک سایت داشته باشیم، و به ما امکان می دهد پارامترهایی را برای زمانی که MicroVM ها را در داخل و خارج مقیاس کنیم، پیکربندی کنیم. به عنوان مثال، ما هر سرویس را طوری پیکربندی میکنیم که قبل از خاموش کردن MicroVM فقط به تعداد ثابتی از درخواستها اجازه رسیدگی به آن را بدهد تا از اجرای نامحدود MicroVM جلوگیری شود.
ما از همین پارامترها استفاده می کنیم تا بدانیم چه زمانی باید مشتاقانه یک MicroVM دیگر را در انتظار خاموش شدن راه اندازی کنیم.
اگر سرویسی برای توابع لبه سایت از قبل در گره محاسباتی وجود نداشته باشد، یکی ایجاد میشود و بررسی میکنیم که آیا تمام تصاویر موجود در مشخصات ماشین روی دیسک وجود دارد یا خیر. در صورت وجود گم شدن، از گره لبه برداشته شده و روی دیسک نوشته می شود. این رویکرد به این معنی است که ما فقط تصاویر تابع لبه را واکشی می کنیم که در آن منطقه ترافیک دریافت می کنند.
قبل از اینکه درخواست به جایی برسد، گره لبه مشخصاتی را برای ماشینی می نویسد که یک تابع را اجرا می کند. مشخصات سه تصویر را نام میبرد: زمان اجرا، تصویر پلتفرم ما و تصویر تابع لبه. همچنین محدودیت های CPU، حافظه و اتصال را تعیین می کند.
مشخصات با درخواست، در هر درخواست همراه است. اطلاعات هش و سایت خاص آن برای تبدیل شدن به یک شناسه سرویس محاسبه می شود. این امکان جداسازی را فراهم میکند، زیرا دو استقرار با کد متفاوت یا متغیرهای محیطی متفاوت، سرویسهای متفاوتی هستند و هرگز یک MicroVM به اشتراک نمیگذارند.
این انزوا برای شکستهایی که نمیخواهیم ممکن باشد، بیشترین اهمیت را دارد. یک استقرار احتمالی در معرض خطر در یک MicroVM جداگانه اجرا میشود، و حتی اگر از زمان اجرا فرار کند، نمیتواند مشتریان دیگر یا خود لایه محاسباتی را مسموم کند. ایزوله های V8، صرف نظر از نامشان، این سطح ایزوله را ارائه نمی دهند.
هر منطقه دارای گروهی از گره های محاسباتی است. گره لبه یکی را برای سرویس با استفاده از هش کردن قرار میگیرد: همان سرویس هر بار روی همان گره قرار میگیرد، این همان چیزی است که MicroVM را گرم نگه میدارد و کد از قبل روی دیسک و پس از خوانده شدن آن در حافظه نهان ذخیره میشود. این چسبندگی به ما یک استراتژی کش می دهد. اگر درخواستها را به طور مساوی در سراسر گروه پخش کنیم، در نهایت با سطح بالاتری از شروع سرد مواجه میشویم.
مهم است که به خاطر داشته باشید که در حالی که ارسال هر درخواست برای یک تابع به همان گره محاسباتی مسیر سریعی است، اما همچنین نحوه شکل گیری یک نقطه داغ است - جایی که یک تابع مشغول برای منابع با هر چیز دیگری در آن جعبه رقابت می کند. سرویسی که سهم بزرگی از ترافیک یک منطقه را به یک گره متصل می کند، گره را به قیمت سایر سرویس ها اشباع می کند.
ما این را با آرام کردن چسبندگی متعادل می کنیم. بیش از یک آستانه خاص، ما سرویس را در یک تکه از گره ها پخش می کنیم. این به ما امکان میدهد جهشهای ناگهانی ترافیک را از یک مشتری جذب کنیم، بدون اینکه روی سایر سرویسهایی که به همان گره هش شدهاند، تأثیر بگذاریم.
در نهایت، هنگامی که یک گره انتخاب می شود، کد تابع را وارد می کند. یک گره محاسباتی که قبلا تابع را انجام داده است، قبلا آن را دارد. گرهی که برای اولین بار آن را می بیند، یک بار آن را واکشی می کند و آن را در حافظه پنهان ذخیره می کند، بنابراین فقط اولین درخواست آن هزینه را پرداخت می کند.
هر تابع در Firecracker MicroVM خود اجرا می شود. اینها در کمتر از یک میلیثانیه ایجاد میشوند و در حدود 2 میلیثانیه در p99 شروع میشوند، زیرا VM بهجای یک سیستم عامل کامل، یک محیط لینوکس حذفشده را راهاندازی میکند. فایلهای تابع edge بهعنوان یک تصویر EROFS فشردهنشده نصب میشوند و سپس با حافظه نقشهبرداری میشوند، بنابراین VM به جای بارگیری همه آن، تنها بخشهایی از بستهای را که در واقع استفاده میکند، میخواند.
هنگامی که MicroVM بوت می شود و سرور جاوا اسکریپت شروع به گوش دادن به پورت می کند، ما یک عکس فوری از MicroVM می گیریم. هنگامی که تابع لبه فراخوانی نمی شود، MicroVM هایی که آن را اجرا می کنند به جای اینکه بیکار بنشینند، آن را صفر می کنند. دفعه بعد که فراخوانی شد، یک MicroVM جدید را از آن عکس فوری شروع می کنیم. عکس فوری با حافظه نگاشت شده است، بنابراین VM می تواند بدون منتظر ماندن برای بازخوانی کل عکس فوری در حافظه، اجرا را شروع کند.
چرخه عمر VM - بوت، عکس فوری، بازیابی و مقیاس به صفر - کار محصول Unikraft است. ما در طول مهاجرت از نزدیک با آنها کار کردیم تا مطمئن شویم که تحت حجم درخواست و الگوهای ترافیک ما باقی می ماند.
پس از چندین سال بهره برداری از این پروژه، ما قبلا آموخته هایی داشتیم که برای به حداکثر رساندن عملکرد و توانایی اشکال زدایی گنجانده شده بودیم. در مقیاس، ما با انواع مشکلات مواجه شدهایم، از تمام شدن پورتهای سوئیچهای مجازی گرفته تا DNS (متعجب بودیم، اما همیشه DNS نبود).
در این تکرار، ما مطمئن شدیم که گرههای محاسباتی حلکنندههای DNS محلی را اجرا میکنند. ما همچنین معیارهایی را که جمعآوری میکنیم گسترش دادهایم، مواردی مانند زمان راهاندازی، زمان باز شدن اولین پورت و زمان شروع کد کاربر را ضبط میکنیم. همچنین چندین قطع کننده مدار برای اطمینان از مسیریابی مجدد و از کار انداختن سریع گره های محاسباتی وجود دارد.
این کل مسیر است و در یک نمونه گرم حدود 6 میلیثانیه اضافه میکند. هیچکدام از آنها شبکه ما را ترک نمیکند، و ما کنترل کل چرخه درخواست را در دست داریم. همه چیز در بالا بین رسیدن درخواست و بازگشت پاسخ اتفاق می افتد.
وقتی سیستمی مانند آنچه در بالا توضیح داده شد میسازید، همزمان برای دو چیز بهینهسازی میکنید: تجربه کاربر نهایی و انعطافپذیری عرضه. ما باید بتوانیم تغییرات را به سرعت اجرا کنیم، اما آن را با توانایی بازگرداندن به همان سرعت متعادل کنیم.
گره های محاسباتی از یک تصویر پایه منتشر شده توسط Unikraft ساخته شده و مجموعه ای از بسته ها را نصب می کنند. این گره ها به چند دلیل جدا از گره های لبه ما ساخته می شوند: گره های لبه ما را سبک و سریع نگه می دارد، به ما امکان می دهد از انواع نمونه های مختلف برای گره های محاسباتی خود استفاده کنیم، و به ما امکان می دهد این گره ها را به طور مستقل مقیاس کنیم.
یک صفحه کنترل گره های محاسباتی موجود و سالم را ردیابی می کند و گره های لبه آن را برای آن لیست نظرسنجی می کنند. همچنین این همان چیزی است که استقرار را هدایت می کند - یک ناوگان جدید در کنار ناوگان در حال اجرا ظاهر می شود، متناسب با آن مقیاس می شود و تنها زمانی که سالم باشد، ترافیک را به دست می گیرد.
ایجاد زیرساخت محاسباتی مستلزم همکاری نزدیک با تیم Unikraft است. در طول مهاجرت، ما با آنها در آزمایش صحت، رسیدگی به حجم زیادی از درخواستها و ایجاد قابلیتهای خاص پلتفرم خود کار کردهایم.
کار برای بازسازی معماری محاسبات لبه ما چیزی بیش از افزایش سرعت است. این پایه سریعتری است که میتوانیم آن را ادامه دهیم و کنترل بیشتری روی آن داشته باشیم. بهترین بخش این است که امروز به ترافیک تولید شما خدمات می دهد، با همان قیمت، بدون گام مهاجرت و چیزی برای تغییر در هیچ پروژه ای.
اجرای محاسبات توسط خودمان به این معنی است که سقف توابع لبه را باید افزایش دهیم. سه چیز که قبلا نبودند این کار را قابل انجام میکند:
اینجا کارمان تمام نشده است محدودیتها و لبههای ناهمواری که قبلا نمیتوانستیم آنها را لمس کنیم، همانهایی هستند که اکنون روی آن کار میکنیم، پس با ما همراه باشید.
متن اصلی (انگلیسی)
5x faster Edge Functions: V8 isolates to Firecracker MicroVMs
Article URL: https://www.netlify.com/blog/edge-functions-firecracker-microvms/ Comments URL: https://news.ycombinator.com/item?id=49912444 Points: 219 # Comments: 96