تشغل ألفازيد نظامها الخلفي بالكامل — يخدم أكثر من 95,000 طالب في أكثر من 50 دولة — على AWS Lambda باستخدام إطار العمل الخالي من الخوادم. تشتمل المعمارية على Flask على Lambda خلف بوابة API، MySQL 8 على RDS، S3 لتوصيل المحتوى، وبحيرة تحليلات مخصصة (SQS → Kinesis Firehose → S3 → Glue → Athena). المهايرات النحيفة في Lambda تحسن تأخير بدء التشغيل البارد، ويخدم النظام أكثر من 7 تطبيقات من قاعدة كود واحدة مع تغيير تهيئة وقت التشغيل.
لماذا تستخدم النظام الخالي من الخوادم في تقنيات التعليم؟
تطبيقات التعليم لها أنماط استخدام غير متوقعة:
- صباحات أيام الأسبوع: تحميل ولي الأمر للتطبيق قبل إرسال الطفل إلى المدرسة (زيادة في الحركة)
- بعد الظهر في أيام الأسبوع: جلسات ممارسة بعد المدرسة (تحميل مستمر)
- عطلات نهاية الأسبوع: جلسات مكثفة (2-3 أضعاف الحمل العادي)
- خلال رمضان: انفجار في الاستخدام المسائي (جلسات القرآن العائلية)
- عطلات المدارس: نمط مختلف تمامًا
مزايا النظام الخالي من الخوادم:
- تسعير حسب الطلب: تدفع فقط للاستخدام الفعلي. إذا وصل 10 مستخدمين للـ API، تدفع لتلك الطلبات. إذا وصل 100,000 في لحظة فيروسية، تتوسع فوراً.
- زيرو بدء بارد للنقاط المتواترة: نحن نستخدم طبقات Lambda دائماً دافئة للنقاط التي تُستدعى باستمرار
- التوسع التلقائي: تعامل مع 10 مستخدمين متزامنين أو 10,000 دون أي تغييرات في البنية التحتية
- عدم الحاجة لصيانة الخوادم: يُركز الفريق على المناهج والذكاء الاصطناعي، وليس على Kubernetes أو موازنات التحميل
تحليل معماري معمق
بوابة API → Lambda → RDS
[تطبيق العميل] (iOS، Android، ويب)
↓
[بوابة API] (توجيه HTTP، تحديد معدل)
↓
[مناولات Lambda] (تطبيق Flask، ذاكرة 512MB، زمن انتهاء 28 ثانية)
├── مسارات التطبيق: /app/* (نقاط النهاية المتنقلة)
├── مسارات المستخدم: /user/* (نقاط النهاية المصادق عليها)
└── مسارات الإدارة: /boss/* (لوحة التحكم الإدارية)
↓
[MySQL 8 على RDS] (بيانات دائمة)
↓
[استجابة] (JSON يعود إلى العميل)
Lambdas نحيفة للسرعة
معظم Lambdas نحيفة بوعي:
# مناول نحيف (~100KB)
import json
import pymysql
def get_user_progress(event, context):
user_id = event['pathParameters']['user_id']
# اتصال مباشر بـ DB (بدون overhead ORM)
conn = pymysql.connect(host='rds.aws.com', user='app', password='...', database='amal')
cursor = conn.cursor()
cursor.execute(
'SELECT concept_id, accuracy FROM user_memory WHERE user_id = %s',
(user_id,)
)
rows = cursor.fetchall()
conn.close()
return {
'statusCode': 200,
'body': json.dumps([{'concept': r[0], 'accuracy': r[1]} for r in rows])
}
لا يوجد استيراد لـ Flask، لا ORM SQLAlchemy، ولا middleware. النتيجة: بدء بارد ~500ms مقابل 5-10 ثانية لتطبيق Flask كامل.
نقاط النهاية الثقيلة (توليد المحتوى، معالجة التحليلات) تستخدم Flask كاملة:
# معالج ثقيل (~30MB مع Flask، SQLAlchemy، numpy)
from flask import Flask, jsonify
from models import UserMemory
import numpy as np
app = Flask(name)
@app.route('/content_duo/generate', methods=['POST'])
def generate_content_duo():
# منطق معقد يتطلب ORM
user = UserMemory.query.filter_by(user_id=request.json['user_id']).first()
# ... توليد جلسة مخصصة ...
return jsonify(session_data)
المعادلة: البداية الباردة أبطأ، لكن هذه تُستدعَى بتواتر أقل.
التأشير لكل تطبيق في الجداول
خادم RDS واحد يخدم أكثر من 7 تطبيقات مع عزل على مستوى قاعدة البيانات:
-- تطبيق أمل
CREATE TABLE amal_users (...)
CREATE TABLE amal_content_bytes (...)
CREATE TABLE amal_user_memory (...)
-- تطبيق ثريا
CREATE TABLE thurayya_users (...)
CREATE TABLE thurayya_content_bytes (...)
CREATE TABLE thurayya_user_memory (...)
-- تطبيقات أخرى: qais_, kiDelite_, إلخ.
في وقت النشر، متغير بيئة APP_NAME يختار البادئة:
app_name = os.getenv('APP_NAME', 'amal') # 'amal'، 'thurayya'، 'qais'، إلخ.
الاستعلامات تستخدم البادئة بشكل ديناميكي
table_name = f'{app_name}_users'
cursor.execute(f'SELECT * FROM {table_name} WHERE id = %s', (user_id,))
بحيرة التحليلات
المشكلة: استعلامات قاعدة البيانات المباشرة من أجل التحليلات تبطئ الإنتاج. تشغيل التقارير يغلق الجداول.
الحل: خط تحليلي غير متزامن
[التطبيق المحمول]
↓ (إرسال حدث)
[نقطة API] → [قائمة انتظار SQS] (غير متزامن)
↓ (الاستجابة فوراً للتطبيق)
↓ (لا تنتظر التحليلات)
[Kinesis Firehose] (يكدس الأحداث كل 5 دقائق أو عندما تصل إلى 100MB)
↓
[S3] (مُقسمة: s3://analytics-lake/amal/2026/03/28/events.parquet)
↓
[AWS Glue] (يزحف على S3، يستنتج البنية)
↓
[Athena] (استعلامات SQL عبر محرك Presto)
↓
[لوحة القيادة] (يعرض رؤى في الوقت الحقيقي)
نمط قائمة الانتظار المهملة (DLQ)
إذا فشلت التحليلات:
SQS → [فشل Firehose]
↓
[قائمة الانتظار المهملة تتلقى الرسائل الفاشلة]
↓
[يتم إرسال تنبيه إلى العمليات]
↓
[API الإنتاجية غير متأثرة]
التحليلات لا تعيق الطلبات. يمكن للأطفال التعلم حتى لو كانت خطوط التحليلات متوقفة.
استراتيجيات تحسين التكلفة
الاستراتيجية 1: Lambdas نحيفة للنقاط ذات التردد العالي
- التطبيق الجوال العادي يقوم بـ 10-20 طلب API لكل جلسة
- 95,000 مستخدم نشط × 3 جلسات/يوم × 15 مكالمة/جلسة = 4.275M مكالمة/يوم
- إذا كانت كل مكالمة تكلف $0.0000002 (تسعير Lambda)، فهذا $0.86/يوم
- تقليل وقت البدء البارد بـ 10 ثوانٍ يوفر ~$500/شهر
الاستراتيجية 2: مثيلات RDS محفوظة
- حجز لمدة 3 سنوات: خصم ~60% مقابل عند الطلب
- نستخدم
db.r6i.xlarge(4 vCPU، 32GB RAM): $2,800/شهر محجوز مقابل $6,500/شهر عند الطلب - مدخرات سنوية: ~$50,000
الاستراتيجية 3: التخزين المؤقت
- البيانات التي يُرجع إليها كثيرًا (المناهج التعليمية، البايتات) مخزنة في ElastiCache (Redis)
- يقلل استعلامات RDS بـ 70%
- التكلفة: $800/شهر للتخزين، يوفر $2,000/شهر في RDS
خدمة أكثر من 7 تطبيقات من قاعدة كود واحدة
| التطبيق | البادئة | جدول DB | كدسة Lambda | الحالة |
|---|---|---|---|---|
| أمل | amal_ |
أكثر من 40 جدول | مشتركة | إنتاج |
| ثريا | thurayya_ |
أكثر من 40 جدول | مشتركة | إنتاج |
| قيس | qais_ |
أكثر من 35 جدول | مشتركة | بيتا |
| KidElite | kidelite_ |
أكثر من 40 جدول | مشتركة | إنتاج |
| مدرسة ألفازيد | school_ |
أكثر من 50 جدول | مشتركة | بيتا |
| مونتيسوري ألفازيد | montessori_ |
أكثر من 45 جدول | مشتركة | داخلي |
نظام خلفية واحد، خط نشر واحد، 6 تطبيقات متزامنة. إطلاق تطبيق جديد: أسابيع بدلاً من شهور.
الأسئلة الشائعة
س: ألا يوجد حد زمني أقصى في Lambda يبلغ 15 دقيقة؟
ج: لدى Lambda حد زمني أقصى يبلغ 15 دقيقة، لكن نادراً ما نحتاج إلى طلبات طويلة الأمد. العمليات الثقيلة (توليد المحتوى، التصدير الكبير) تستخدم مهام غير متزامنة مع SQS + وظائف الخطوة.
س: ماذا لو تعطل قاعدة البيانات؟
ج: لدى RDS تجاوز الفشل التلقائي عبر مناطق متعددة (أساسي + نسخة احتياطية). يحدث الفشل التلقائي في حوالي 60 ثانية. يلاحظ العملاء وقت توقف وجيز لكن التعافي سريع.
س: كيف تتعاملون مع تجميع اتصال قاعدة البيانات مع Lambda عديمة الحالة؟
ج: كل مثبت Lambda يحتفظ بمجموعة من الاتصال (تُستخدم عبر الدعوات الدافئة). تبدأ الدعوات الباردة اتصالات جديدة. يجلس RDS Proxy بين Lambda وRDS لإدارة حدود الاتصال.



