سرورلس در مقیاس بزرگ: اجرای اپ‌های آموزش عربی با AWS Lambda
5 دقیقه مطالعهMohammad Shaker

سرورلس در مقیاس بزرگ: اجرای اپ‌های آموزش عربی با AWS Lambda

Alphazed با استفاده از AWS Lambda و معماری سرورلس، بیش از ۹۵ هزار دانش‌آموز را در ۵۰ کشور پوشش می‌دهد و از Flask و MySQL 8 بهره می‌برد.

Engineering

پاسخ سریع

Alphazed با استفاده از AWS Lambda و معماری سرورلس، بیش از ۹۵ هزار دانش‌آموز را در ۵۰ کشور پوشش می‌دهد و از Flask و MySQL 8 بهره می‌برد.

Alphazed کل بخش بک‌اند خود را — که به بیش از ۹۵ هزار دانش‌آموز در بیش از ۵۰ کشور سرویس می‌دهد — روی AWS Lambda با استفاده از Serverless Framework اجرا می‌کند. معماری شامل Flask روی Lambda پشت API Gateway، MySQL 8 روی RDS، S3 برای ارائه محتوا و یک دریاچه تحلیل سفارشی (SQS → Kinesis Firehose → S3 → Glue → Athena) است. هندلرهای کم‌حجم Lambda زمان راه‌اندازی سرد را بهینه می‌کنند و سیستم از یک کدبیس برای بیش از ۷ اپ با پیکربندی پویا در زمان اجرا پشتیبانی می‌کند.

چرا سرورلس برای آموزش فناوری؟

الگوهای استفاده اپ‌های آموزشی پیش‌بینی‌ناپذیر است:

  • صبح‌های روزهای هفته: والدین قبل از فرستادن کودک به مدرسه اپ را دانلود می‌کنند (افزایش ترافیک)
  • بعدازظهر روزهای هفته: جلسات تمرینی پس از مدرسه (بار مداوم)
  • آخر هفته‌ها: جلسات فشرده چند ساعته (۲ تا ۳ برابر بار عادی)
  • ماه رمضان: استفاده در شب‌ها افزایش شدید دارد (جلسات قرآنی خانوادگی)
  • تعطیلات مدرسه: الگوی کاملاً متفاوت

مزایای سرورلس:

  • پرداخت به ازای درخواست: فقط برای استفاده واقعی هزینه می‌کنید. اگر ۱۰ کاربر به API وصل شوند، هزینه ۱۰ فراخوانی است. اگر ۱۰۰,۰۰۰ کاربر در لحظه ویروسی شوند، فوراً مقیاس می‌دهد.
  • آغاز سرد صفر برای نقاط پرتکرار: از لایه‌های Lambda همواره گرم برای نقاط پرتکرار استفاده می‌کنیم
  • مقیاس‌پذیری خودکار: از ۱۰ تا ۱۰,۰۰۰ کاربر همزمان بدون تغییر زیرساخت پاسخگو است
  • نگهداری صفر سرور: تیم روی محتوا و هوش مصنوعی تمرکز دارد، نه کلاسترهای Kubernetes یا توازن بار

بررسی معماری

API Gateway → Lambda → RDS

[برنامه کاربر] (iOS، Android، وب)
    ↓
[API Gateway] (مسیر‌یابی HTTP، محدودیت نرخ درخواست)
    ↓
