التوسّع وموازنة الأحمال
درس 1 من 3
1التوسّع وموازنة الأحمال
الصورة الكبيرةخادم واحد يخدم ألف مستخدم. لمليون تحتاج خوادم كثيرة، وموازنًا يوزّع الطلبات بينها، وطريقة تجعل أي خادم قادرًا على خدمة أي طلب.
ماذا تشاهد في الرسم: التوسع الأفقي: الموازن يوزّع، والخوادم متطابقة ويمكن استبدالها، والحالة تعيش في مكان مشترك واحد.
خارطة هذا الجزء
المفاهيم بالترتيب، اضغط أيًّا منها للقفز إليه:
طريقان إلى نفس الفكرة
مقهى بكاشير واحد يختنق في الذروة. تستطيع أن تحضر كاشيرًا أسرع (توسع عمودي)، لكن للسرعة حد. أو تفتح خمس كاشيرات وموظفًا عند الباب يوجّه كل زبون للأقل زحامًا (توسع أفقي وموازن أحمال). بشرط أن أي كاشير يستطيع أن يخدم أي زبون، أي أن الطلبات مسجلة في نظام مشترك لا في دفتر كل كاشير.
ابدأ بتقدير تقريبي: المستخدمون النشطون يوميًا × الطلبات لكل مستخدم ÷ 86400 = متوسط الطلبات بالثانية، والذروة عادة 2 إلى 10 أضعاف. التوسع العمودي بسيط وله سقف ونقطة فشل واحدة. الأفقي يتطلب خوادم بلا حالة: الجلسات في Redis أو رموز JWT، والملفات في تخزين كائنات (S3)، لا على قرص الخادم. الموازن (L4 على TCP أو L7 على HTTP) بخوارزميات: round robin، أقل اتصالات، موزون، أو تجزئة IP للالتصاق (sticky) حين لا مفر. فحوص الصحة تخرج الخادم المعطل، والتوسع التلقائي يضيف خوادم حسب المعالج أو طول الطابور. والقاعدة غالبًا عنق الزجاجة التالي.
قبل أن تبدأ
🚢النشر
مسار الحاويات والنشر.
📨HTTP
تعرف الطلب والرد.
الفكرة الجوهرية
1قدّر بالأرقام
قبل أي مخطط، احسب. هذه دالة صغيرة تحوّل أرقام العمل إلى طلبات بالثانية وعدد خوادم:
import math
def estimate(daily_users, requests_per_user, peak_factor, rps_per_server):
average = daily_users * requests_per_user / 86_400
peak = average * peak_factor
servers = math.ceil(peak / rps_per_server) + 1 # +1 so one can fail
return round(average), round(peak), servers
for users in (10_000, 1_000_000):
avg, peak, servers = estimate(users, requests_per_user=30, peak_factor=5, rps_per_server=200)
print(f"{users:>9,} users: avg {avg} rps, peak {peak} rps, servers {servers}")2خوارزميات الموازنة
Round robin يوزع بالدور، وأقل اتصالات يختار الأقل انشغالًا، وهو أفضل حين تختلف مدد الطلبات. محاكاة بطلبات بعضها ثقيل:
from itertools import cycle
requests = [5, 1, 1, 5, 1, 1, 5, 1, 1] # seconds of work per request
servers = ["A", "B", "C"]
def round_robin(jobs):
load = dict.fromkeys(servers, 0)
for job, server in zip(jobs, cycle(servers)):
load[server] += job
return load
def least_loaded(jobs):
load = dict.fromkeys(servers, 0)
for job in jobs:
target = min(load, key=load.get)
load[target] += job
return load
print("round robin :", round_robin(requests))
print("least loaded:", least_loaded(requests))3بلا حالة
لو حفظ الخادم A جلسة المستخدم في ذاكرته، ثم أرسل الموازن الطلب التالي إلى B، يجد المستخدم نفسه خارج حسابه. انقل الجلسة لمكان مشترك:
Stateful (breaks when scaled):
server A memory: {session_42: {user: "sara", cart: [...]}}
next request -> server B -> "who are you?"
Stateless (scales):
any server -> Redis: GET session:42 -> {user: "sara", cart: [...]}
uploaded files -> object storage, not local diskمثال محلول
المسألة: تطبيق حجوزات يتوقع 200 ألف مستخدم يوميًا، كل واحد 20 طلبًا، والذروة 6 أضعاف. الحساب: 200,000 × 20 ÷ 86,400 ≈ 46 طلبًا/ث متوسط، و≈ 278 في الذروة. خادم يتحمل 150 طلبًا/ث، فنحتاج 2 + 1 احتياطي = 3. النتيجة: ثلاثة خوادم بلا حالة خلف موازن، لا مئة خدمة مصغّرة.
خرافة مقابل حقيقة
| الخرافة | الحقيقة |
|---|---|
| التوسع يعني إعادة كتابة كل شيء. | غالبًا يكفي جعل الخوادم بلا حالة وإضافة موازن وذاكرة مؤقتة. |
| الجلسات اللاصقة (sticky) تحل المشكلة. | تخفيها: الخادم يتعطل فيفقد مستخدموه جلساتهم، والتوزيع يختل. |
أين تقابله في العمل
🛍️مواسم التخفيضات
إضافة خوادم تلقائيًا في الذروة وإزالتها بعدها.
🌐التوفر العالي
خادم يتعطل والموقع مستمر.
اختبر فهمك
مليون مستخدم يوميًا، 10 طلبات لكل واحد. المتوسط تقريبًا؟
10,000,000 ÷ 86,400 ≈ 116.
لماذا يجب أن تكون الخوادم بلا حالة؟
الحالة في مكان مشترك تجعل الخوادم متطابقة.
الطلبات تختلف كثيرًا في مدتها. أي خوارزمية أفضل؟
يرسل للأقل انشغالًا فلا يتراكم الثقيل على خادم.
بطاقات مراجعة سريعة
تحقق من فهمك
أين تحفظ الجلسات في نظام موسّع؟
في Redis مشترك، أو في رمز موقّع مثل JWT عند العميل.
ما الفرق بين موازن L4 وL7؟
L4 يوزع اتصالات TCP دون قراءتها، وL7 يقرأ HTTP فيوجه حسب المسار والترويسات.
بعد إضافة خوادم، ما عنق الزجاجة التالي غالبًا؟
قاعدة البيانات، وهي موضوع الدرس التالي.
مصادر هذا الدرس
مرتّبة بالنوع. ابدأ بالتوثيق الرسمي إذا تبي المرجع الدقيق، وبالمقال أو الفيديو إذا تبي الشرح أولًا.
خلّصت الدرس؟
سجّل الدخول ليُحفظ تقدّمك.