امروز نسخهٔ open beta قابلیت Local Uploads برای R2 را منتشر کرده‌ایم 🚀. با فعال‌سازی Local Uploads، دادهٔ آبجکت ابتدا نزدیک مشتری نوشته می‌شود و سپس به‌صورت آسنکرون به محلی که bucket در آن قرار دارد کپی می‌شود. داده بلافاصله در دسترس و strongly consistent باقی می‌ماند؛ در نتیجه آپلودها سریع‌تر می‌شوند و تجربهٔ کاربری جهانی‌تر حس می‌شود.

خیلی از اپلیکیشن‌ها نیاز به عملکرد جهانی دارند — مثلاً کاربرانی که از مناطق مختلف رسانه آپلود می‌کنند یا دستگاه‌هایی که لاگ و تلمتری از گوشه‌و‌کنار دنیا ارسال می‌کنند. با این حال داده باید جایی ذخیره شود و زمانی که کلاینت دور از محل bucket است، ترافیک باید تا آنجا برود. R2 یک object storage است که روی شبکهٔ جهانی Cloudflare ساخته شده: از ابتدا داده‌ها را برای خواندن سریع به‌صورت جهانی cache می‌کند، ضمن اینکه strong consistency و صفر هزینهٔ egress را حفظ می‌کند. این رفتار پشت صحنه اتفاق می‌افتد خواه از S3 API، Workers Bindings یا plain HTTP استفاده کنید. حالا با Local Uploads، هم خواندن و هم نوشتن می‌تواند از هر نقطه‌ای سریع باشد ⚡️.

می‌توانید خودتان در یک دمو تغییرات عملکرد را ببینید. اگر آماده‌اید، Local Uploads را در Cloudflare Dashboard در تنظیمات bucket فعال کنید یا با یک دستور سادهٔ Wrangler روی یک bucket موجود فعالش کنید.

npx wrangler r2 bucket local-uploads enable [BUCKET]

نتایج: تا 75% کاهش در مدت‌زمان درخواست‌های آپلود سراسری — در Private beta و بنچمارک‌های مصنوعی ما، زمان تا آخرین بایت (TTLB) برای درخواست‌های آپلود (مثل PutObject, UploadPart) تا 75% کاهش نشان داد زمانی که کلاینت در منطقه‌ای مختلف نسبت به bucket قرار دارد. در این اندازه‌گیری، TTLB از زمان دریافت درخواست آپلود توسط R2 تا بازگشت پاسخ 200 محاسبه شده است.

در تست‌های مصنوعی برای شبیه‌سازی آپلودهای بین‌منطقه‌ای، یک کلاینت در Western North America راه‌اندازی کردیم و یک bucket را با hint موقعیت Asia-Pacific تنظیم کردیم. کلاینت حدود 20 درخواست PutObject در ثانیه برای 30 دقیقه با هر شیء به حجم 5 MB ارسال کرد. مقایسهٔ p50 (میانگین میانه) TTLB نشان داد که بدون Local Uploads TTLB حدود 2s و با Local Uploads حدود 500ms شده است — اختلافی معنی‌دار برای تاخیرهای بین‌منطقه‌ای.

چطور کار می‌کند: مشکل فاصله — برای درک بهتر، نگاهی به معماری R2 بیندازیم. R2 از چند مؤلفه تشکیل شده است: R2 Gateway Worker که در سراسر شبکهٔ Cloudflare از طریق Cloudflare Workers مستقر است و نقطهٔ ورود همهٔ درخواست‌های API برای احراز هویت و روتینگ است؛ Durable Object Metadata Service که یک لایهٔ توزیع‌شده بر پایهٔ Durable Objects برای ذخیره و مدیریت metadata آبجکت‌ها (مثل key، checksum) است؛ و Distributed Storage Infrastructure که داده‌های رمزنگاری‌شده را به‌صورت پایدار نگه می‌دارد.

بدون Local Uploads، روند آپلود به این شکل است: درخواست ابتدا توسط R2 Gateway که نزدیک کاربر است دریافت و احراز هویت می‌شود. در حین استریم داده‌ها از کلاینت، داده رمزنگاری شده و در storage infrastructure در منطقهٔ bucket نوشته می‌شود. وقتی نوشتن کامل شد، Gateway metadata را به Metadata Service منتشر می‌کند و بعد از commit، پاسخ موفقیت را به کلاینت برمی‌گرداند. اگر کلاینت و bucket در مناطق مختلف باشند، همین فاصلهٔ بیشتر باعث نوسان و تأخیر بیشتر در جریان نوشتن داده می‌شود و آپلودها آهسته‌تر یا کمتر قابل اعتماد می‌شوند.

با فعال شدن Local Uploads دو حالت داریم: یا کلاینت و bucket در یک منطقه هستند، یا در مناطق مختلف. در حالت اول، فرایند مانند قبل است و داده‌ها مستقیماً در storage منطقهٔ bucket نوشته می‌شوند. اما در حالت دوم، R2 داده را در storage نزدیک به کلاینت می‌نویسد و هم‌زمان metadata را به منطقهٔ bucket منتشر می‌کند.

نکتهٔ مهم: بعد از نوشتن اولیه، آبجکت بلافاصله قابل دسترسی است و در کل فرایند تکثیر (replication) قابل خواندن باقی می‌ماند — نیازی نیست منتظر تمام شدن کپی پس‌زمینه باشید. 🌍

قابل‌توجه: این قابلیت برای bucketهایی با محدودیت حوزهٔ قضایی (jurisdiction restriction) فعال نیست (مثلاً EU، FedRAMP).