[هندلرهای Lambda] (اپ Flask، ۵۱۲ مگابایت حافظه، محدودیت ۲۸ ثانیه)
    ├── مسیرهای اپ: /app/* (نقاط پایانی موبایل)
    ├── مسیرهای کاربر: /user/* (نقاط پایانی احراز هویت‌شده)
    └── مسیرهای ادمین: /boss/* (داشبورد مدیریت)
    ↓
[MySQL 8 روی RDS] (داده‌های دائمی)
    ↓
[پاسخ] (JSON به کلاینت)

هندلرهای کم‌حجم برای سرعت

اکثر Lambdaها به عمد کوچک هستند:

# هندلر کم‌حجم (~100کیلوبایت)
import json
import pymysql

def get_user_progress(event, context): user_id = event['pathParameters']['user_id']

# اتصال مستقیم به دیتابیس (بدون سربار 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])
}

بدون import فریم‌ورک Flask، بدون ORM SQLAlchemy و بدون middleware. نتیجه: زمان شروع سرد ~۵۰۰ میلی‌ثانیه در مقابل ۵ تا ۱۰ ثانیه برای اپ کامل Flask.

نقاط سنگین (تولید محتوا، پردازش تحلیل‌ها) از Flask کامل استفاده می‌کنند:

# هندلر سنگین (~۳۰ مگابایت با 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 بیش از ۷ اپ را با جداسازی سطح دیتابیس سرویس می‌دهد:

-- اپ Amal
CREATE TABLE amal_users (...)
CREATE TABLE amal_content_bytes (...)
CREATE TABLE amal_user_memory (...)

-- اپ Thurayya 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] (رویدادها را هر ۵ دقیقه یا ۱۰۰ مگابایت دسته‌بندی می‌کند)
    ↓
[S3] (بخش‌بندی‌شده: s3://analytics-lake/amal/2026/03/28/events.parquet)
    ↓
[AWS Glue] (اسکیمای S3 را پیمایش و استنتاج می‌کند)
    ↓
[Athena] (کوئری SQL با میزبان Presto)
    ↓
[داشبورد] (نمایش نکات لحظه‌ای)

الگوی صف نامه مرده (DLQ)

اگر تحلیل شکست خورد:

SQS → [شکست Firehose]
  ↓
  [DLQ پیام‌های ناموفق را می‌گیرد]
  ↓
  [هشدار به عملیات ارسال می‌شود]
  ↓
  [API تولید بدون تاثیر]

تحلیل هرگز روی درخواست‌های کاربران تاثیر نمی‌گذارد. کودکان حتی اگر پایپلاین تحلیل قطع باشد، می‌توانند ادامه دهند.

استراتژی‌های بهینه‌سازی هزینه

استراتژی ۱: هندلرهای کم‌حجم برای نقاط پرتکرار

  • هر اپ موبایل معمولاً ۱۰-۲۰ درخواست API در هر جلسه ارسال می‌کند
  • ۹۵,۰۰۰ کاربر فعال × ۳ جلسه در روز × ۱۵ درخواست در هر جلسه = ۴.۲۷۵ میلیون درخواست در روز
  • قیمت هر درخواست حدود ۰.۰۰۰۰۰۰۲ دلار است که برابر ۰.۸۶ دلار در روز می‌شود
  • کاهش زمان شروع سرد به اندازه ۱۰ ثانیه صرفه‌جویی ۵۰۰ دلار در ماه دارد

استراتژی ۲: رزرو RDS

  • رزرو سه‌ساله با تخفیف حدود ۶۰٪ نسبت به پرداخت لحظه‌ای
  • از نمونه db.r6i.xlarge با ۴ هسته CPU و ۳۲ گیگابایت رم استفاده می‌کنیم: ماهانه ۲۸۰۰ دلار رزرو در مقابل ۶۵۰۰ دلار پرداخت لحظه‌ای
  • صرفه‌جویی سالانه حدود ۵۰,۰۰۰ دلار

استراتژی ۳: کشینگ

  • داده‌های پرتکرار (برنامه درسی، محتوا) در ElastiCache (Redis) کش می‌شود
  • تقریباً ۷۰٪ کوئری‌های RDS را کاهش می‌دهد
  • هزینه کش ماهانه ۸۰۰ دلار و صرفه‌جویی ۲۰۰۰ دلار در هزینه RDS

ارائه بیش از ۷ اپ از یک کدبیس واحد

اپپیشوندجدول‌های دیتابیسستاپ Lambdaوضعیت
Amalamal_۴۰+ جدولمشترکتولید
Thurayyathurayya_۴۰+ جدولمشترکتولید
Qaisqais_۳۵+ جدولمشترکنسخه بتا
KidElitekidelite_۴۰+ جدولمشترکتولید
Alphazed Schoolschool_۵۰+ جدولمشترکنسخه بتا
Alphazed Montessorimontessori_۴۵+ جدولمشترکداخلی

یک بک‌اند، یک خط لوله استقرار، ۶ اپ همزمان. راه‌اندازی اپ جدید در هفته‌ها به جای ماه‌ها انجام می‌شود.

سؤالات متداول

س: آیا Lambda محدودیت توقف ۱۵ دقیقه‌ای ندارد؟
ج: Lambda حداکثر ۱۵ دقیقه توقف دارد، اما ما به ندرت نیاز به درخواست طولانی داریم. بارهای سنگین (تولید محتوا، خروجی‌های بزرگ) با کارهای غیرهمزمان SQS + Step Functions کار می‌کنند.

س: اگر دیتابیس قطع شود چی؟
ج: RDS دارای Multi-AZ با Failover خودکار (نسخه اصلی + ذخیره) است. تغییر حدود ۶۰ ثانیه طول می‌کشد و کلاینت‌ها فقط تاخیر کوتاه می‌بینند.

س: چگونه با Lambda بدون حالت، اتصال‌های دیتابیس مدیریت می‌شود؟
ج: هر نمونه Lambda استخر اتصال دارد که در فراخوانی‌های گرم دوباره استفاده می‌شود. شروع سرد اتصال تازه می‌گیرد. در بین Lambda و RDS، RDS Proxy محدودیت اتصال را کنترل می‌کند.

اشتراک‌گذاریTwitterLinkedInWhatsApp

مقالات مرتبط