لماذا قد لا يكون AWS S3 و CloudFront الخيار الأمثل لتقديم الأصول الثابتة؟

دقائق القراءة: 9

تُعد AWS بلا شك الرائدة في مجال الحوسبة السحابية، وتكاد لا تخلو أي مقارنة بين مزودي الخدمات السحابية من ذكرها. ورغم أن S3 يُعتبر الحل الأكثر شيوعًا وشعبية لتخزين البيانات في السحابة، إلا أنه قد لا يكون الخيار الأمثل دائمًا لجميع الاحتياجات، خاصةً عندما يتعلق الأمر بتقديم الأصول الثابتة (Static Assets). في هذا المقال، سأوضح الأسباب التي تدفعنا لإعادة التفكير في هذا الاختيار.

أود التنويه بأن الهدف ليس التقليل من شأن AWS أو خدماتها، فمكانتها الريادية في الحوسبة السحابية لا جدال فيها. هذه مجرد ملاحظات وتجارب شخصية من استخدامي لـ CloudFront + S3، بالإضافة إلى بدائل مثل DigitalOcean + Cloudflare، وأدعوكم للنظر في هذه الأفكار بشكل بناء.

فهم آلية عمل CloudFront و S3 في توزيع المحتوى

يُعتبر CloudFront خدمة أخرى من AWS تُستخدم وتُوصى بها غالبًا مع S3 لتوزيع الملفات الرقمية عالميًا. CloudFront هي شبكة توصيل محتوى (CDN) من أمازون، تمتلك خوادم حافة (Edge Servers) منتشرة في جميع أنحاء العالم.

دعنا نشرح آلية عملها: عندما يحاول مستخدم، من الهند على سبيل المثال، تحميل موقعك الإلكتروني الذي يقع خادمه الأصلي في الولايات المتحدة الأمريكية، وكنت تستخدم تطبيقًا أحادي الصفحة (SPA) مثل React أو Angular، فإن صفحة index.html الأولية ستُحمّل من خادمك الأصلي (من الممارسات الجيدة عدم تخزين صفحات HTML مؤقتًا، خاصةً في تطبيقات SSR لتجنب مشاكل التخزين المؤقت).

بعد ذلك، إذا استضفت ملفات JavaScript و CSS الخاصة بك على CloudFront (المدعوم بـ S3)، فإن هذه الطلبات ستُوجّه إلى اسم نطاق من CloudFront، والذي يُحل إلى عنوان IP لخادم أقرب جغرافيًا للمستخدم. في هذا السيناريو، قد يكون الخادم الأقرب هو أحد خوادم AWS في مركز بيانات بمومباي، الهند.

من هذه النقطة، يتولى خادم الحافة هذا مسؤولية تسليم الملف. هنا يمكن أن يحدث أحد أمرين:

  • إصابة ذاكرة التخزين المؤقت (Cache Hit): الملف متاح بالفعل على خادم مومباي (مخزن مؤقتًا)، ويتم إرجاع الملف للمستخدم فورًا.
  • فقدان ذاكرة التخزين المؤقت (Cache Miss): الملف غير موجود على خادم الحافة، ويتعين على الخادم القيام برحلة إلى الخادم الأصلي (S3 bucket في هذه الحالة) لجلب الملف.

حتى في حالة فقدان ذاكرة التخزين المؤقت، فمن المرجح أن يكون الأداء أسرع للمستخدم مقارنةً بعدم استخدام CloudFront. لماذا؟ لأنه عندما يحدث Cache Miss ويحاول خادم الحافة الوصول إلى الخادم الرئيسي، فإنه يستخدم خط اتصال إنترنت من الفئة الأولى (Tier 1) تديره أمازون، وهي شركة أمريكية تبلغ قيمتها تريليونات الدولارات. من المرجح أن تكون لديهم اتصال إنترنت وزمن انتقال أفضل بكثير مما يمكن أن يقدمه مزود خدمة الإنترنت الخاص بك (ISP). بالإضافة إلى ذلك، نظرًا لأنهم ضمن شبكة أمازون العالمية نفسها، يمكنهم إجراء تحسينات ذكية لتوفير المزيد من الوقت.

