آشنایی با AWS Lambda Proactive Initialization

این پست برای اولین بار در وبلاگ من منتشر شد و به اشتراک گذاشته شد توییتر، بنابراین اگر این پست را دوست دارید – لطفا مشترک شوید!
AWS Lambda می تواند عملکردهای شما را گرم کند (به صورت رایگان)
در مارس 2023، AWS مستندات چرخه حیات عملکرد لامبدا را به روز کرد و این بیانیه جدید جالب را شامل شد:
“برای توابعی که از همزمانی رزرو نشده (بر اساس تقاضا) استفاده می کنند، Lambda ممکن است به طور فعال یک نمونه تابع را راه اندازی کند، حتی اگر فراخوانی وجود نداشته باشد.”
در ادامه آمده است:
“وقتی این اتفاق میافتد، میتوانید فاصله زمانی غیرمنتظرهای را بین فازهای اولیه و فراخوانی تابع خود مشاهده کنید. این شکاف میتواند شبیه چیزی باشد که هنگام استفاده از همزمانی ارائه شده مشاهده میکنید.”
این جمله که در اسناد دفن شده است، نشان دهنده چیزی است که به طور گسترده در مورد AWS Lambda شناخته نشده است. که AWS ممکن است عملکردهای شما را گرم کند تا تأثیر و دفعات شروع سرد را کاهش دهد، حتی زمانی که بر اساس درخواست استفاده می شود!
امروز 13 ژوئیه – آنها در این مورد بیشتر توضیح دادند:
“برای توابعی که از همزمانی رزرو نشده (بر اساس تقاضا) استفاده می کنند، لامبدا گاهی اوقات محیط های اجرا را از قبل راه اندازی می کند تا تعداد فراخوانی های شروع سرد را کاهش دهد. به عنوان مثال، لامبدا ممکن است یک محیط اجرای جدید را برای جایگزینی یک محیط اجرایی که در شرف خاموش شدن است مقداردهی اولیه کند. اگر یک محیط اجرای از قبل راهاندازیشده در دسترس باشد، در حالی که Lambda در حال راهاندازی یک محیط اجرای جدید برای پردازش فراخوانی است، Lambda میتواند از محیط اجرای از قبل راهاندازی شده استفاده کند.”
این به روز رسانی تصادفی نیست. در واقع این نتیجه چندین ماه است که من با تیم خدمات AWS Lambda کار کردم:
1 – محیط های اجرا (به بخش “فاز آغاز” مراجعه کنید)، و 2 – شکاف اولیه سازی فراخوانی
در این پست ما تعریف می کنیم که Sandbox Lambda Initialized Proactively Initialized چیست، چه تفاوتی با شروع سرد دارند و تعداد دفعات وقوع آنها را اندازه گیری می کنیم.
ردیابی اولیه سازی فعال
این ماجرا زمانی شروع شد که متوجه شدم که به نظر می رسد یک اشکال در ردیابی توزیع شده باشد. ردیابی به درستی فاز اولیه سازی لامبدا را اندازه گیری کرد، اما به نظر می رسید که اولین فراخوانی را چند دقیقه پس از شروع اولیه نشان می دهد. این می تواند با SnapStart یا Provisioned Concurrency اتفاق بیفتد – اما این تابع از هیچ یک از این قابلیت ها استفاده نمی کرد و در غیر این صورت کاملاً غیرقابل توجه بود.
فلمگراف به این صورت است:
ما میتوانیم یک شکاف بزرگ بین مقداردهی اولیه تابع و فراخوانی ببینیم – در این مورد درخواست فراخوانی حتی تا 12 ثانیه پس از گرم شدن جعبه شنی توسط کلاینت انجام نشده است.
ما همچنین مواردی را مشاهده کردهایم که در آن مقدار اولیه چند دقیقه قبل از اولین فراخوانی اتفاق میافتد، در این مورد فاصله تقریباً 6 دقیقه بود:
پس از بحث زیاد با تیم خدمات AWS Lambda – متوجه شدم که در حال مشاهده یک Sandbox Lambda Initialized Proactively Initialized هستم.
بحث در مورد Initialization فعال در سطح فنی بدون تعریف شروع سرد دشوار است، بنابراین بیایید از آنجا شروع کنیم.
تعریف شروع سرد
AWS Lambda یک شروع سرد را در مستندات به عنوان زمان صرف شده برای دانلود کد برنامه شما و شروع زمان اجرا تعریف می کند.
تا به حال، درک شده بود که شروع سرد برای هر فراخوانی عملکردی که در آن جعبه سند بیکار و اولیه آماده دریافت درخواست وجود ندارد (غایب با استفاده از SnapStart یا Provisioned Concurrency) اتفاق می افتد.
هنگامی که یک فراخوانی تابع شروع سردی را تجربه می کند، کاربران چیزی از 100 میلی ثانیه تا چند ثانیه دیگر تأخیر را تجربه می کنند و توسعه دهندگان یک تاخیر را مشاهده می کنند. Init Duration
در گزارش های CloudWatch برای فراخوان گزارش شده است.
با تعریف شروع سرد، اجازه دهید این را گسترش دهیم تا تعریف اولیه سازی فعال را درک کنیم.
تعریف فنی اولیه سازی فعال
راهاندازی فعال زمانی اتفاق میافتد که یک Sandbox تابع Lambda بدون فراخوانی معلق Lambda مقداردهی اولیه شود.
بهعنوان یک توسعهدهنده، این امر مطلوب است، زیرا هر سندباکس اولیهای فعالانه به معنای شروع سرد کمتری است که در غیر این صورت کاربر تجربه میکند.
به عنوان یک کاربر از برنامه ای که توسط لامبدا پشتیبانی می شود، گویی هرگز شروع سردی وجود نداشته است.
این مانند دریافت همزمانی ارائه شده لامبدا – به صورت رایگان است.
منافع همسو در مدل مسئولیت مشترک
طبق گفته تیم خدمات AWS Lambda، Initialization Proactive نتیجه علایق همسو شده توسط تیمی است که AWS Lambda را اجرا می کند و توسعه دهندگانی که برنامه های کاربردی را روی Lambda اجرا می کنند.
ما می دانیم که از منظر اقتصادی، AWS Lambda می خواهد تا آنجا که ممکن است عملکردهای زیادی را روی یک سرور اجرا کند (بله، بدون سرور سرورهایی دارد…). ما همچنین می دانیم که توسعه دهندگان می خواهند شروع سرماخوردگی آنها تا حد امکان نادر و سریع باشد.
با درک این واقعیت که شروع سرد، زمان ارزشمند CPU را در یک سیستم مشترک و چند مستاجر جذب می کند (زمانی که در حال حاضر صورتحساب ندارد)، واضح است که هر گزینه ای که AWS برای به حداقل رساندن این زمان داشته باشد، برای دو طرف سودمند است.
AWS Lambda یک سرویس توزیع شده است. ناوگان کارگری باید دوباره مستقر شوند، کوچک شوند، بزرگ شوند و به خرابیهای سختافزار اصلی پاسخ دهند. پس از همه – همه چیز همیشه شکست می خورد.
این بدان معناست که حتی با توان عملیاتی حالت پایدار، لامبدا باید جعبههای ماسهای عملکردی را برای کاربران در طی چند ساعت یا روز بچرخاند. AWS حداقل یا حداکثر مدت اجاره را برای جعبه ماسهبازی تابعی منتشر نمیکند، اگرچه در عمل من 7 دقیقه در سمت پایین و چندین ساعت در سمت بالا مشاهده کردهام.
این سرویس همچنین باید به طور مؤثر اجرا شود و تا آنجا که ممکن است عملکردهای زیادی را در یک دستگاه ترکیب کند. در سیستم های توزیع شده، به این نام می گویند bin packing
(معروف به ریختن هر چه بیشتر وسایل در یک سطل).
زمان کمتری صرف مقداردهی اولیه توابع AWS می شود می داند فراخوانی ارائه خواهد کرد، برای همه بهتر است.
زمانی که Lambda به طور فعال عملکرد شما را راه اندازی می کند
در تماسی با تیم خدمات AWS Lambda، آنها برخی از موارد منطقی اولیه سازی فعال – استقرار و تکالیف مشتاق را تأیید کردند.
در نظر بگیرید که ما با تابعی کار می کنیم که در حالت ثابت 100 فراخوانی همزمان را تجربه می کند. وقتی تغییری را در تابع (یا پیکربندی عملکرد) خود اعمال میکنید، AWS میتواند حدس منطقی بزند که پس از اتمام استقرار، به فراخوانی همان تابع 100 بار به طور همزمان ادامه میدهید.
به جای منتظر ماندن برای هر فراخوانی برای شروع سرد، AWS به طور خودکار (تقریباً) 100 جعبه شنی را مجدداً برای جذب آن بار پس از اتمام استقرار فراهم می کند. برخی از کاربران همچنان تمام مدت شروع سرد را تجربه خواهند کرد، اما برخی دیگر این کار را نمی کنند (بسته به مدت زمان درخواست و زمان رسیدن درخواست ها).
این می تواند به طور مشابه زمانی اتفاق بیفتد که Lambda نیاز به چرخش یا عرضه میزبان های Lambda Worker جدید دارد.
اینها بهینه سازی های جدیدی در حوزه سیستم های توزیع شده نیستند، اما این اولین بار است که AWS تأیید می کند که این بهینه سازی ها را انجام می دهد.
اولیه سازی فعال به دلیل تکالیف مشتاق
در موارد خاص، راهاندازی پیشگیرانه نتیجه الگوهای ترافیک طبیعی در برنامه شماست که در آن یک سیستم داخلی به نام AWS Lambda Placement Service درخواستهای در حال انتظار فراخوانی لامبدا را به محض در دسترس شدن به جعبههای ماسهبازی اختصاص میدهد.
در اینجا نحوه کار آن آمده است:
یک تابع Lambda در حال اجرا را در نظر بگیرید که در حال حاضر در حال پردازش یک درخواست است. در این حالت فقط یک جعبه شنی در حال اجراست. هنگامی که یک درخواست جدید عملکرد Lambda را فعال می کند، هواپیمای کنترل لامبدا AWS موجود بودن را بررسی می کند. warm
جعبه های شنی برای اجرای درخواست شما.
اگر هیچ کدام در دسترس نباشد، یک جعبه ماسهبازی جدید توسط صفحه کنترل مقداردهی اولیه میشود:
با این حال ممکن است در این زمان که یک سندباکس گرم درخواستی را تکمیل کرده و آماده دریافت درخواست جدید باشد.
در این صورت، لامبدا درخواست را به جعبه ماسهبازی گرم تازه رایگان اختصاص میدهد.
جعبه شنی جدیدی که ایجاد شد اکنون درخواستی برای ارائه ندارد. همچنان گرم نگه داشته میشود و میتواند درخواستهای جدید را ارائه کند – اما کاربر منتظر گرم شدن جعبه شنی نماند.
این یک مقداردهی اولیه است.
هنگامی که یک درخواست جدید می رسد، می توان آن را بدون تاخیر به این ظرف گرم هدایت کرد!
درخواست B مدتی را در انتظار یک جعبه شنی (اما کمتر از مدت زمان کامل شروع سرد) صرف کرد. این تأخیر در متریک مدت زمان منعکس نمی شود، به همین دلیل است که نظارت بر تأخیر پایان به انتها هر درخواست همزمان از طریق سرویس تماس مهم است! (مانند API Gateway)
تشخیص اولیه سازی های پیشگیرانه
ما می توانیم از این واقعیت استفاده کنیم که توابع AWS Lambda باید در عرض 10 ثانیه مقداردهی اولیه شوند، در غیر این صورت زمان اجرا Lambda دوباره از ابتدا مقداردهی اولیه می شود. با استفاده از این واقعیت، میتوانیم با خیال راحت استنباط کنیم که یک Sandbox لامبدا به طور فعال در زمانی که:
- بیش از 10 ثانیه بین اولین بخش اولیه فراخوانی اولیه تابع پردازش شده و
- ما در حال پردازش اولین فراخوان برای جعبه شنی هستیم.
هر دوی اینها به راحتی آزمایش می شوند، در اینجا کد Node آمده است:
const coldStartSystemTime = new Date()
let functionDidColdStart = true
export async function handler(event, context) {
if (functionDidColdStart) {
const handlerWrappedTime = new Date()
const proactiveInitialization = handlerWrappedTime - coldStartSystemTime > 10000 ? true : false
console.log({proactiveInitialization})
functionDidColdStart = false
}
return {
statusCode: 200,
body: JSON.stringify({success: true})
}
}
و برای پایتون:
import json
import time
init_time = time.time_ns() // 1_000_000
cold_start = True
def hello(event, context):
global cold_start
if cold_start:
now = time.time_ns() // 1_000_000
cold_start = False
proactive_initialization = False
if (now - init_time) > 10_000:
proactive_initialization = True
{% raw %}print(f'{{proactiveInitialization: {proactive_initialization}}}'){% endraw %}
body = {
"message": "Go Serverless v1.0! Your function executed successfully!",
"input": event
}
response = {
"statusCode": 200,
"body": json.dumps(body)
}
return response
فراوانی اولیه سازی های پیشگیرانه
در توان عملیاتی کم، عملاً هیچ مقدار اولیه اولیه برای توابع AWS Lambda وجود ندارد. اما من این تابع را بارها و بارها در یک حلقه بی پایان صدا زدم (به لطف اعتبارات AWS ارائه شده توسط برنامه AWS Community Builder) و متوجه شدم که تقریبا 65% شروع سرد من در واقع مقداردهی اولیه فعال بود و به تأخیر کاربر کمکی نمی کرد.
سوال اینجاست:
fields @timestamp, @message.proactiveInitialization
| filter proactiveInitialization == 0 or proactiveInitialization == 1
| stats count() by proactiveInitialization
در اینجا تفکیک دقیق است، توجه داشته باشید که هر نوار مجموع مقداردهی اولیه را منعکس می کند:
با اجرای این پرس و جو طی چند روز در چندین زمان اجرا و روش های فراخوانی، مشاهده کردم که بین 50٪ تا 75٪ از مقداردهی اولیه، فعال بودند (در مقابل 50٪ تا 25٪ که شروع سرد واقعی بودند):
ما می توانیم این را در مجموع انباشته فراخوان ها برای یک پنجره یک روزه منعکس کنیم. در اینجا یک تابع پایتون با فرکانس بسیار بالا فراخوانی شده است:
ما میتوانیم بعد از یک روز ببینیم، ما 63 جعبه لامبدا اولیه اولیهسازی شده فعال داشتهایم، تنها با 11 شروع سرد. 85٪ از مقداردهی اولیه فعال بودند!
قهرمان بدون سرور AWS کن کالینز یک بسته بسیار محبوب Rails-Lambda را حفظ می کند. پس از مدتی بحث، او قابلیت ردیابی اولیه سازی های پیشگیرانه را اضافه کرد و به نتیجه مشابهی رسید – در مورد او پس از یک آزمایش 3 روزه با استفاده از Ruby با یک زمان اجرا سفارشی، 80 درصد اولیه سازی ها فعال بودند:
تأیید آنچه ما مشکوک بودیم
این پست آنچه را که همه ما حدس می زدیم تأیید می کند اما هرگز با قطعیت نمی دانستیم – AWS Lambda عملکردهای شما را گرم می کند. ما نشان دادهایم که چگونه میتوانید این رفتار را مشاهده کنید، و حتی با تیم خدمات AWS Lambda صحبت کردیم تا برخی از محرکهای این گرم شدن را تأیید کنیم.
اما این سؤال پیش میآید – در مورد راهاندازی فعال AWS Lambda چه باید کرد؟
کارهایی که باید در مورد Initialization فعال انجام دهید
هیچ چی.
این تحقق وعده سرور بدون سرور در یک راه بزرگ است. در حالی که AWS زیرساخت های زیربنایی را بهبود می بخشد، می توانید روی برنامه خود تمرکز کنید. شروع سرد تبدیل به چیزی می شود که توسط ارائه دهنده ابر مدیریت می شود و شما هرگز نباید به آنها فکر کنید.
ما از سرویسهای بدون سرور استفاده میکنیم زیرا حملونقل سنگین غیرمتمایز را به ارائهدهندگان ابری بارگذاری میکنیم. نیازهای مقیاسپذیری خودکار شما و نیازهای مقیاسپذیری خودکار من احتمالاً مشابه نیستند، اما حجم کاری که در مجموع با میلیونها عملکرد در میان هزاران مشتری گرفته میشود، AWS میتواند عملکردها را بهطور پیشبینیکننده مقیاسبندی کند و عملکرد را برای همه افراد درگیر بهبود بخشد.
پیچیدن آن
امیدوارم از اولین نگاه اولیه به Initialization فعال لذت برده باشید و کمی بیشتر در مورد نحوه مشاهده و درک حجم کاری خود در AWS Lambda یاد گرفته باشید. اگر میخواهید معیارها و/یا ردیابیهای APM را برای توابع اولیه اولیه ردیابی کنید، برای هر کسی که از Datadog استفاده میکند در دسترس است.
این همچنین اولین پست من به عنوان یک قهرمان بدون سرور AWS بود. بنابراین اگر این نوع محتوا را دوست دارید لطفاً در وبلاگ من مشترک شوید یا با آن تماس بگیرید توییتر با هر سوالی