İçeriğe geç
جميع الخدمات

توسيع نطاق الخلفية

التوسيع ليس إضافة خوادم بل العثور على الاختناق: القياس، وتحسين قاعدة البيانات والاستعلامات، وطبقات التخزين المؤقت، والطوابير، والانتقال القابل للتراجع.

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

الفرق بين توسيع النطاق والأداء والصمود

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

كيف ننظم عمل التوسيع

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

تشخيص الاختناق والقياس

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

تصميم قاعدة البيانات وتحسين الاستعلامات

أول ما ينكسر تحت الحمل هو قاعدة البيانات في الغالب الأعم، والسبب ليس الجهاز عادة. السبب استعلام بلا فهرس، أو استعلامات تتكرر داخل حلقة، أو شاشة قوائم تنمو نتيجتها بلا حد. وإضافة فهرس من دون قراءة خطة الاستعلام تخمين كذلك، فالفهرس الخاطئ يبطئ عمليات الكتابة وينقل المشكلة من مكان إلى آخر. سوق Anneekspres الإلكتروني بني من الصفر على Python وإطار Django فوق قاعدة PostgreSQL، وتعمل التصفية حسب الفئات والبحث وإدارة المخزون والطلبات في لوحة البائع على البنية نفسها. وفي أنظمة الكتالوج التي تغلب عليها التصفية تقع الكلفة في الاستعلام لا في الخادم، ومنصة World Summer Schools تجمع مئات البرامج في كتالوج واحد قابل للبحث بعوامل تصفية حسب العمر والبلد ونوع البرنامج والتاريخ.

طبقات التخزين المؤقت وإبطال الصلاحية

إضافة طبقة تخزين مؤقت سهلة، والصعب هو تقرير ما الذي يجب ألا يدخلها. فالمنظومة التي تعرض بيانات قديمة تكلف أكثر من المنظومة البطيئة، ولذلك يكتب مسبقا عمر كل سجل في الذاكرة المؤقتة والحدث الذي يسقطه. ومنصة Biletico مثال ملموس على ذلك: استلمت المنصة وأعيد بناء الواجهة وتخطيط المقاعد ومسار الدفع، وفي جانب البنية التقنية وضع التخزين المؤقت على Redis فوق حزمة تجمع Next.js مع Node.js، وحفظت البيانات في قاعدة MongoDB الوثائقية. وفي المنصة نفسها يمكن أن يعكس تخطيط المقاعد المبني على Canvas أي لوحة رسم تفاعلية حالة الإشغال لحظة بلحظة. وعندنا يحسم نطاق التخزين المؤقت وما يبقى خارجه بوصفه قرارا مكتوبا. وقد دخلت بنى التخزين المؤقت أيضا في عمل الأداء لدى Welldone وTegoly من المشاريع نفسها.

الطوابير والمعالجة غير المتزامنة القائمة على الأحداث

يجب ألا ينفذ طلب المستخدم إلا العمل الذي ينتظره المستخدم. أما إصدار الفواتير وإرسال الإشعارات وحساب التقارير ومناداة الخدمات الخارجية فليست من ذلك العمل. وحين ترفع من مسار الطلب وتوضع في طابور ينخفض زمن الاستجابة، ويبقى مسار الطلبات حيا حين تسقط خدمة طرف ثالث. في بنية Anneekspres بني طابور الرسائل على RabbitMQ، وتذكر صفحة المشروع أن المنظومة تعمل بفضل هذه البنية من دون انقطاع تحت حركة مرور عالية. ومنصة Lextum AI بنيت على بنية خدمات مصغرة مع معالجة غير متزامنة عبر RabbitMQ، وتصفها صفحة المشروع بأنها جاهزة للاستخدام المؤسسي ذي الحركة العالية. والطابور ليس مجانيا، فضياع الرسالة ومعالجتها مرتين وترتيب وصولها ثلاث حالات منفصلة تعالج كل واحدة منها على حدة.

الانتقال التدريجي من الوحدة الواحدة إلى الخدمات المصغرة

الخدمات المصغرة تعني تقسيم التطبيق القائم في قاعدة شيفرة واحدة، أي الوحدة الواحدة، إلى خدمات صغيرة تتحدث عبر الشبكة؛ وهذا التقسيم كلفة لا غاية بحد ذاته. فبمجرد فصل الخدمات يتحول نداء الدالة إلى نداء عبر الشبكة، ويصعب في وقت واحد تتبع الأخطاء واتساق البيانات وتوافق الإصدارات والمراقبة. ومنصة Lextum AI بنيت ببنية خدمات مصغرة، أي أنها سلمت على هذا النحو ولم تنقل عن وحدة واحدة. وأكثر الأنظمة لا تحتاج إلى ذلك، ويكفيها زمنا طويلا تطبيق واحد ذو وحدات مفصولة بعناية. وحين يلزم التقسيم فعلا فإنه لا يجرى دفعة واحدة: يختار جزء واحد يختلف حمله أو إيقاع إصداره اختلافا بينا عن سائر النظام، ويكتب حده، وينقل جانب القراءة أولا، ولا يتبعه جانب الكتابة إلا بعد قياس عمل القراءة. ولا يشرع في جزء ثان بالتوازي.

