كانت فواتيرنا تحرق ميزانيتنا: كيف أنقذتنا الحوسبة بلا خوادم (Serverless) من جحيم الخوادم الخاملة؟

الفاتورة التي كادت أن “تجلطنا”: قصة من أرض الواقع

قبل كم سنة، كنت أنا وشريكي، شب حريقة ومتحمس، شغالين على تطبيق جديد. الفكرة كانت بسيطة لكن قوية: أداة بتستخدم الذكاء الاصطناعي لتحسين جودة صور المنتجات للمتاجر الإلكترونية الصغيرة. قضينا شهور طويلة نسهر الليالي ونحن نكتب الكود ونبني النموذج، وكان الحماس عنّا “للسما”.

أطلقنا النسخة التجريبية، وعملنا شوية تسويق. فجأة، وبدون سابق إنذار، “انفجر” الوضع! مقال واحد كتبه مؤثر تقني مشهور كان كفيل بإرسال آلاف المستخدمين لمنصتنا في ساعات قليلة. الخوادم اللي كنا مستأجرينها (كم من instance على AWS EC2) بدأت “تولول” تحت الضغط. فرحنا جدًا بالاهتمام، وعلى طول قمنا بزيادة سعة الخوادم عشان نستوعب الحمل الهائل.

لكن الفرحة ما اكتملت. بعد يومين، خفّ الضغط بشكل كبير. عادت الأمور لطبيعتها، والمستخدمون الجدد صاروا يجوا بشكل متقطع. المشكلة؟ بقينا ندفع ثمن الخوادم الضخمة اللي جبناها عشان نتحمل “يوم الذروة” هذاك. كانت الخوادم قاعدة معظم اليوم “بت bost” (خاملة)، ما بتعمل إشي تقريبًا، لكن عدّاد الفلوس كان شغال 24 ساعة.

أتذكر جيدًا اليوم الذي وصلت فيه فاتورة AWS الشهرية. فتحت لوحة التحكم، وشفت الرقم. نظرت لشريكي ونظر إليّ، وحكيت له جملة واحدة باللهجة العامية: “هاي الفاتورة رح تجلطنا!”. كانت التكاليف تأكل من ميزانيتنا المحدودة بشكل مرعب. هنا، أدركنا أن طريقتنا في التعامل مع البنية التحتية كانت خاطئة تمامًا، وكان لا بد من إيجاد حل جذري. هذا الحل كان اسمه: الحوسبة بلا خوادم (Serverless).

ما هي الحوسبة بلا خوادم (Serverless)؟ وليش اسمها “مخادع”؟

أول ما تسمع مصطلح “بلا خوادم”، ممكن تفكر إنه ما في سيرفرات بالمرة. هذا الكلام مش دقيق. الاسم شوي مخادع. الخوادم موجودة طبعًا، لكن الفكرة هي أنك أنت كمطور لا تديرها ولا تفكر فيها أبدًا.

تخيل الفرق بين امتلاك سيارة واستخدام سيارة أجرة (أو أوبر).

  • الخوادم التقليدية (امتلاك سيارة): أنت مسؤول عن كل شيء. شراء السيارة (توفير الخادم)، صيانتها الدورية، التأمين، الوقود، تغيير الزيت، وتصليح الأعطال (إدارة نظام التشغيل، التحديثات الأمنية، مراقبة الأداء). سواء استخدمت السيارة أم ركنتها أمام البيت، فأنت تدفع تكاليفها.
  • الحوسبة بلا خوادم (سيارة أجرة): أنت فقط تطلب الخدمة عند الحاجة إليها. تركب السيارة، توصلك لوجهتك، وتدفع فقط مقابل تلك الرحلة. لا تفكر في صيانة السيارة أو وقودها أو مكان ركنها. هذا بالضبط ما تفعله منصات مثل AWS Lambda أو Azure Functions. أنت تكتب الكود (وظيفة/Function)، وهم يتكفلون بتشغيله عند الطلب وتدفع فقط مقابل مدة التشغيل بالمللي ثانية.