تبدو هذه الميزات رائعة حتى الآن، فما هي المشكلة إذن؟ دعنا نتعمق في التفاصيل.

تحديات ضغط الأصول (Asset Compression)

يتيح CloudFront تقديم الأصول المضغوطة باستخدام خوارزمية GZIP. ومع ذلك، هناك تقنية ضغط أحدث وأكثر كفاءة تُعرف باسم Brotli، والتي تحظى بدعم معظم المتصفحات الرئيسية. تضغط Brotli بيانات النقل بشكل أكبر، مما يعني توفيرًا في التكاليف وتقليلًا لوقت انتظار المستخدمين (شاشات التحميل البيضاء).

حتى الآن، لا يدعم Amazon CloudFront تسليم الأصول المضغوطة بتقنية Brotli بشكل مباشر. وهذا أمر مفهوم، حيث أن ضغط Brotli أبطأ عند التنفيذ الفوري (on the fly) مقارنةً بـ GZIP الذي يطبقه CloudFront حاليًا.

قد يخطر ببال البعض فكرة ضغط الملفات بأنفسنا وتخزينها على S3 ثم تسليم النسخة المضغوطة. للأسف، الأمر ليس بهذه البساطة، وسرعان ما نجد أنفسنا أمام مشكلة معمارية أعمق.

عادةً ما يبدو عنوان URL لأحد الأصول كالتالي: http://mysite/assets/javascript/file.js.

عندما يُرسل المتصفح طلبًا، فإنه يرسل رأسًا (header) يسمى Accept-Encoding. يمكن لهذا الرأس أن يحتوي على خوارزميات الضغط التي يدعمها المتصفح، مثل gzip، deflate، brotli، وغيرها. يجب على الخادم أن يتصرف بذكاء لتحقيق أقصى قدر من الكفاءة:

  • إذا كان العميل يدعم brotli، يجب دائمًا تسليم الأصل المضغوط بـ brotli.
  • إذا كان العميل يدعم gzip، يجب دائمًا تسليم gzip.
  • بخلاف ذلك، يتم تسليم الملف الأصلي.

يجب أيضًا التأكد من تعيين Content-Encoding الصحيح في نوع الاستجابة (response type) حتى يتمكن المتصفح من التعرف على خوارزمية الضغط.

هذا يعني أنه يجب عليك أولاً إنشاء ثلاثة أشكال مختلفة لكل ملف أصل:

  1. file.js
  2. file.js.br (نسخة brotli)
  3. file.js.gz (نسخة gzip)

ويجب عليك تسليمها بشكل مشروط اعتمادًا على دعم المتصفح. CloudFront هو شبكة توصيل محتوى “غبية” (dumb CDN)؛ فهو ببساطة يربط عنوان URL للطلب بالملف الموجود على خادمك. لا يمكنه إجراء أي تحويلات إلا إذا… اخترت خدمة AWS أخرى: دوال Lambda@Edge.

دور Lambda@Edge في تحسين الضغط

نعلم جميعًا خدمة Lambda من AWS، التي تتيح تشغيل الدوال في السحابة دون القلق بشأن البنية التحتية الأساسية، مع نموذج تسعير يعتمد على عدد الطلبات والوقت المستغرق. خدمة Lambda@Edge هي خدمة مماثلة، ولكنها مصممة خصيصًا للعمل على خوادم الحافة (Edge Servers) ضمن مراكز بيانات CloudFront CDN.

يمكنك من الناحية التقنية تهيئة دالة Lambda@Edge لتعمل كوسيط بين طلب العميل وشبكة CloudFront CDN. تستطيع Lambda فحص الطلب، والاطلاع على رؤوس المحتوى المدعومة (supported content headers)، ثم تعديل عنوان URL بناءً على ذلك وإعادة توجيهه إلى CloudFront “الغبي” الذي سيقوم بعد ذلك بجلب الملف من URL المعدّل.

على سبيل المثال، إذا رأت Lambda أن المتصفح أرسل رأس Accept-Encoding: br، فيمكن استخدام Lambda لتعديل عنوان URL للطلب من /javascript/file.js إلى /javascript/file.js.br دون أن يلاحظ المستخدم هذا التغيير. ستقوم CloudFront بعد ذلك بجلب حمولة أصغر وإرجاع استجابة بترميز Brotli. هذا يبدو كحل رائع ومربح! ولكن أين تكمن المشكلة إذن؟

