ما هي أنماط التصميم التي يتم الاستفادة منها الأكثر رافعة في خلق تطبيقات توفر عالية؟ [مغلق

StackOverflow https://stackoverflow.com/questions/814742

سؤال

وبالمثل ، هل هناك أنماط تصميم يجب تجنبها؟

هل كانت مفيدة؟

المحلول

أفترض أنك تكتب تطبيق نوع الخادم (دعنا نترك تطبيقات الويب لفترة من الوقت - هناك بعض حلول الرف التي يمكن أن تساعد هناك ، لذلك دعونا نلقي نظرة على "لقد حصلت على هذا النوع الجديد من الخادم الذي كتبته "، لكني أريد أن يكون مشكلة هكتار).

في تطبيق الخادم ، عادة ما يتم تحويل الطلبات من العملاء (بشكل ما أو آخر) إلى نمط نوع أو نوع أمر ، ثم يتم تنفيذها في قائمة انتظار واحدة أو أكثر.

لذا ، المشكلة الأولى - تحتاج إلى تخزين الأحداث/الأوامر بطريقة ستستمر في المجموعة (أي عندما تتولى عقدة جديدة كسيد ، فإنها تنظر إلى الأمر التالي الذي يحتاج إلى التنفيذ ويبدأ).

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

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

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

بعض هذه القضايا موجودة أيضًا لأنظمة العمال الرئيسية.

تحتاج أيضًا إلى إدارة أخطاء جيدة حيث يزداد عدد الأشياء التي يمكن أن تخطئ في تحديث الحالة (كما تشارك الشبكة الآن).

أستخدم نمط الحالة كثيرًا. بدلاً من تحديثات سطر واحد ، بالنسبة للآثار الجانبية ، فأنت تريد إرسال الطلبات/الردود ، واستخدام FSM محدد المحادثة لتتبع التقدم.

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

تحتاج أيضًا إلى رمز التنظيف وما إلى ذلك (أي. لا تريد أن تنتظر البيانات من عميل إعادة الاتصال للانتظار إلى الأبد).

يتم استخدام الكثير من قائمة الانتظار. لذلك سيستخدم الكثير من الأشخاص بعض حافلات الرسائل (يقول JMS بالنسبة لـ Java) لدفع الأحداث بطريقة معاملات.

Terracotta (مرة أخرى لـ Java) يحل الكثير من هذا من أجلك - ما عليك سوى تحديث الذاكرة - Terracotta هي الواجهة/الوسيط هنا. لقد حقنوا فقط جوانب لك.

Terracotta (لا أعمل من أجلهم) - يقدم مفهوم "Super Static" ، بحيث تحصل على هذه المفردات واسعة العنقودية التي تكون رائعة ، ولكن عليك فقط أن تدرك كيف سيؤثر ذلك على اختبار وتطوير سير العمل - أي. استخدم الكثير من التكوين ، بدلاً من ميراث التطبيقات الملموسة لإعادة الاستخدام الجيد.

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

غالبًا ما يتم استخدام الرسائل (على سبيل المثال JMS) لإدخال اقتران فضفاض بين الخدمات المختلفة. مع خادم الرسائل اللائق ، يمكنك القيام بالكثير من توجيه MSG (مرة أخرى Apache Camel أو ما شابه ذلك ، يقوم بعمل رائع) أي. قل مستهلكًا لزجًا ضد مجموعة من منتجي JMS وما إلى ذلك يمكن أن يسمح أيضًا بفشل جيد. يمكن أن توفر JMS Queue وما إلى ذلك طريقة بسيطة لتوزيع CMDs في الكتلة ، غير مميّزة من Master / Slave. (مرة أخرى ، يعتمد ذلك على ما إذا كنت تقوم بعمل لوب أو كتابة خادم / منتج من نقطة الصفر).

(إذا حصلت على وقت في وقت لاحق ، فسوف أقوم بترتيب ، ربما أضع مزيد من التفاصيل في إصلاح القواعد الإملائية وما إلى ذلك)

نصائح أخرى

نهج واحد لإنشاء برنامج موثوق برنامج تحطم فقط:

برنامج Crash-only هو برنامج يتعطل بأمان ويتعافى بسرعة. الطريقة الوحيدة لوقفها هي تعطله ، والطريقة الوحيدة للبدء هي التعافي. يتكون نظام التعطل فقط من مكونات تعطل فقط تتواصل مع الطلبات القابلة لإعادة المحاولة ؛ تتم معالجة العيوب عن طريق تحطيم وإعادة تشغيل المكون الخاطئ وإعادة محاولة أي طلبات توقيتها. غالبًا ما يكون النظام الناتج أكثر قوة وموثوقية لأن استرداد الانهيار هو مواطن من الدرجة الأولى في عملية التنمية ، بدلاً من الفكرة اللاحقة ، ولم تعد بحاجة إلى رمز إضافي (والواجهات والأخطاء المرتبطة) لإغلاقها الصريح. يجب أن تكون جميع البرامج قادرة على التعطل بأمان والتعافي بسرعة ، ولكن يجب أن تتمتع برامج التعطل فقط بهذه الصفات ، أو يصبح نقصها واضحًا بسرعة.

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

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

خاطئ - ظلم - يظلم:

... وسيكون هناك خادم تخزين

جيد:

... وستكون هناك مزرعة من خوادم تخزين (متعددة) مع موازنات تحميل (متعددة) أمامها

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

  • استخدم مستويات متعددة من ذاكرة التخزين المؤقت.

  • ابحث عن الحلول الشائعة على تسريع Thigs Up (memcached على سبيل المثال).

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

  • استخدم أسماء DNS للأشياء ، Fe storage-lb.servicename يحل العناوين لجميع محولات التخزين. إذا كنت ترغب في إضافة واحدة ، فما عليك سوى تعديل DNS ، ستبدأ جميع الخدمات في استخدامها بشكل تلقائي.

  • أبقيها بسيطة. كلما زاد عدد الأنظمة التي تعتمد عليها ، زادت خدمتك منها.

يعد تصميم أنظمة التوفر العالي (HA) مجالًا نشطًا للبحث والتطوير. إذا نظرت إلى ACM أو IEEE ، فهناك الكثير من الأوراق البحثية حول صفات الخدمة (التوفر ، الموثوقية ، قابلية التوسع ، وما إلى ذلك) وكيفية تحقيقها (اقتران فضفاض ، التكيف ، إلخ). إذا كنت تبحث أكثر عن التطبيقات العملية ، فقم بإلقاء نظرة على أنظمة متسامح ووساطة تم تصميمها للسماح بالتجميع أو الشبكة أو السحابة مثل الوظائف.

يعد النسخ المتماثل وموازنة التحميل (ويعرف أيضًا باسم الوكيل العكسي) من أكثر الأنماط شيوعًا لتحقيق أنظمة HA ، وغالبًا ما يمكن القيام بها دون إجراء تغييرات في التعليمات البرمجية على البرامج الأساسية على افتراض أنها ليست مقترنة بإحكام. حتى الكثير من العروض السحابية الأخيرة يتم تحقيقها بشكل أساسي من خلال النسخ المتماثل وموازنة التحميل ، على الرغم من أنها تميل إلى البناء في مرونة للتعامل مع نطاقات واسعة من الطلب على النظام.

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

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

كما أفهمها ، فأنت تبحث عن أنماط محددة لاستخدامها في تطبيقات Java جزء من بنية HA. بالطبع هناك عدد كبير من الأنماط وأفضل الممارسات التي يمكن استخدامها ، ولكن هذه ليست "أنماط هكتار" حقًا. بدلاً من ذلك ، إنها أفكار جيدة يمكن استخدامها في سياقات MANYS.

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

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

على الرغم من كل هذا ، هناك أنماط مفيدة بشكل خاص في سياقات HA. تم توثيق العديد منهم في الكتاب الكلاسيكي "أنماط بنية تطبيق المؤسسة" بقلم مارتن فاولر.

أنا أفسر "توافر عالية" كما "صفر توقف"" ، والتي يمكن تنفيذها وفقًا لسؤال SE آخر:

صفر تعطل النشر لتطبيقات Java

  1. A/B Switch: (Rolling Upgrade + Mechanism)
  2. النشر الموازي - Apache Tomcat: (لتطبيقات الويب فقط)
  3. تأخر ملزمة المنفذ
  4. ربط المنفذ المتقدم

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

أنماط الاستخدام:

الوكيل/مصنع :

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

إستراتيجية

يمكنك تغيير الخوارزمية في وقت التشغيل عن طريق اختيار خوارزمية واحدة من عائلة من الخوارزميات. إذا أخذت مثال شركات الطيران ، فيمكنك التبديل بين خوارزميات DiscountFare و NormalFare خلال أشهر حركة المرور غير الذروة وذروة.

ديكور:

يمكنك تغيير سلوك الكائن في وقت التشغيل. أضف فئة جديدة وتزيين مسؤولية إضافية.

مشترك كهربائي:

مفيد عند تغيير الواجهة أو العقد بين الإصدار 1 والإصدار 2. سوف يستجيب محول طلبات العميل القديمة والجديدة بشكل مناسب.

إرشادات عامة:

  1. اقتران فضفاض بين الأشياء
  2. يتبع صلب مبادئ في طلبك

تشير إلى صناعة المصدر مقالات الموقع لأنماط أعلاه لفهم أفضل.

ما لا يجب استخدامه:

بصرف النظر عن أنماط التصميم ، يجب عليك اتخاذ بعض الاحتياطات لتحقيق وقت التوقف عن التطبيق الخاص بك.

  1. لا تقدم نقطة فشل في نظامك.
  2. استخدم ذاكرة التخزين المؤقت الموزعة (مثل الطين) /أقفال.
  3. إزالة الاقتران الصعب بين الخدمات. قم بإزالة الاقتران الضيق بين الخدمات باستخدام حافلة/ أطر عمل المراسلة (JMS ، ActiveMQ إلخ)

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

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

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top