إذًا، “بلا خوادم” تعني أنك تحررت من عبء إدارة الخوادم، وليس أنها غير موجودة.

المشكلة الكلاسيكية: جحيم الخوادم الخاملة (The Idle Server Hell)

مشكلتنا التي ذكرتها في البداية هي مشكلة شائعة جدًا، خصوصًا للتطبيقات التي لديها نمط استخدام متقلب (Spiky Traffic). أنت تضطر لتوفير بنية تحتية (Provisioned Capacity) قادرة على التعامل مع أقصى حمل متوقع، ولكن 90% من الوقت، يكون استخدامك الفعلي (Actual Usage) أقل بكثير.

هذه الفجوة بين السعة المتاحة والاستخدام الفعلي هي “مال مهدر”. أنت تدفع مقابل طاقة حاسوبية لا تستخدمها. هذا هو ما أسميه “جحيم الخوادم الخاملة”.

تخيل أنك تدفع فاتورة كهرباء لمنزل ضخم فيه 10 غرف، مع أنك لا تستخدم سوى غرفة واحدة معظم أيام السنة. هذا بالضبط ما كنا نفعله.

كيف أنقذتنا Serverless: نموذج “الدفع حسب الاستخدام”

عندما انتقلنا إلى بنية Serverless، تغيرت المعادلة بالكامل. بدلًا من خادم يعمل 24/7، قمنا بتقسيم منطق تطبيقنا إلى دوال (Functions) صغيرة ومستقلة. على سبيل المثال، دالة لمعالجة الصور، دالة لإرسال إيميل تأكيد، دالة للتحقق من هوية المستخدم، وهكذا.

الجمال هنا يكمن في نموذج التسعير:

  1. لا تدفع شيئًا إذا لم يتم تشغيل الكود الخاص بك. صفر استخدام = صفر تكلفة.
  2. تدفع فقط مقابل عدد مرات تنفيذ الدالة ومدة تنفيذها (محسوبة بالمللي ثانية) وحجم الذاكرة المخصصة لها.

مقارنة بسيطة بالتكاليف (قبل وبعد)

لنأخذ مثالًا رقميًا تقريبيًا لتوضيح الفكرة:

  • قبل (خادم تقليدي – EC2): لنفترض أننا كنا نستخدم خادمًا من نوع t3.medium على AWS، يعمل 24/7. تكلفته الشهرية تقريبًا 30$ (حسب المنطقة والأسعار الحالية). هذه التكلفة ثابتة سواء خدم الخادم 10 طلبات أو 10 ملايين طلب.
  • بعد (بلا خوادم – AWS Lambda): لنفترض أن تطبيقنا يستقبل 2 مليون طلب في الشهر. كل طلب يستغرق 300 مللي ثانية للتنفيذ، وخصصنا له 512 ميجابايت من الذاكرة.
    • معظم مقدمي الخدمات السحابية مثل AWS يقدمون طبقة مجانية سخية (Free Tier). في حالة Lambda، تحصل على مليون طلب مجاني و 400,000 جيجابايت-ثانية من وقت الحوسبة كل شهر.
    • للمليون طلب الإضافية: 1,000,000 * (0.20$/مليون طلب) = 0.20$
    • وقت الحوسبة بعد الطبقة المجانية: سيكون قليلًا جدًا. الحساب التقريبي قد يوصل التكلفة الإجمالية إلى حوالي 5-7$ فقط في الشهر!

لاحظ الفرق! انتقلنا من فاتورة ثابتة ومؤلمة إلى فاتورة متغيرة تتناسب تمامًا مع حجم استخدامنا الفعلي. هذا هو جوهر تحسين التكاليف في السحابة (FinOps).

لنكتب أول دالة Lambda: مثال عملي

الكلام النظري جميل، لكن “الشغل هو اللي بحكي”. خلينا نكتب مثال عملي وبسيط جدًا، وهو سيناريو كلاسيكي ومثالي للحوسبة بلا خوادم.

السيناريو: خدمة تصغير الصور

عندما يقوم مستخدم برفع صورة إلى سلة تخزين (S3 Bucket) معينة، نريد تشغيل دالة Lambda تلقائيًا لإنشاء نسخة مصغرة (thumbnail) من هذه الصورة وحفظها في سلة تخزين أخرى.

كود الدالة (باستخدام Node.js)

هذا مثال لكود الدالة باستخدام Node.js ومكتبة sharp لمعالجة الصور. ستحتاج لتثبيت المكتبات عبر npm install sharp @aws-sdk/client-s3.


// index.mjs
import { S3Client, GetObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3";
import sharp from "sharp";
import { Readable } from "stream";

// تهيئة عميل S3
const s3Client = new S3Client({ region: process.env.AWS_REGION });

// دالة لتحويل stream إلى buffer
const streamToBuffer = (stream) =>
    new Promise((resolve, reject) => {
        const chunks = [];
        stream.on("data", (chunk) => chunks.push(chunk));
        stream.on("error", reject);
        stream.on("end", () => resolve(Buffer.concat(chunks)));
    });


export const handler = async (event) => {
    // استخراج اسم السلة (Bucket) واسم الملف (Key) من الحدث القادم من S3
    const sourceBucket = event.Records[0].s3.bucket.name;
    const sourceKey = decodeURIComponent(event.Records[0].s3.object.key.replace(/+/g, " "));
    
    // اسم السلة الهدف التي سنحفظ فيها الصورة المصغرة
    const destinationBucket = process.env.DESTINATION_BUCKET;
    const destinationKey = `thumbnails/${sourceKey.split('/').pop()}`;

    try {
        // 1. جلب الصورة الأصلية من S3
        console.log(`Fetching image: ${sourceBucket}/${sourceKey}`);
        const getObjectParams = {
            Bucket: sourceBucket,
            Key: sourceKey,
        };
        const getObjectResult = await s3Client.send(new GetObjectCommand(getObjectParams));
        
        // التأكد من أن Body هو stream
        if (!(getObjectResult.Body instanceof Readable)) {
            throw new Error("Failed to get a readable stream from S3.");
        }
        
        const originalImageBuffer = await streamToBuffer(getObjectResult.Body);

        // 2. تصغير الصورة باستخدام مكتبة sharp
        console.log(`Resizing image...`);
        const resizedImageBuffer = await sharp(originalImageBuffer)
            .resize({ width: 200, height: 200, fit: 'cover' })
            .toBuffer();

        // 3. رفع الصورة المصغرة إلى السلة الهدف
        console.log(`Uploading thumbnail to: ${destinationBucket}/${destinationKey}`);
        const putObjectParams = {
            Bucket: destinationBucket,
            Key: destinationKey,
            Body: resizedImageBuffer,
            ContentType: 'image/jpeg', // أو حسب نوع الصورة
        };
        await s3Client.send(new PutObjectCommand(putObjectParams));

        console.log("Success!");
        return {
            statusCode: 200,
            body: JSON.stringify({ message: "Thumbnail created successfully!" }),
        };
    } catch (error) {
        console.error("Error processing image:", error);
        throw error; // سيؤدي هذا إلى إعادة محاولة تنفيذ Lambda إذا تم تكوينها لذلك
    }
};

كيفية النشر (بشكل مبسط)

  1. اكتب الكود واحفظه في ملف (مثل index.mjs).
  2. أنشئ مجلد node_modules بتشغيل npm install.
  3. اضغط المشروع (الكود مع node_modules) في ملف .zip.
  4. من لوحة تحكم AWS، اذهب إلى خدمة Lambda وأنشئ دالة جديدة.
  5. ارفع ملف الـ .zip الخاص بك.
  6. قم بضبط الإعدادات: زد من مهلة التنفيذ (Timeout) إلى 30 ثانية مثلًا، وخصص الذاكرة (512MB مناسبة).
  7. أضف “مُحفّز” (Trigger) للدالة. في حالتنا، سيكون هذا المحفز هو حدث “إنشاء كائن جديد” (Object Created) في سلة S3 المصدر.
  8. لا تنسَ إعطاء الدالة الصلاحيات اللازمة (IAM Role) لقراءة الملفات من السلة المصدر والكتابة في السلة الهدف.

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

نصائح أبو عمر الذهبية للانتقال إلى Serverless

بعد سنوات من العمل مع هذه التقنية، تعلمت بعض الدروس بالطريقة الصعبة. اسمحوا لي أن أشارككم بعض النصائح العملية:

نصيحة 1: فكّر بالأحداث (Think in Events)

الانتقال إلى Serverless هو تحول في طريقة التفكير قبل أن يكون تحولًا تقنيًا. بدلًا من التفكير في عمليات طويلة الأمد (long-running processes)، ابدأ بالتفكير في “أحداث” (events) وردود أفعال قصيرة. ما هو الحدث (رفع صورة، طلب HTTP، رسالة في طابور)؟ وما هي الوظيفة الصغيرة التي يجب أن تستجيب لهذا الحدث؟

نصيحة 2: احذر من “البداية الباردة” (Cold Starts)

عندما لا يتم استدعاء دالتك لفترة، تقوم المنصة السحابية “بإطفائها” لتوفير الموارد. عند أول طلب بعد فترة الخمول هذه، تحتاج المنصة إلى بضع مئات من المللي ثانية (أو أكثر) لتحميل الكود وتهيئته. هذا التأخير يسمى “البداية الباردة”.

كيف تخفف من أثرها؟

  • Provisioned Concurrency (AWS): يمكنك أن تدفع مبلغًا صغيرًا لإبقاء عدد معين من نسخ دالتك “دافئة” وجاهزة للاستجابة فورًا. استخدمها للتطبيقات الحساسة للزمن.
  • اختر لغات سريعة البدء: لغات مثل Node.js و Python و Go عادةً ما تكون أسرع في البدء من Java أو .NET.
  • قلل حجم الكود: كلما كان حجم حزمة النشر أصغر، كان وقت البدء أسرع.

نصيحة 3: المراقبة والتسجيل (Monitoring & Logging) ليست رفاهية

في البنية التقليدية، يمكنك الدخول إلى الخادم والتحقق من ملفات السجل. في عالم Serverless، كل شيء موزع. تصبح أدوات مثل Amazon CloudWatch (للسجلات والمقاييس) و AWS X-Ray (لتتبع الطلبات عبر الخدمات) ضرورية للغاية وليست رفاهية. بدونها، “بتصير زي اللي بدور على إبرة بكومة قش… بالليل!”. استثمر الوقت في تعلم كيفية استخدامها بفعالية.

نصيحة 4: ابدأ صغيراً (Start Small)

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

نصيحة 5: استخدم أطر العمل (Use Frameworks)

نشر الدوال وإدارة الصلاحيات والربط بين الخدمات يدويًا عبر لوحة التحكم يصبح معقدًا بسرعة. استخدم أطر عمل مثل Serverless Framework أو AWS SAM (Serverless Application Model). هذه الأدوات تسمح لك بتعريف بنيتك التحتية بالكامل ككود (Infrastructure as Code) في ملف واحد (عادةً YAML)، مما يجعل عملية النشر والتحديث وإعادة الإنتاج سهلة ومنظمة.

الخلاصة: هل Serverless هي الحل السحري لكل شيء؟

بالتأكيد لا. الحوسبة بلا خوادم ليست حلًا سحريًا لكل المشاكل. هي أداة قوية جدًا في صندوق أدواتك كمطور، ولكن لها حالات استخدام مثالية وحالات أخرى قد لا تكون مناسبة لها.

متى تتألق Serverless؟

  • التطبيقات ذات الاستخدام المتقلب أو غير المتوقع.
  • المهام التي تعمل بالخلفية وتستجيب للأحداث (مثل معالجة الصور والفيديوهات، تحليل البيانات).
  • واجهات برمجة التطبيقات (APIs) البسيطة والمتوسطة.
  • مشاريع النماذج الأولية السريعة (Prototyping) حيث تريد التركيز على الكود وليس البنية التحتية.

متى يجب أن تفكر مرتين؟ 🤔

  • التطبيقات التي تتطلب عمليات حسابية طويلة جدًا ومستمرة (قد تكون الخوادم المخصصة أرخص).
  • التطبيقات التي تتطلب تحكمًا دقيقًا جدًا في بيئة نظام التشغيل.
  • إذا كنت قلقًا جدًا من “التقييد بمزود واحد” (Vendor Lock-in).

بالنسبة لنا، كان الانتقال إلى Serverless هو القرار الأفضل الذي اتخذناه. لقد أنقذ ميزانيتنا، وحررنا من صداع إدارة الخوادم، وسمح لنا بالتركيز على ما يهم حقًا: بناء منتج رائع لعملائنا. نصيحتي لك: لا تخف من تجربتها. ابدأ بمشروع جانبي صغير، وانظر بنفسك كيف يمكن لهذه التقنية أن تغير طريقة عملك. 😉

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

التوظيف وبناء الهوية التقنية

كانت سيرتي الذاتية تذهب لسلة المهملات: كيف أنقذني ‘نموذج التأثير الكمي’ من جحيم أنظمة تتبع المتقدمين (ATS)؟

أشارككم قصتي مع أنظمة تتبع المتقدمين (ATS) وكيف كانت تتجاهل سيرتي الذاتية. سأشرح لكم "نموذج التأثير الكمي"، وهو منهجي الخاص الذي ساعدني في تجاوز هذه...

2 مايو، 2026 قراءة المزيد
التوسع والأداء العالي والأحمال

كان فشل خدمة واحدة يجرنا جميعًا للأسفل: كيف أنقذنا نمط ‘قاطع الدائرة’ من جحيم ‘الفشل المتتالي’؟

أشارككم قصة حقيقية من قلب المعركة البرمجية، ليلة كاد فيها فشل خدمة صغيرة أن ينهار نظامنا بالكامل. سنغوص في مفهوم "الفشل المتتالي" وكيف كان نمط...

2 مايو، 2026 قراءة المزيد
التكنلوجيا المالية Fintech

دفتر الأستاذ غير القابل للتغيير: كيف أنهينا كابوس تسوية المدفوعات في شركتنا؟

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

2 مايو، 2026 قراءة المزيد
البنية التحتية وإدارة السيرفرات

كانت خوادمنا نسخًا مشوهة: كيف أنقذنا Ansible من جحيم “الانحراف في الإعدادات” (Configuration Drift)؟

أشارككم قصة حقيقية من قلب المعركة التقنية، كيف تحولت خوادمنا إلى فوضى عارمة بسبب "الانحراف في الإعدادات"، وكيف كانت أداة Ansible هي طوق النجاة الذي...

2 مايو، 2026 قراءة المزيد
اختبارات الاداء والجودة

كانت تحديثات CSS تكسر تصميمنا بصمت: كيف أنقذنا ‘الاختبار البصري التراجعي’ من جحيم ‘يبدو مكسورًا’؟

في كل مرة نُحدّث فيها ملف CSS، كنا نخشى من كارثة بصرية غير متوقعة. أشارككم قصة كيف أنقذنا 'الاختبار البصري التراجعي' من ساعات لا نهائية...

2 مايو، 2026 قراءة المزيد
أتمتة العمليات

كانت أوامرنا حبيسة الطرفية (Terminal): كيف حررنا عملياتنا بـ ‘ChatOps’ وجعلناها في متناول الجميع؟

أنا أبو عمر، مبرمج فلسطيني، وأروي لكم كيف انتقلنا من عالم الأوامر المعقدة والمحصورة في الطرفية (Terminal) إلى بيئة عمل شفافة وتعاونية. في هذه المقالة،...

2 مايو، 2026 قراءة المزيد
البودكاست