التكلفة: العقبة الكبرى أمام AWS S3 و CloudFront

كل ما ناقشناه حتى الآن يبدو جذابًا وفعالًا، ولكن عندما تبدأ في التعامل مع أعداد كبيرة من المستخدمين وحجم حركة مرور كبير، ستدرك أن AWS قد لا تكون الخيار الأمثل عندما يتعلق الأمر بتكاليف نقل البيانات. لقد قامت شركة Zoom بالابتعاد عن AWS لنفس السبب.

علاوة على ذلك، مع تطبيق ضغط الأصول، ستتحمل أيضًا تكاليف استدعاءات Lambda@Edge. على الرغم من أن تطبيق Lambda@Edge قد يقلل من تكاليف نقل البيانات الإجمالية (لأنك تسلم ملفات أصغر)، إلا أنه يضيف بندًا جديدًا للتكلفة.

يعتمد تسعير CloudFront بشكل أساسي على نقل البيانات. لا يتم تحصيل رسوم منك عندما يسترد CloudFront البيانات من S3 bucket، بل يتم تحصيل الرسوم عندما يسترد المستخدم البيانات من خوادم الحافة.

تقدير التكلفة: سيناريو حركة مرور عالية (الهند)

لنفترض أن لديك موقعًا إلكترونيًا شائعًا (يستهدف الهند بشكل أساسي) يزوره حوالي 50,000 مستخدم يوميًا. لنفترض أيضًا أنك تجري تغييرات تصميمية أسبوعية (وهو أمر شائع للمنتجات سريعة التطور)، مما يستدعي إبطال ذاكرة التخزين المؤقت للمتصفح و CloudFront. دعنا نفترض كذلك أن المستخدم الواحد يقوم بتنزيل حوالي 10 ميجابايت من الأصول الثابتة (بما في ذلك CSS و JS والصور والخطوط) المستضافة على S3 عبر CloudFront.

لنحسب التكلفة:

  • 50,000 مستخدم هندي
  • 0.17 دولار أمريكي لكل جيجابايت (سعر CloudFront في الهند)
  • 10 ميجابايت لكل مستخدم
  • يسترد كل مستخدم هذه البيانات 4 مرات شهريًا (بسبب مسح ذاكرة التخزين المؤقت أربع مرات، مرة واحدة أسبوعيًا)
التكلفة = 50000 * 0.17 * (10/1024) * 4 = 332 دولار أمريكي

هذه هي تكلفة نقل البيانات فقط! لم يتم احتساب تكلفة تخزين S3 أو تكلفة استضافة الموقع. (ولم يتم تضمين تسعير Lambda لأنه ضئيل نسبيًا: (0.20 * (50,000 * 4))/1,000,000 = 4 سنتات).

تقدير التكلفة: سيناريو حركة مرور منخفضة التكلفة (الولايات المتحدة الأمريكية)

في هذا السيناريو، لنفترض أن الموقع يستهدف حركة مرور من الولايات المتحدة الأمريكية. ستكون المعلمات كالتالي:

  • 50,000 مستخدم أمريكي
  • 0.085 دولار أمريكي لكل جيجابايت (سعر CloudFront في الولايات المتحدة)
  • 3 ميجابايت لكل مستخدم (بافتراض كفاءة أعلى في الضغط)
  • يسترد كل مستخدم هذه البيانات 4 مرات شهريًا
التكلفة = 50000 * 0.085 * (3*4)/1024 = 50 دولار أمريكي

هذه هي أقل تكلفة قد تدفعها عند استخدام CloudFront مع حركة المرور المذكورة (بافتراض أن جميع المستخدمين البالغ عددهم 50,000 هم من الولايات المتحدة فقط). وتذكر أن هذه التكلفة مخصصة فقط لنقل البيانات، ولا تشمل تكاليف الخادم لاستضافة موقعك الإلكتروني.

بدائل أكثر فعالية من حيث التكلفة والأداء