اختبار الحمل وتخطيط الطاقة الاستيعابية

يبنى اختبار الحمل حول حدث حقيقي في تقويم عملكم لا حول رقم مدور: دقيقة فتح بيع التذاكر، وانطلاق حملة، وبداية موسم، ويوم صرف الرواتب. ويكتب الهدف قبل الاختبار، وإلا صار في الإمكان تفسير النتيجة لاحقا تفسيرا حسنا من أي زاوية. والمقيس ليس صمود المنظومة فحسب، بل عند أي نقطة تنكسر وبأي عرض تظهر، إذ لا وجود لخطة طاقة من دون معرفة نقطة الانكسار. ففي مشروع Anneekspres وضع شرط منصة قادرة على تحمل حركة مرور عالية منذ بداية العمل. وفي مشروع Togodo أتاحت تحسينات الأداء عملا سلسا تحت حركة مرور عالية. أما البنية التي أنشئت لمنصة World Summer Schools فصممت قابلة للتوسع وجاهزة لنمو أعداد البرامج والمستخدمين.

أين تنكسر الأنظمة في الواقع

نقطة الانكسار نادرا ما تكون طاقة المعالج. وفي الممارسة يخرج الأمر من أحد أربعة مواضع. الأول قاعدة البيانات، إذ يملأ استعلام واحد بلا فهرس مجمع الاتصالات عند ارتفاع الحمل فيوقف المنظومة كلها في الانتظار. والثاني المسار المتزامن، فبقاء عمل لا ينتظره المستخدم داخل مسار الطلب يبطئ نظامكم في اللحظة التي تبطئ فيها خدمة خارجية. والثالث غياب التخزين المؤقت أو بناؤه على وجه خاطئ، والثاني أخطر من الأول لأنه يعرض بيانات غير صحيحة في صمت. والرابع خط الإصدار، فإذا صار النشر إلى بيئة التشغيل حدثا استثنائيا بقيت المشكلة المكتشفة قائمة ساعات أو أياما. وقد بنيت أتمتة التكامل والتسليم المستمرين على Jenkins في مشاريع Anneekspres وBiletico وLextum AI وWelldone وWorld Summer Schools جميعها. وبناء خط الإصدار نفسه عمل مستقل يعالج ضمن خدمة DevOps وCI/CD لدينا.

كلفة التوسيع وأين ينبغي التوقف

كل طبقة تضاف طبقة يلزم تشغيلها. فالتخزين المؤقت يجلب صنفا من أخطاء إبطال الصلاحية، والطابور يجلب حالات ضياع الرسائل وإعادة معالجتها، وتقسيم الخدمات يجلب صنفا من الأعطال يأتي عبر الشبكة. لذلك نكتب إلى جانب كل قرار توسيع رقمين: المكسب المتوقع، وعبء التشغيل الشهري لتلك الطبقة. وتحدد نقطة التوقف سلفا كذلك. نتوقف حين يبلغ القياس هدفه، ونتوقف حين يتبين أن الاختناق حجم أعمال لا مسألة تقنية، ولا ننتقل إلى العلاج الكبير ما دام الأرخص يفي بالغرض. وكثيرا ما يكون فهرس واحد أو تصحيح استعلام واحد أسرع وأدوم من تغيير معماري. والنمو الرأسي، أي جهاز واحد أكبر، قد يخرج أرخص من بنية موزعة، ولا نتحرج من قول ذلك. وإذا لم يكن المنتج قد تحقق من فرضيته بعد فالتوسيع جواب خاطئ، والعمل يعود عندئذ إلى خدمة تطوير المنتج الأولي لدينا.

كيف يجري الانتقال بلا انقطاع

يجرى عمل التوسيع على منظومة حية، ولذلك يلزم أن تكون كل خطوة قابلة للتراجع. والترتيب على هذا النحو. يوضع أولا خط الإصدار والمراقبة، لأن أي تغيير بلا آلية تراجع لا يجرب أصلا. وتنفذ تغييرات المخطط على مرحلتين: يضاف الحقل الجديد، ويعيش الشكلان جنبا إلى جنب مدة، ولا يزال الحقل القديم إلا بعد قياس أنه لم يعد مستعملا. وتنقل مسارات القراءة قبل مسارات الكتابة، لأن الخطأ في جانب القراءة يمكن الرجوع عنه. وتفتح التغييرات خلف راية وتعطى أولا لشريحة صغيرة من حركة المرور. وتكتب خطة التراجع قبل خروج التغيير إلى بيئة التشغيل، ويسمى فيها من يتراجع وعند أي عتبة. وفي مشروع Biletico تشكل البنية التي تتيح اختبار كل تحديث وإطلاقه شرطا مسبقا لهذا الإيقاع، وفي مشروع Anneekspres يشكله الخط الذي يتيح نشرا سريعا.

معايير اختيار التقنية لدينا

الاختيار محصور بأدوات نشغلها في بيئة الإنتاج ويستطيع غيرنا صيانتها بعد التسليم. ففي جانب قاعدة البيانات يبقى التفضيل الافتراضي للخيار العلائقي: تعمل منصات Anneekspres وLextum AI وWorld Summer Schools على PostgreSQL، ويعمل Welldone على MySQL، ويعمل Tegoly على MSSQL، ويجمع Togodo بين MSSQL وPostgreSQL معا. وحيث يكون المخطط متغيرا ننتقل إلى الجانب المستندي، وفي هذه المجموعة يعمل Biletico وTegoly مع قاعدة MongoDB الوثائقية. وفي جانب التطبيق نستعمل Node.js حين يغلب على الحمل الإدخال والإخراج، ونستعمل Python مع Django حين يغلب نموذج البيانات وشاشات الإدارة، ونستعمل .NET حين يكون التكامل المؤسسي وبنية الأدوار هما الحاسمين. وتقوم طبقة التخزين المؤقت على Redis، ويقوم الطابور على RabbitMQ، وتقوم الخوادم على Ubuntu، ويقوم خط الإصدار على أداة Jenkins للتكامل المستمر. وثلاثة معايير هي التي تحسم، وليست الموضة منها: من يتولى الصيانة بعد التسليم، وهل تتوافر في السوق كفاءات في تلك التقنية، وهل يمكن أن تبقى الاستضافة في حسابكم أنتم.

مشاريع شاركت فيها هذه الخدمة

دخلت خدمة توسيع نطاق الخلفية في كل واحد من الأعمال أدناه. وتفصيل كل عمل قائم على صفحته الخاصة في قسم قصص النجاح.

  • Anneekspres: سوق إلكتروني لمنتجات الأم والطفل بني من الصفر، مع طابور رسائل على RabbitMQ وإدارة بيانات على PostgreSQL وخطوط Jenkins، والمنظومة تعمل من دون انقطاع تحت حركة مرور عالية.
  • Lextum AI: إنتاج الوثائق ومراجعة العقود والتحرير المتزامن لفرق القانون، على بنية خدمات مصغرة مع معالجة غير متزامنة عبر RabbitMQ وبنية SaaS مدارة على منصة AWS السحابية.
  • Biletico: منصة تذاكر استلمت فأعملت واجهتها وتخطيط المقاعد المبني على Canvas ومسار الدفع فيها، مع تخزين مؤقت على Redis فوق Next.js وNode.js وبيانات محفوظة في قاعدة MongoDB الوثائقية.
  • Togodo: شاشات جديدة ومراسلة لحظية وإشعارات أضيفت إلى تطبيق فعاليات اجتماعية، وأتاحت تحسينات الأداء عملا سلسا تحت حركة مرور عالية.
  • Welldone: خدمات على .NET وقاعدة MySQL وبنى تخزين مؤقت وبنية خوادم قابلة للتوسع على Ubuntu، أنشئت لعمليات مغسلة صناعية.
  • World Summer Schools: مئات برامج المدارس الصيفية جمعت في كتالوج واحد قابل للبحث، على بنية سحابية فوق Next.js و.NET وPostgreSQL جاهزة لنمو أعداد البرامج والمستخدمين.
  • Tegoly: منصة توقيع رقمي حسنت سرعتها بآليات التخزين المؤقت وبإعدادات خوادم محسنة على Azure، وخفض عمل الأداء أزمنة تحميل الصفحات.
  • Terazzi: منصة في مجال البناء والديكور جرت فيها تحسينات على جانب الخلفية والأداء، وقد رفع ذلك العمل أداء الموقع.

أبرز المزايا

  • القياس أولا: لا يقترح تغيير معماري قبل ظهور صورة الأداء
  • مواضع الاختناق الأربعة: الاستعلام، والخطوة المتزامنة، والتخزين المؤقت، وخط الإصدار
  • خطة الاستعلام وقرار الفهرسة قبل تكبير الخادم
  • تخزين مؤقت على Redis وطابور على RabbitMQ يخرج العمل غير المنتظر من مسار الطلب
  • انتقال تدريجي قابل للتراجع مع خطة تراجع مكتوبة
  • اختبار الحمل يبنى حول حدث عمل حقيقي لا حول رقم مدور

الأسئلة الشائعة

كم يستغرق عمل توسيع نطاق الخلفية وكيف يسعر؟

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

هل يمكنكم تنفيذ ذلك من دون إيقاف المنظومة؟

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

ماذا نسلّم عند انتهاء العمل؟

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

من يتولى الصيانة والمراقبة بعد ذلك؟

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

هل يحتاج كل نظام بطيء إلى توسيع النطاق؟

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

لماذا نمس البنية بدل شراء خادم أكبر؟

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

كيف نقدّم هذه الخدمة

لنتحدث عن مشروعك

كيف يمكننا تطبيق هذه الخدمة على مشروعك؟

املأ نموذج طلب العرض للحصول على استشارة مجانية لمدة 30 دقيقة.