WebAssembly بیسروصدا در حال تبدیلشدن به رانتایم پیشفرض محاسبات لبه (edge) است

Cloudflare و Fastly برای جذب مشتریان یکسان با هم رقابت میکنند، پلتفرمهایی ناسازگار با یکدیگر دارند و بهندرت بهطور علنی درباره چیزی به توافق میرسند. با این حال، هر دو شرکت در محصولات محاسبات لبه خود به یک نتیجه رسیدهاند: WebAssembly، نه کانتینرها، رانتایمی است که اجرای واقعاً توزیعشده در سطح جهانی با تأخیر پایین را ممکن میسازد. این همگرایی نه تصادفی است و نه دنبالهروی از یک ترند، بلکه یک مسئله فیزیکی است که کانتینرها در مقیاسی که شبکههای لبه در آن کار میکنند، نمیتوانند حل کنند.
مشکل کُلد استارت که کانتینرها هرگز حل نکردند
یک کانتینر پیش از آنکه کد شما حتی یک دستور را اجرا کند، به هسته سیستمعامل، یک لایه فایلسیستم و تصمیم زمانبند (scheduler) نیاز دارد. حتی رانتایمهای بهینهشده کانتینر، زمان راهاندازی را در حد دهها میلیثانیه اندازه میگیرند. این برای یک دیتاسنتر با ترافیک پایدار به سمت چند منطقه محدود مشکلی ندارد، اما برای شبکهای لبه که میخواهد در هر بار فراخوانی، تابع شما را بهصورت کاملاً سرد در نزدیکترین نقطه از میان بیش از ۳۳۰ نقطه حضور خود راهاندازی کند، مناسب نیست؛ زیرا نگهداشتن کانتینرها بهصورت گرم در هر موقعیت لبه برای هر مشتری، از نظر اقتصادی مقیاسپذیر نیست.
WebAssembly این مشکل را کاملاً دور میزند. یک ماژول Wasm قالبی فشرده و ایزولهشده (sandboxed) از بایتکد است که هیچ وابستگی به هسته سیستمعامل ندارد و در همان پردازه میزبان رانتایم اجرا میشود. Fastly Compute که بر پایه Wasmtime ساخته شده، ماژولها را در بازه میکروثانیه، نه میلیثانیه، نمونهسازی میکند. Cloudflare Workers نیز Wasm را در همان معماری ایزوله V8 که پیشتر برای JavaScript استفاده میکرد اجرا میکند، بهطوریکه یک ماژول Wasm و یک تابع JS تضمین یکسانی برای راهاندازی سریع دارند. این تفاوتی هزار برابری در رده تأخیر راهاندازی است، و در لبه، تأخیر راهاندازی صرفاً یک بهینهسازی نیست، بلکه کل ارزش پیشنهادی است.
Component Model کدنویسی چندزبانه در لبه را عملی کرد
تا همین اواخر، بزرگترین ضعف عملی Wasm قابلیت تعامل (interoperability) بود. یک ماژول Wasm کامپایلشده از Rust و ماژولی دیگر از Go نمیتوانستند بهراحتی توابع یکدیگر را فراخوانی کنند یا انواع داده پیچیده به اشتراک بگذارند؛ تیمها مجبور بودند همهچیز را بهصورت دستی از مرز یک آرایه بایت سریالایز کنند، که این موضوع بخش زیادی از جذابیت Wasm را برای تیمهای دارای پایگاهکد چندزبانه از بین میبرد.
WebAssembly Component Model مستقیماً به این مسئله میپردازد. این مدل یک سیستم نوع رابط استاندارد (WIT) تعریف میکند که به ماژولهای کامپایلشده از زبانهای منبع مختلف اجازه میدهد رابطهای تایپشدهای به یکدیگر عرضه کنند؛ رابطهایی ترکیبپذیر، درست مانند کتابخانههای اشتراکی پیش از آنکه ایمیجهای کانتینر این نوع ترکیب را دشوار کنند. دادههای نظرسنجی توسعهدهندگان خود Cloudflare این تغییر را بهطور ملموس نشان میدهد: کامپوننتهای WASM در سال ۲۰۲۳، ۱۲ درصد از استقرارهای Workers را تشکیل میدادند و در جدیدترین آمار به ۳۴ درصد رسیدهاند. این صرفاً نویز پذیرندگان اولیه نیست؛ این نشانه تبدیلشدن یک رانتایم به زیرساخت پیشفرض است.
امروز چه چیزی واقعاً به Wasm کامپایل میشود
Rust همچنان بالغترین گزینه است؛ نبود گاربجکالکتور و خروجی باینری کوچک آن را تقریباً همتراز ایدهآل با محدودیتهای لبه کرده است. Go از طریق TinyGo پشتیبانی قابلاستفاده اما سنگینتری دارد. C و C++ از طریق Emscripten کامپایل میشوند، و دههها کد موجود میتواند با تغییرات نسبتاً کم برای Wasm هدفگذاری شود. Python و JavaScript از طریق مفسرهایی که خودشان به Wasm کامپایل شدهاند اجرا میشوند؛ روشی که کار میکند اما بخشی از مزیت کُلد استارت را از دست میدهد، چون شما یک مفسر را همراه کد خود عرضه میکنید. اگر منطق لبه شما واقعاً به کارایی حساس است -مسیریابی درخواستها، بررسی احراز هویت، بازنویسی هدرها، تبدیل تصاویر- در حال حاضر مسیر Rust به Wasm قویترین ترکیب از بلوغ اکوسیستم و ویژگیهای رانتایم را ارائه میدهد.
جایی که هنوز کم میآورد
مدل ایزولهسازی Wasm به این معناست که دسترسی مستقیم به فایلسیستم و ساکتهای خام باید از مسیر WASI (رابط سیستم WebAssembly) عبور کند، که هنوز در حال باثباتشدن است؛ بنابراین با بالغشدن ویژگیهای WASI Preview 2 و گسترش پشتیبانی از آنها، انتظار تغییراتی در سطح API را داشته باشید. تجربه دیباگ هم همچنان از کانتینرها عقبتر است: ابزارهای stack trace و پروفایلینگ برای Wasm در حال اجرا داخل یک میزبان لبه در حال بهبودند، اما هنوز به بلوغ یک دهه ابزار کانتینری نرسیدهاند. و برای بارهای کاریای که به وضعیت (state) بلندمدت، دسترسی سنگین به GPU یا یکپارچگی عمیق با سیستمعامل نیاز دارند، Wasm در لبه ابزار مناسبی نیست؛ این نوع کارها همچنان جای خود را در یک کانتینر سنتی یا یک VM نزدیکتر به دادههای شما دارند.
واقعاً باید چه کار کرد
اگر در حال ساخت چیزی هستید که در زمان درخواست روی Cloudflare Workers، Fastly Compute یا Vercel Edge Functions اجرا میشود، Wasm را بهعنوان هدف پیشفرض در نظر بگیرید، نه یک آزمایش. برای سرویسهای جدیدی که ذاتاً برای لبه طراحی میشوند، اگر تأخیر برایتان اهمیت دارد، پیش از رفتن سراغ رویکردی صرفاً مبتنی بر JS/TS، یک نمونه اولیه با Rust بسازید؛ چون شکاف زمان راهاندازی در طول میلیونها فراخوانی روی هم انباشته میشود. اگر تیم شما از قبل با چند زبان کار میکند، همین حالا پیگیری ابزارهای WIT مربوط به Component Model را شروع کنید؛ این همان بخشی است که به شما اجازه میدهد دیگر لازم نباشد چسب سریالایز دستی و شکننده بین ماژولهای لبه بنویسید. و اگر بار کاری شما واقعاً به اتصالات پایدار، وضعیت بزرگ در حافظه یا محاسبات GPU نیاز دارد، صرفاً به این دلیل که Wasm ترند است آن را بهزور درون Wasm نریزید؛ این دقیقاً همان دسته از بارهای کاری است که مدل رانتایم لبه هرگز قرار نبوده آن را حل کند.