دعنا نفترض الآن أنك تستضيف جميع هذه الأصول الثابتة على خادمك الرئيسي فقط، مع استخدام NGiNX كوكيل عكسي (reverse proxy)، وتشغيله على خادم افتراضي (droplet) من DigitalOcean بتكلفة 60 دولارًا شهريًا.

حجم نقل البيانات الشهري لديك سيكون:

50000 * (10/1024) * 4 = 1952 جيجابايت (حوالي 2 تيرابايت)

توفر DigitalOcean 1 تيرابايت من نقل البيانات مجانًا لكل خادم افتراضي (droplet). بعد ذلك، تبلغ التكلفة 10 دولارات لكل 1 تيرابايت إضافي.

إذن، التكلفة الصافية لتشغيل الخادم بالكامل ستكون 60 دولارًا (للخادم) + 10 دولارات (لـ 1 تيرابايت إضافي) = 70 دولارًا.

صحيح أنك قد تواجه بعض زمن الانتقال (latency) لأنك تستضيف الأصول بنفسك (وسنتطرق إلى حل هذه المشكلة لاحقًا). ومع ذلك، يُعد NGiNX خادم ويب عالي الأداء ويمكن الاعتماد عليه لضمان عدم كونه نقطة اختناق في تسليم الأصول الثابتة.

بهذه الطريقة، تكون قد خفضت تكلفة “نقل الأصول فقط” من 332 دولارًا إلى 70 دولارًا لتشغيل الخادم بأكمله!

نصيحة إضافية لتحسين الأداء والتكلفة

إذا كان تركيزنا على خدمة المستخدمين في الهند، فيمكنك استخدام خادم DigitalOcean موجود في الهند. هذا سيقلل من زمن الانتقال بشكل كبير.

ليس هذا فحسب، بل يمكنك أيضًا اختيار استخدام شبكة Cloudflare CDN، والتي تقدم خدماتها مجانًا في كثير من الحالات. قد لا تحتفظ Cloudflare بملفاتك في CDN إذا كانت كبيرة جدًا أو يتم الوصول إليها بشكل غير متكرر. ولكن بافتراض أن لدينا موقعًا شائعًا جدًا، فمن المرجح أن يكون هذا الخيار فعالًا. وإذا لم يكن كذلك، يمكنك اختيار أي خدمة CDN أخرى، وأضمن لك أنها ستكون أقل تكلفة بكثير من 332 دولارًا شهريًا.

خلاصة موجزة (TL;DR)

إذا كنت تستضيف موقعًا إلكترونيًا بحجم حركة مرور متوسط إلى كبير، مع تحديثات مجدولة بانتظام، فمن الأكثر فعالية من حيث التكلفة استضافة الأصول بنفسك واستخدام شبكات CDN خارجية (أو حتى شبكات CDN مثل DigitalOcean CDN) بدلاً من الاعتماد على S3 و CloudFront، حيث تكون أسعار نقل البيانات مرتفعة للغاية.

الخلاصة التقنية

لقد قمت شخصيًا بتطبيق إعداد CloudFront + AWS S3 على منصة codedamn.com، وهي منصة تعليمية للمطورين. وسرعان ما أدركت أنه على الرغم من أن هذا الإعداد يبدو متطورًا ويضع codedamn في مصاف الشركات الكبرى التي تعتمد على Amazon، إلا أنه لم يكن فعالًا بما فيه الكفاية من حيث التكلفة والأداء في سياق معين.

تُظهر التجربة أن الحلول التي تبدو مثالية على الورق قد لا تكون كذلك دائمًا عند التطبيق العملي، خاصةً مع تزايد حجم حركة المرور والحاجة إلى تحديثات متكررة. إن تقييم تكلفة نقل البيانات، ودعم تقنيات الضغط الحديثة مثل Brotli، والمرونة المعمارية، كلها عوامل حاسمة عند اختيار حل استضافة الأصول الثابتة. قد تكون البدائل التي تعتمد على الاستضافة الذاتية (بواسطة خوادم مثل NGiNX) مع CDN مجاني أو منخفض التكلفة (مثل Cloudflare أو DigitalOcean CDN) أكثر جدوى اقتصاديًا وتوفر تحكمًا أكبر، مع الحفاظ على مستوى عالٍ من الأداء.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *