دليلك الشامل للبدء في عالم المعمارية اللامركزية (Serverless) مع AWS Lambda

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

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

كل ما عليك فعله هو تحميل الكود الخاص بك إلى خدمة مزود سحابي، ليقوم هو تلقائيًا بتوفير بيئة تنفيذ مؤقتة. على عكس البنى التقليدية، يمكن للأنظمة اللامركزية التوسع الفوري للتعامل مع آلاف الطلبات في لحظة، وتدفع فقط مقابل مدة تنفيذ الكود الخاص بك.

في هذا المقال، سنقوم ببناء نموذج اتصال بسيط مدعوم بخدمة Lambda اللامركزية من AWS (خدمات الويب من أمازون). ومع ذلك، فإن المعمارية اللامركزية مناسبة لتطبيقات من أي تعقيد أو حجم. على سبيل المثال، قمنا ببناء myCompiler — بيئة تطوير برمجية تدعم 20 لغة — وهي تعمل بشكل كبير بالاعتماد على هذه المعمارية.

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

ستحتاج إلى حساب AWS للمتابعة مع هذا الدليل، ويمكنك التسجيل هنا. سيتم تغطية استخدامنا لخدمات AWS في هذا الدليل بالكامل ضمن الطبقة المجانية (Free Tier).

كيف تعمل خدمة AWS Lambda؟

في هذا القسم، سنتفهم سير العمل مع Lambda وفهمًا موجزًا لكيفية عملها. ومع ذلك، تنطبق هذه المفاهيم على معظم عروض Serverless الأخرى لمزودي الخدمات السحابية.

مع Lambda، تقوم بتحميل الكود الخاص بك إلى AWS، والذي يكون عادةً عبارة عن سكريبت مكتوب بلغة Python أو Node.js أو Ruby. في حالة لغة مثل Go أو Java أو C#، يكون عبارة عن ملف تنفيذي لنظام Linux أو حزمة بتنسيق اللغة (مثل ملفات jar للغة Java). بعد تحميل الكود الخاص بك، يمكنك بعد ذلك "استدعاءه" يدويًا أو استخدام خدمة AWS أخرى لهذا الغرض (سنتناول هذا بالتفصيل بعد قليل).

عندما تستدعي الكود الخاص بك، تنشئ Lambda بيئة Linux آمنة ومؤقتة تسمى "حاوية" (container) على أحد خوادمها، ويتم تغذية أي بيانات مررتها كجزء من الاستدعاء إلى الدالة الخاصة بك. بمجرد اكتمال تنفيذ الدالة، تُعيد خدمة Lambda نتائج الكود إلى الجهة المستدعية. يمكن بعد ذلك إعادة استخدام الحاوية لخدمة تنفيذ آخر، أو إذا لم يتم استدعاء الدالة لفترة طويلة، يتم تدمير الحاوية.

عند إجراء استدعاءات متوازية، تنشئ Lambda حاوية لخدمة كل استدعاء. نظرًا لأن كل استدعاء مخصص لحاوية واحدة، فإن كل استدعاء يحصل على موارد وافرة للتنفيذ. يمكنك تخصيص ما بين 128 ميجابايت إلى 3 جيجابايت من الذاكرة لكل استدعاء، بالإضافة إلى وحدات معالجة مركزية (CPUs) تزداد مع الذاكرة. اجمع هذا مع حقيقة أنها يمكن أن تخدم ما يصل إلى 1000 استدعاء متوازي (يمكن زيادة هذا عن طريق الاتصال بـ AWS)، يمكنك التعامل مع أعباء العمل الثقيلة دون الحاجة للقلق بشأن التوسع.

إذًا، مع التخلص من مخاوف التوسع، ما هي تكلفة تشغيل AWS Lambda؟ يتم قياس استخدام Lambda باستخدام المعايير التالية: عدد الطلبات، الذاكرة المخصصة لها، وعدد المللي ثانية التي تستغرقها دوالك للتشغيل. إذا اخترت أصغر حجم للذاكرة (128 ميجابايت)، واستغرقت دوالك ثانية واحدة للتشغيل عند استدعائها، يمكنك استدعاء دالتك ما يصل إلى مليون مرة مجانًا. بعد ذلك، يمكن أن يكلف كل مليون استدعاء ما يصل إلى 2.30 دولارًا. قد يبدو حجم الذاكرة 128 ميجابايت صغيرًا، لكنه بالتأكيد كافٍ للتعامل مع العديد من أنواع أعباء العمل.

API Gateway: خدمة طلبات HTTP باستخدام Lambda

كما ذكرنا سابقًا، بمجرد تحميل الكود الخاص بك، يجب عليك استدعاؤه يدويًا. لبناء تطبيق ويب، ستحتاج إلى خادم يستمع لطلبات HTTP، ويستدعي دالتك بتفاصيل الطلب، ويترجم البيانات التي تُرجعها دالتك كاستجابة HTTP. لدى AWS خدمة أخرى تتيح لك القيام بذلك بالضبط — API Gateway.

تمامًا مثل Lambda، إنها خدمة أخرى مُدارة من AWS يمكنها التوسع تلقائيًا للتعامل مع أحجام طلبات عالية للغاية. بمجرد إنشاء API Gateway، ستحصل على عنوان URL أساسي يبدو كالتالي:

https://abcdefgh.execute-api.us-east-1.amazonaws.com/

تحت هذا العنوان الأساسي، يمكنك تعيين المسارات وطرق الطلب (مثل GET أو POST) إلى دوالك. لديك أيضًا خيار إنشاء نطاقك المخصص إذا كنت ترغب في استخدام شيء آخر غير الافتراضي، لكننا لن نتناول ذلك في هذا الدليل. أيضًا، تمامًا مثل Lambda، فإن تسعير API Gateway رائع أيضًا — يمكنك خدمة ما يصل إلى مليون طلب مجانًا، وبعد ذلك يكلف كل مليون طلب دولارًا واحدًا.

بناء نموذج اتصال

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

  1. أولاً، سنقوم بإعداد SES (Simple Email Service)، خدمة البريد الإلكتروني من AWS. هذا لمساعدتنا في إرسال رسائل البريد الإلكتروني لنموذج الاتصال.
  2. بعد ذلك، سنقوم بإعداد "دور" (role) لـ Lambda، ثم ننشئ دالة Lambda تتلقى طلب HTTP وترسل لنا بريدًا إلكترونيًا.
  3. سنقوم بإعداد API Gateway وربطه بالدالة التي أنشأناها في الخطوة 2.
  4. سنقوم بعد ذلك بإعداد صفحة ويب تتفاعل مع نقطة نهاية API Gateway وتقدم التفاصيل التي يملأها المستخدم.

في نهاية هذا الدليل، ستقوم بإعداد شيء يعمل بهذا الشكل:

رسم توضيحي لبنية تطبيق لامركزي لنموذج اتصال

للبدء، قم بزيارة وحدة تحكم إدارة AWS (أو ببساطة، "الوحدة") وقم بتسجيل الدخول باستخدام التفاصيل التي استخدمتها للتسجيل. بمجرد تسجيل الدخول، يمكنك استخدام القائمة المنسدلة "الخدمات" (Services) في شريط التنقل للتبديل بين الخدمات المختلفة التي سنستخدمها.

لقطة شاشة لوحدة تحكم إدارة AWS الرئيسية

إعداد SES لإرسال رسائل البريد الإلكتروني

ابدأ بزيارة قسم SES (Simple Email Service) في الوحدة عبر القائمة المنسدلة "الخدمات"، أو باستخدام هذا الرابط المباشر. ثم، انقر على قسم "عناوين البريد الإلكتروني" (Email Addresses) على اليسار. ستُقابل بهذه الصفحة:

صفحة عناوين البريد الإلكتروني في خدمة AWS SES

انقر على زر "التحقق من عنوان بريد إلكتروني جديد" (Verify a New Email Address) ثم أدخل عنوان بريدك الإلكتروني، وانقر على "التحقق من عنوان البريد الإلكتروني هذا" (Verify This Email Address). ستتلقى بريدًا إلكترونيًا يحتوي على رابط تحقق. افتحه للتحقق من العنوان، ثم قم بتحديث صفحة وحدة تحكم SES. سترى أن عنوان البريد الإلكتروني قد تم التحقق منه:

لقطة شاشة لعنوان بريد إلكتروني تم التحقق منه في AWS SES

في هذه المرحلة، ستتمكن من إرسال رسائل بريد إلكتروني لعنوان بريدك الإلكتروني باستخدام SES.

إعداد دور لدالة Lambda

في AWS، تبدأ معظم الكيانات بلا أذونات على الإطلاق للتفاعل مع الموارد أو الخدمات الأخرى في حساب AWS الخاص بك، ما لم تمنحها أذونات صريحة للقيام بذلك. هذا يعني أن دالة Lambda الخاصة بنا لن تتمكن من التحدث إلى خدمات مثل SES لإرسال رسائل البريد الإلكتروني. تستخدم Lambda ما يسمى "دورًا" (role) لتحديد مستوى الوصول الذي تمتلكه للخدمات الأخرى.

لذلك، في هذا القسم، سنقوم بإعداد دور لدالتنا مع إمكانية الوصول إلى SES و CloudWatch. CloudWatch هي خدمة تخزن السجلات والمقاييس، وتستخدمها Lambda لتخزين الأخطاء وسجلات التنفيذ لدوالك.

لإعداد الدور، انتقل إلى قسم IAM (Identity and Access Management) في الوحدة، أو استخدم هذا الرابط المباشر، وانقر على "الأدوار" (Roles) من اليسار. سترى صفحة مثل تلك أدناه:

صفحة الأدوار في خدمة AWS IAM

سنحتاج إلى إنشاء دور جديد، لذا انقر على "إنشاء دور" (Create role). سترى صفحة تحتوي على قائمة بخدمات AWS. بما أننا نقوم بإعداد هذا لـ Lambda، حدد "Lambda" وانقر على زر "التالي: الأذونات" (Next: Permissions).

صفحة اختيار الكيان الموثوق به لإنشاء الدور في AWS IAM

الآن، في صفحة الأذونات، ستحصل على خيار لإرفاق السياسات. أولاً، سنمنح أذونات "SES" — ويمكنك القيام بذلك عن طريق البحث عن "SES" واختيار سياسة "AmazonSESFullAccess".

صفحة إرفاق السياسات لإنشاء الدور في AWS IAM

وبالمثل، يمكنك منح الوصول إلى CloudWatch عن طريق البحث عن "CloudWatchFullAccess" ثم تحديد السياسة التي تظهر:

لقطة شاشة لسياسة CloudWatchFullAccess في AWS IAM

بعد تحديد هذه السياسات، انقر على "التالي: العلامات" (Next: Tags) ثم زر "التالي: المراجعة" (Next: Review). في مربع النص "اسم الدور" (Role name)، أدخل اسم دور من اختيارك، مثل "ContactFormRole". ثم، انقر على زر "إنشاء دور" (Create Role).

صفحة مراجعة وإنشاء الدور في AWS IAM

الآن، لدينا دور جاهز للاستخدام مع دالة Lambda الخاصة بنا.

إنشاء دالة Lambda

في هذه المرحلة، يمكننا إنشاء دالة Lambda التي تتلقى التفاصيل من API Gateway، وترسل لنا بريدًا إلكترونيًا. لإنشاء الدالة، انتقل إلى قسم Lambda في الوحدة، أو استخدم هذا الرابط المباشر. انقر على "الدوال" (Functions) من الجانب الأيسر. في هذه الصفحة، انقر على زر "إنشاء دالة" (Create function).

صفحة إنشاء دالة Lambda جديدة

في صفحة إنشاء الدالة، سيُطلب منك اسم الدالة واللغة التي تريد استخدامها. سنسمي دالتنا "ContactFormFunction"، وسنستخدم Python 3.8 كلغة.

صفحة تكوين اسم الدالة واللغة لدالة Lambda

بعد ذلك، سنقوم بإرفاق الدور الذي أنشأناه في القسم السابق. انقر على "اختيار أو إنشاء دور تنفيذ" (Choose or create an execution role) أسفل قسم "الأذونات" (Permissions)، وحدد "استخدام دور موجود" (Use an existing role) ثم حدد الدور الذي أنشأناه سابقًا، "ContactFormRole". بمجرد إدخال التفاصيل، انقر على زر "إنشاء دالة" (Create function).

صفحة تكوين الأذونات للدالة Lambda

سينقلك هذا إلى صفحة تعرض تفاصيل حول دالتك. قم بالتمرير لأسفل قليلاً حتى تتمكن من رؤية محرر الكود، والذي يبدو كالتالي:

محرر الكود لدالة Lambda في وحدة تحكم AWS

في الجزء الأيمن، الصق الكود التالي وقم بتغيير your_email_address_here إلى عنوان بريدك الإلكتروني.

import boto3
from base64 import b64decode
from urllib.parse import parse_qs

# Replace your email address here
send_to = 'your_email_address_here'

def lambda_handler(event, context):
    # We receive our data through POST requests. API gateway
    # sends the POST data as a Base64 encoded string in
    # event['body'], so we must decode it.
    data = parse_qs(b64decode(event['body']).decode())

    subject = 'You got a message from %s' % data['email'][0]
    text = '\n'.join([
        'Name: %s' % data['name'][0],
        'Email: %s' % data['email'][0],
        'Message %s' % data['message'][0]
    ])

    # Send an email through SES with the SendEmail API
    client = boto3.client('ses', region_name='us-east-1')
    client.send_email(
        Source=send_to,
        Destination={'ToAddresses': [send_to]},
        Message={
            'Subject': {'Data': subject},
            'Body': {'Text': {'Data': text}}
        },
        ReplyToAddresses=[data['email'][0]]
    )

    # This is the response that'll be sent out through the
    # API gateway to the browser.
    return {
        'statusCode': 200,
        'headers': {
            'Access-Control-Allow-Origin': '*'
        },
        'body': '"Success"'  # jquery expects a JSON response
    }

بعد ذلك، انقر على زر "حفظ" (Save) في الجزء العلوي الأيمن لحفظ الكود الخاص بك. بعد الانتهاء من ذلك، سنقوم بإنشاء API Gateway وربطه بدالة Lambda.

التعامل مع طلبات HTTP باستخدام API Gateway

لإضافة API Gateway وربطه بدالتك، قم بالتمرير لأعلى في صفحة دالة Lambda حتى ترى قسم "المصمم" (Designer)، وانقر على زر "إضافة مشغل" (Add Trigger) كما هو موضح أدناه:

زر إضافة مشغل لدالة Lambda في قسم المصمم

سيؤدي هذا إلى فتح صفحة تكوين "المشغل" (Trigger). المشغلات هي ما يمكن أن يستدعي دالة Lambda الخاصة بك، وبما أننا نحتاج إلى API Gateway، اختره من القائمة المنسدلة:

خيارات اختيار المشغل لدالة Lambda

سيؤدي هذا إلى ظهور خيارات مختلفة لإعداد API Gateway. تأكد من أنك قمت بإعداد "API" إلى "إنشاء API جديد" (Create a new API) و "اختيار قالب" (Choose a template) إلى "HTTP API":

خيارات تكوين API Gateway لإنشاء API جديد

قم بالتمرير لأسفل وانقر على دالة "إضافة" (Add) لإعداد API Gateway. يستغرق هذا بضع ثوانٍ ليكتمل، وبمجرد الانتهاء، ستنتقل إلى عرض المصمم. انقر على زر "API Gateway" على اليسار لرؤية عنوان URL الذي يمكنك من خلاله تشغيل دالة Lambda:

عرض المصمم لدالة Lambda مع تفاصيل API Gateway

الآن، قبل أن نبني صفحة نموذج الاتصال، سنختبر أن إعدادنا حتى الآن يعمل بشكل صحيح. إذا كنت تستخدم MacOS أو Linux أو إصدارًا حديثًا من Windows 10، يمكنك نسخ عنوان URL الخاص بـ API Gateway الموضح أعلاه وتشغيل الأمر التالي في محطتك الطرفية. تأكد من استبدال your_api_gateway_url بعنوان URL الفعلي!

curl -i your_api_gateway_url --data-urlencode "name=John" --data-urlencode "email=john@example.com" --data-urlencode "message=hi there"

إذا سار كل شيء على ما يرام، سترى استجابة 200 OK مع رسالة "Success"، كالتالي:

لقطة شاشة لاستجابة أمر curl ناجحة

يجب أن تتلقى أيضًا بريدًا إلكترونيًا في صندوق الوارد الخاص بك بعنوان "You got a message from john@example.com" مع التفاصيل التي تم إدخالها في النموذج. ومع ذلك، قد يكون هذا أحيانًا صعبًا. قد يتم تسليم البريد الإلكتروني في مجلد البريد العشوائي الخاص بك، أو أحيانًا يتم رفضه دون أن تراه على الإطلاق. هذا لأن مزودي الخدمة مثل Gmail و Yahoo يحظرون الأطراف الثالثة (مثل SES) من إرسال رسائل البريد الإلكتروني باستخدام اسم نطاقهم. إذا كان لديك اسم نطاق خاص بك، يمكنك تجاوز ذلك عن طريق إعداد سجل SPF. ومع ذلك، لن نناقش ذلك في هذا الدليل، حيث نريد أن تتمكن من المتابعة حتى بدون نطاق.

بعد ذلك، سنكمل هذا الدليل ببناء صفحة نموذج الاتصال.

بناء صفحة نموذج الاتصال

افتح محرر النصوص المفضل لديك واحفظ الكود التالي كملف HTML. تذكر استبدال your_api_gateway_url بعنوان URL الكامل الذي حصلت عليه سابقًا.

<!DOCTYPE html>
<html>
<head>
    <title>Contact form</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
    <style>
        body {
            margin-top: 20px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h2>Contact form</h2>
        <hr>
        <form id="form">
            <div class="form-group">
                <label for="name">Your name</label>
                <input type="text" class="form-control" id="name" placeholder="Your name">
            </div>
            <div class="form-group">
                <label for="email">Your email address</label>
                <input type="email" class="form-control" id="email" placeholder="Your email address">
            </div>
            <div class="form-group">
                <label for="message">Your message</label>
                <textarea class="form-control" id="message" rows="3"></textarea>
            </div>
            <div id="alert" class="alert d-none"></div>
            <button type="submit" class="btn btn-primary">Submit</button>
        </form>
    </div>

    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <script>
        function showMessage(msg, type) {
            $('#alert').attr('class', `alert alert-${type}`).text(msg)
        }

        function hideMessage(msg) {
            $('#alert').attr('class', 'd-none')
        }

        $('#form').submit(event => {
            event.preventDefault()
            hideMessage()
            let name = $('#name').val().trim()
            let email = $('#email').val().trim()
            let message = $('#message').val().trim()

            if (!(name && email && message)) {
                showMessage('You must fill in all the fields before submitting the form', 'danger')
                return
            }

            $.post('your_api_gateway_url', {name, email, message}).done(_ => {
                showMessage("Thanks for contacting us. We'll be in touch shortly.", 'success')
            }).fail(_ => {
                showMessage('Something went wrong when submiting the message', 'danger')
            })
        })
    </script>
</body>
</html>

بمجرد حفظ الملف، افتحه في متصفحك، املأ التفاصيل وانقر على "إرسال" (Submit). ستتمكن من رؤية رسالة نجاح، كالتالي:

لقطة شاشة لنموذج اتصال ناجح

يؤدي النقر على الزر إلى إرسال التفاصيل كطلب POST إلى API Gateway، والذي يقوم بعد ذلك بتشغيل دالة Lambda، والتي بدورها ترسل لنا بريدًا إلكترونيًا عبر SES. ومع ذلك، كما ناقشنا في القسم السابق ("التعامل مع طلبات HTTP باستخدام API Gateway")، قد لا تتلقى بريدًا إلكترونيًا في ظروف معينة.

الآن بعد أن أصبح لدينا نموذج اتصال ينقل معظم منطقه إلى المعمارية اللامركزية، لديك صفحة الويب الثابتة هذه التي تحتاج إلى استضافتها في مكان ما. فهل تحتاج إلى خادم لاستضافة هذه الصفحة؟ لا على الإطلاق! تقدم AWS خدمة تخزين تسمى S3 (Simple Storage Service)، ويمكنك استخدامها لاستضافة مواقع الويب الثابتة. يتطلب هذا اسم نطاق، لذا إذا كنت تمتلك واحدًا، يمكنك استخدام هذا المقال لاستضافة صفحة الويب.

إلى أين تتجه بعد ذلك؟

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

لحسن الحظ، هناك أدوات مختلفة يمكن أن تساعدك في بناء ونشر تطبيقات Serverless على AWS، مثل Serverless framework أو AWS Chalice. يمكن لـ CloudFormation، وهي خدمة AWS مجانية، أن تساعدك أيضًا في بناء التطبيقات عن طريق أتمتة عملية النشر من خلال قوالب مكتوبة بلغة JSON أو YAML، على الرغم من أنها أصعب قليلاً في الاستخدام من الخيارات الأخرى.

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

تُعد المعمارية اللامركزية (Serverless) وخدمة AWS Lambda نقلة نوعية في عالم تطوير التطبيقات، حيث تحرر المطورين من أعباء إدارة البنية التحتية. يتيح هذا النموذج التركيز الكامل على كتابة الكود وتوفير القيمة للمستخدمين، مع الاستفادة من التوسع التلقائي والمرونة الفائقة وتقليل التكاليف بشكل كبير، حيث يتم الدفع فقط مقابل الاستهلاك الفعلي للموارد. بناء نموذج اتصال بسيط باستخدام Lambda و API Gateway و SES يوضح سهولة البدء وقوة هذه التقنيات في إنشاء حلول فعالة وقابلة للتوسع، مما يفتح آفاقًا واسعة لتطوير تطبيقات معقدة بكفاءة عالية.

اترك تعليقاً

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