چه زمانی از Local Uploads استفاده کنیم — این ویژگی برای بارکاری‌هایی طراحی شده که تعداد زیادی درخواست آپلود از مناطق جغرافیایی مختلف دریافت می‌کنند. موارد مناسب شامل: کاربران توزیع‌شدهٔ جهانی، نیاز به performance و reliability بالا برای آپلود، یا خواستن بهینه‌سازی write بدون تغییر مکان اصلی bucket.

برای بررسی توزیع جغرافیایی درخواست‌های خواندن و نوشتن، می‌توانید در Cloudflare Dashboard به صفحهٔ Metrics برای bucket R2 خود بروید و نمودار Request Distribution by Region را ببینید.

چطور ساختیمش — در Local Uploads داده ابتدا نزدیک مشتری نوشته می‌شود و سپس به منطقهٔ bucket کپی می‌گردد. ما این کار کپی را یک replication task می‌نامیم. برای پردازش آسنکرون این replication taskها از Cloudflare Queues استفاده کردیم: Queues به ما اجازه می‌دهد نرخ پردازش را کنترل کنیم و امکانات handling خطا مثل retries و dead letter queues را داشته باشیم. R2 replication taskها را برای هر storage region روی چند queue شارد می‌کند.

نشر metadata و زمان‌بندی replication — وقتی metadata یک آبجکت با Local Uploads منتشر می‌شود، سه عملیات به‌صورت اتمیک انجام می‌شود: ذخیرهٔ metadata آبجکت، ایجاد یک pending replica key که نشان می‌دهد چه replicationهایی هنوز نیاز است انجام شود، و ایجاد یک replication task marker بر پایهٔ timestamp که زمان ارسال task به queue را کنترل می‌کند.

pending replica key شامل برنامهٔ کامل replication است: تعداد taskها، منبع خواندن، مقصد نوشتن، حالت و اولویت replication، و اینکه آیا منبع بعد از تکمیل حذف شود یا نه. این ساختار به ما انعطاف می‌دهد تا چطور داده‌ها را منتقل کنیم. مثلاً انتقال داده در فاصله‌های طولانی پرهزینه است؛ به‌جای اجرای همهٔ replicaها به‌صورت موازی (که هزینه و فشار شبکه را بالا می‌برد)، ابتدا یک replica در منطقهٔ هدف ایجاد می‌کنیم و سپس از این کپی محلی برای ایجاد replicaهای دیگر درون همان منطقه استفاده می‌کنیم.

یک فرایند پس‌زمینه دوره‌ای replication task markerها را اسکن می‌کند و آن‌ها را به یکی از queueهای مرتبط با storage destination می‌فرستد. این markerها تحویل حداقل-یک‌بار (at-least-once) به queue را تضمین می‌کنند — اگر enqueue کردن شکست خورد یا فرایند کرش کند، marker باقی می‌ماند و در اسکن بعدی تلاش مجدد خواهد شد. این رویکرد اجازه می‌دهد که ما replicationها را در زمان‌های متفاوت پردازش کنیم و فقط taskهای معتبر را صف‌بندی کنیم.

پردازش آسنکرون: مدل pull — برای consumer صف‌ها، ما مدل pull را انتخاب کردیم: یک سرویس مرکزی polling از queueهای منطقه‌ای taskها را می‌کشد و آن‌ها را به Gateway Worker برای اجرا ارسال می‌کند. روند کلی این‌طور است: سرویس polling از یک regional queue taskها را می‌کشد و آن‌ها را بسته‌بندی می‌کند تا batchهای یکنواخت بر اساس حجم داده ساخته شوند؛ سپس jobها به Gateway Worker فرستاده می‌شود؛ Worker داده را از منبع می‌خواند، به مقصد می‌نویسد و metadata را در Durable Object به‌روزرسانی می‌کند و در صورت نیاز منبع را برای garbage collection علامت‌گذاری می‌کند؛ نهایتاً Worker نتیجه را به poller برمی‌گرداند و poller task را به‌عنوان تکمیل‌شده یا شکست‌خورده ack می‌کند.

مدل pull باعث می‌شود فرایند replication پایدار و کارآمد بماند؛ سرویس می‌تواند براساس سلامت سیستم سرعت پردازش را دینامیک تنظیم کند و تضمین کند که داده‌ها امن و مطمئن بین مناطق منتقل شوند 🔁.

شروع به کار — Local Uploads هم‌اکنون در open beta در دسترس است و فعال‌سازی آن هزینهٔ اضافی ندارد. درخواست‌های آپلود با این ویژگی همان هزینهٔ عملیاتی استاندارد Class A را دارند، همانطور که بدون Local Uploads هم داشتند.

برای فعال‌سازی به Cloudflare Dashboard در تنظیمات bucket بروید و کارت Local Uploads را فعال کنید، یا از Wrangler استفاده کنید:

npx wrangler r2 bucket local-uploads enable [BUCKET]

فعال‌سازی Local Uploads بدون اختلال است: آپلودهای در جریان کامل می‌شوند و ترافیک قطع نخواهد شد. اگر سؤال یا بازخورد دارید، جامعهٔ توسعه‌دهندگان و Discord ما مکان‌های مناسبی برای گفتگو هستند.

Cloudflare’s connectivity cloud از شبکه‌های سازمانی محافظت می‌کند و به مشتریان کمک می‌کند اپلیکیشن‌های Internet-scale را به‌صورت کارآمد بسازند و هر وب‌سایتی را تسریع کنند.