با معماریهای سنتی فرایند از راه دور یا همان RPC، یک چالش اساسی وجود دارد: تولیدکنندگان و مصرفکنندگان باید از نظر مقیاس و زمان با یکدیگر هماهنگ باشند. اگر تولیدکنندگان شما دادههای بسیار زیادی برای مدیریت توسط مصرفکنندگان ارسال کنند یا اگر مصرفکنندگان یا سرویسهای پاییندستی از دسترس خارج شوند، رویدادها از دست میروند. این مشکل با چندین مصرفکننده که نیاز به پردازش مستقل دادهها دارند، تشدید میشود. برای مثال، یک بکاند تجارت الکترونیک ممکن است هنگامی که تراکنشها تکمیل میشوند، رویدادهایی را ارسال کند که باید توسط یک سیستم تجزیهوتحلیل و یک سرویس تشخیص تقلب خوانده شوند.
ما میتوانیم این مشکل را با جداسازی (decoupling) تولیدکنندگان و مصرفکنندگان خود حل کنیم؛ یعنی قرار دادن یک سرویس در وسط که عمل نوشتن را جذب میکند و در عین حال به خوانندگان مستقل اجازه میدهد با سرعت خودشان به مصرف دادهها بپردازند.
امروز ما کلادفلر K2 (Cloudflare K2) را در بتای عمومی (public beta) راهاندازی میکنیم تا این مشکل را حل کنیم. K2 یک زیرساخت استریم رویداد بادوام روی پلتفرم توسعهدهندگان است. شما رویدادها را به یک استریم K2 ارسال میکنید، که آنها را به عنوان یک لاگ مرتبشده ذخیره میکند. مصرفکنندگان میتوانند آنها را به روشهای مختلفی بخوانند؛ برای مثال با تقسیمکردن خواندنها در بین مجموعهای از مصرفکنندگان، یا تحویل تمام پیامها به همه مصرفکنندگان. این سرویس کاملاً سرورلس است، به مقادیر عظیمی از داده مقیاسپذیر است و از نگهداری بلندمدت پشتیبانی میکند، بنابراین حتی دورههای طولانی خرابی مصرفکننده نیز باعث از دست رفتن دادهها نمیشود.
در زیر کاپوت، K2 یک لاگ پارتیشنبندیشده و بادوام را در بالای ذخیرهسازی ابجکت R2 (R2 object storage) پیادهسازی میکند که به آن اجازه میدهد تا حجم عظیمی از فضای ذخیرهسازی را مقیاسپندی کند.
اگر آماده شروع به کار هستید، میتوانید با دنبالکردن راهنمای اینجا، اولین استریم خود را در چند ثانیه ایجاد کنید.
استریمها در لبه شبکه (Edge)
ما ابتدا K2 را ساختیم چون ما به یک بافر بادوام در لبه شبکه نیاز داشتیم، که در ابتدا به عنوان لایه تزریق برای پایپلاینهای بیسین (Basin Pipelines) عمل کند. پایپلاینها توسط یک موتور پردازش استریم تغذیه میشوند که با مدل مبتنی بر پول (pull-based) کار میکند، به این معنی که سیستم دیگری باید رویدادها را قبل از خواندن، تبدیل و نوشته شدن در R2 ذخیره کند. و از آنجایی که ما متعهد میشویم که هرگز رویدادها را پس از پذیرش در استریم پایپلاین رها نکنیم، آن ذخیرهسازی باید بادوام باشد - به این معنی که نمیتواند دادهها را از دست بدهد - در طول دورههای زمانی بالقوه طولانی.
این جایی است که بیشتر شرکتها آپاچی کافکا (Apache Kafka) را مستقر میکنند. با این حال، پایپلاینها روی لبه شبکه کلادفلر اجرا میشوند که شامل تعداد زیادی سرور در بیش از ۳۳۵ شهر است. معماری منحصربهفرد ما به این معنی است که ما اغلب نمیتوانیم نرمافزارهای سیستم توزیعشده سنتی مانند کافکا را اجرا کنیم و باید در نحوه ساخت و بهرهبرداری از این سیستمها تجدیدنظر کنیم.
بهویژه برای سرویسهای دارای حالت (stateful)، زیرساخت جهانی کلادفلر چالشهایی را ایجاد میکند: ما بخشهای نسبتاً کوچکی از ماشینها را دریافت میکنیم، آن ماشینها نسبتاً موقتی هستند و شبکه اغلب روی اینترنت عمومی است. اما زیرساخت ما چند قدرت فوقالعاده نیز دارد: به کاربران در هر کجای دنیا که باشند نزدیک است و ظرفیت فوقالعادهای برای مقیاس افقی دارد.
در طراحی سیستم بافر بادوام که به K2 تبدیل شد، تصمیم گرفتیم به پلتفرم قدرتمندی که از قبل داریم تکیه کنیم: R2. سیستمهای ذخیرهسازی ابجکت مانند R2 ذخیرهسازی بسیار بادوام (11 9s!) را با APIهای قوی و سازگار ترکیب میکنند. برونسپاری تکرار و اجماع به لایه ذخیرهسازی به ما این امکان را میدهد که لایه اپلیکیشن (در این مورد K2) را بهطور radical سادهتر، ارزانتر و با کارایی بالاتر بسازیم. فایده ثانویه این است که محاسبات و ذخیرهسازی را از هم جدا میکند و این یعنی هر کدام را میتوان به طور مستقل مقیاسپندی کرد. این به ما اجازه میدهد مقادیر زیادی از دادههای تاریخی را با هزینه کم ذخیره کنیم.
چگونه یک لاگ در بالای ذخیرهسازی ابجکت بسازیم؟ یک مشکل فوری این است که R2 - مانند سایر فروشگاههای ابجکت - از اضافه کردن (appends)، که عملیات استاندارد روی یک لاگ است، پشتیبانی نمیکند. در عوض، ما باید فایلها یا قطعات (segments) کاملی را بنویسیم که به اندازه کافی بزرگ باشند تا هزینه نوشتن و خواندن هر کدام را جبران کنند. ما این کار را با جمعآوری اولیه عملیات نوشتن در حافظه (in-memory) روی یک سرویس لبه انجام میدهیم. پس از انتظار برای مدت کوتاه برای رسیدن دادهها، تمام رویدادها را به عنوان یک فایل قطعه مینویسیم. ما با استفاده از عملیات اتمی R2 بدون نیاز به یک سرویس هماهنگی جداگانه، به نظم و آفستهای کاملاً فزاینده میرسیم.
در حالی که ساخت بر روی R2 مزایای زیادی دارد، یک نکته منفی وجود دارد: تاخیرهای تولید بالاتر. نوشتن در حافظه ابجکت کندتر از دیسک محلی است و ما باید قبل از شروع نوشتن منتظر بمانیم تا دسته محلی جمع شود. در نسخه اولیه K2، این امر حدود ۱ ثانیه تاخیر تولید را در صدک ۹۹ زمان پاسخ اضافه میکند.
ما جزئیات بیشتری را در مورد طراحی K2 در یک بررسی فنی عمیق و آینده به اشتراک خواهیم گذاشت.
استریمها، صفها یا پایپلاینها؟
کلادفلر چندین واسط تحویل ناهمزمانی موجود دارد، از جمله صفها (Queues) و پایپلاینهای بیسین (Basin Pipelines). چه زمانی باید به جای این محصولات موجود به سراغ K2 بروید؟
شباهتهای سطحی بین صفها و استریمهای K2 وجود دارد: هر دو رویدادها را دریافت میکنند، آنها را به طور بادوام ذخیره میکنند و به مصرفکنندگان تحویل میدهند. صفها حول محور ردیابی اقلام فردی کار پرهزینه یا زمانبر طراحی شدهاند که باید به صورت ناهمزمان تکمیل شوند. برای مثال، یک اپلیکیشن پردازش تصویر ممکن است درخواست کاربر را برای مدیریت توسط سرویس پردازش تصویر واقعی در صف قرار دهد. آنها از منطق پیچیدهای در دانه یک آیتم کاری خاص، مانند تلاش مجدد، تاخیرها و صفهای ناموفق برای تلاشهای ناموفق پشتیبانی میکنند.
در مقابل، K2 برای انتقال دادههای مقیاس بالا، نگهداری بلندمدت و مصرف فنآوت طراحی شده است. پیامها به صورت دستهای (batches) تولید و مصرف میشوند که امکان پردازش کارآمد را به قیمت تلاش مجدد در سطح پیام فراهم میکند. این دستهبندی همچنین تاخیر تولیدکننده بالاتری را نسبت به صفها ایجاد میکند.
پایپلاینهای بیسین یک سرویس تزریق سرورلس هستند. شما میتوانید رویدادهای JSON پایپلاین خود را ارسال کنید، که میتوانند تبدیل شده و در R2 یا کاتالوگ بیسین نوشته شوند. هنگامی که نتیجه نهایی نوشتن رویدادها در ذخیرهسازی ابجکت یا جداول آیسبرگ است، پایپلاینها را توصیه میکنیم و وقتی کار سفارشی یا نوشتن در مقصدهای دیگر انجام میشود، K2 را توصیه میکنیم.
شروع به کار
استفاده از K2 شامل ایجاد یک استریم در ابتدا است. شما میتوانید استریمهای زیادی در حساب خود برای موارد استفاده مختلف یا انواع رویدادها داشته باشید. استریمها را میتوان از طریق cf، Wrangler، داشبورد یا API ایجاد کرد.
بیایید مثال جمعآوری و پردازش تحلیلهای محصول را بررسی کنیم. ابتدا، یک استریم با cf ایجاد میکنیم:
هنگامی که یک استریم داریم، میتوانیم از طریق یک API HTTP یا Worker binding شروع به تولید در آن کنیم. برای مثال، از یک Worker:
K2 دادهها را به صورت بایت نشان میدهد، بنابراین میتوانید از هر فرمت یا رمزگذاری که برای اپلیکیشن شما منطقی است استفاده کنید.
اکنون که رویدادها را در یک استریم داریم، میتوانیم یک اشتراک (subscription) ایجاد کنیم. اشتراکها کار را بین مصرفکنندگان تقسیم میکنند و امکان موازیسازی خواندن (read parallelism) را فراهم میکنند - مقیاسپندی به چندین خواننده برای مدیریت بار بیشتر از آنچه یک سرور میتواند مدیریت کند.
ما میتوانیم یک اشتراک از طریق API HTTP ایجاد کنیم.
با ایجاد اشتراک، میتوانیم آن را از هر یک از مصرفکنندگان خود نظرسنجی (poll) کنیم:
هنگامی که یک کلاینت تابع consume را فراخوانی میکند، یک اجاره (lease) برای آن دسته خاص از رویدادها به مدت ۵ دقیقه دریافت میکند. کلاینت میتواند یکی از سه کار زیر را انجام دهد:
- تایید (ack) دسته، که آن را به عنوان پردازش شده علامتگذاری میکند و تضمین میکند که دوباره تحویل داده نخواهد شد
- رد (nack) آن، به این معنی که ما در پردازش آن شکست خوردهایم و میخواهیم دوباره تحویل داده شود
- تمدید (extend) اجاره آن، در صورتی که برای تکمیل پردازش به زمان بیشتری نیاز داشته باشد
این یک روش برای مصرف از K2 است: تقسیم کار در میان چندین مصرفکننده به طوری که هر مصرفکننده بخشی از دادهها را دریافت کند. روش دیگر برای خواندن با یک اشتراک جداگانه برای هر مصرفکننده - الگوی pub/sub - است که در این صورت هر مصرفکننده تمام پیامها را میبیند. یا میتوانید بین این دو روش ترکیب کنید و چندین استخر مصرفکننده مستقل داشته باشید.
برای جزئیات کامل در مورد APIها به اسناد K2 مراجعه کنید.
قیمتگذاری و دسترسی
K2 امروز در بتا عمومی برای حسابهای دارای اشتراکهای پرداختی Workers، در این محدودیتها در دسترس است:
- حداکثر ۱۰ گیگابایت فضای ذخیرهسازی استفاده شده
- ۳۰ مگابایت بر ثانیه تولید در هر استریم
اگر به محدودیتهای بالاتری نیاز دارید، لطفاً با تیم در Discord تماس بگیرید یا فرم افزایش محدودیت را پر کنید.
استفاده از K2 در طول دوره بتا صورتحساب نخواهد شد. هنگامی که صورتحساب را شروع میکنیم، ما این قیمتگذاری را پیشبینی میکنیم:
قیمتگذاری | |
دادههای تولید شده | ۰.۰۴ دلار / گیگابایت |
دادههای مصرف شده | ۰.۰۴ دلار / گیگابایت |
دادههای نگهداری شده | ۰.۰۲ دلار / گیگابایت / ماه |
گامهای بعدی
ما یک نقشه راه هیجانانگیز برای K2 در ماههای آینده داریم، از جمله:
- موازیسازی نوشتن بالاتر، تا استریمهای چند گیگابایت بر ثانیه
- کلیدهای پیام و تضمینهای سفارش مبتنی بر کلید
- مصرفکنندگان Worker مبتنی بر پوش (Push-based)
- لایه اکسپرس با تاخیرهای تولید و سرتاسری کمتر
- پشتیبانی قطرهای برای مشتریان آپاچی کافکا
ما مشتاقیم ببینیم چه چیزی روی K2 میسازید! نظرات خود را در Discord کلادفلر به اشتراک بگذارید.
منبع: blog.cloudflare.com
