السحابة

تصميم نظام خلفي لتطبيق توصيل يتوسع على Azure وAWS

آلات حالة الطلبات، الخدمات المبنية على الأحداث، نمط Outbox، واللبنات السحابية التي نستخدمها لإبقاء منصات التوصيل سريعة في ذروة الغداء.

لمنصات التوصيل نمط حركة قاسٍ: لا شيء تقريبًا في الرابعة فجرًا، ثم جدار من الطلبات عند 12:00 و19:00. يجب أن يمتص النظام الخلفي هذه الذروات دون فقدان طلب واحد، وأن يبقي المندوبين والتجار والعملاء متزامنين، وأن يبقى بسيطًا بما يكفي ليشغّله فريق صغير. هذا هو الشكل الذي نستخدمه.

ابدأ بآلة حالة الطلب

كل خلل توصيل صحّحناه يومًا كان في جذره انتقالًا غير مشروع بين الحالات. لذا نجعل الانتقالات صريحة وقابلة لاختبار الوحدات قبل كتابة أي متحكم.

C#
// Order state machine — explicit, testable transitions
public enum OrderStatus { Placed, Accepted, Preparing, ReadyForPickup, PickedUp, Delivered, Cancelled }

static readonly Dictionary<OrderStatus, OrderStatus[]> Allowed = new()
{
    [OrderStatus.Placed]         = new[] { OrderStatus.Accepted, OrderStatus.Cancelled },
    [OrderStatus.Accepted]       = new[] { OrderStatus.Preparing, OrderStatus.Cancelled },
    [OrderStatus.Preparing]      = new[] { OrderStatus.ReadyForPickup },
    [OrderStatus.ReadyForPickup] = new[] { OrderStatus.PickedUp },
    [OrderStatus.PickedUp]       = new[] { OrderStatus.Delivered },
};

public void Transition(OrderStatus next)
{
    if (!Allowed.TryGetValue(Status, out var ok) || !ok.Contains(next))
        throw new InvalidOperationException($"{Status} -> {next} is not allowed");
    Status = next;
    _events.Add(new OrderStatusChanged(Id, next, DateTime.UtcNow));
}

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

نشر الأحداث بموثوقية: نمط Outbox

الكتابة في قاعدة البيانات ثم النشر إلى ناقل الرسائل مشكلة الكتابة المزدوجة الكلاسيكية: إن فشلت الخطوة الثانية فلديك طلب مدفوع لا يوصّله أحد. نمط Outbox التعاملي يحلها بكتابة الحدث في نفس المعاملة مع الطلب.

C#
// Transactional outbox — publish events reliably
await using var tx = await db.Database.BeginTransactionAsync();
db.Orders.Update(order);
db.OutboxMessages.Add(new OutboxMessage("order.status-changed", JsonSerializer.Serialize(evt)));
await db.SaveChangesAsync();
await tx.CommitAsync();
// A background worker (Hangfire / hosted service) drains the outbox to Azure Service Bus or Amazon SQS.

خدمات لا نظام أحادي — لكن ليس كثيرة

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

مطابقة المكونات مع Azure وAWS

الحاجةMicrosoft AzureAmazon Web Services
الحاوياتAzure Kubernetes Service / Container AppsAmazon EKS / ECS Fargate
ناقل الرسائلAzure Service BusAmazon SQS + SNS
قاعدة بيانات علائقيةAzure SQL / Azure Database for MySQLAmazon RDS / Aurora
التخزين المؤقت والمكانيAzure Cache for RedisAmazon ElastiCache
الملفات (إثبات التسليم)Blob StorageAmazon S3
المراقبةApplication InsightsCloudWatch + X-Ray

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

امتصاص ذروة الغداء

  • توسّع حسب عمق الطابور لا المعالج. عمال التوزيع يتوسعون تلقائيًا من عدد الطلبات غير المعيّنة.
  • خزّن الكتالوج مؤقتًا. القوائم تتغير نادرًا وتُقرأ باستمرار؛ Redis بمدد صلاحية قصيرة يزيل 80% من حمل قاعدة البيانات.
  • حدّ معدل طلبات جهاز التاجر. مطعم يحدّث كل ثانية أثناء الازدحام هجوم حجب خدمة ذاتي.
  • سخّن قبل الذروة. توسّع مجدول عند 11:30 و18:30 أرخص من توسّع تفاعلي عند 12:05.

وقت الوصول المباشر والمسارات

تتدفق مواقع المندوبين عبر مجموعات Redis الجغرافية؛ ويأتي وقت الوصول من Google Maps Platform Routes API ويُخزّن مؤقتًا لكل مقطع مسار. نجمّع الاستدعاءات — طلب واحد لعدة مندوبين مرشحين — فتبقى فاتورة الخرائط متوقعة.

نصيحة تشغيلية: أعطِ كل طلب معرّف ارتباط يسافر عبر السجلات والطوابير والإشعارات. حين يتصل عميل، يجد الدعم القصة كاملة في ثوانٍ.

الخلاصة

حالة صريحة، أحداث موثوقة، حفنة من الخدمات محددة الحدود، وتوسّع مقود بالطوابير: هذه وصفة كل منصة توصيل سلّمناها. مزود السحابة أقل أهمية من الانضباط.

IG
كتبه فريق الهندسة في بوابة عشتار

يكتب مهندسونا عمّا يبنونه كل يوم — الأنظمة الفورية، تطبيقات الهواتف، المنصات السحابية، والمفاضلات التي تقف خلفها. هل لديك سؤال عن مشروعك؟ يسعدنا الحديث معك.

جميع المقالات

لديك فكرة؟ لنبنِها معًا.

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

راسلناinfo@ishtar-gate.com مانشستر، المملكة المتحدة+44 7503 321169 بغداد، العراق+964 770 677 1307