لماذا لا يجب عليك استخدام خدمات صغيرة (ييت) (العربية (Arabic))

لماذا لا يجب عليك استخدام خدمات صغيرة (ييت)

Monday, 29 December 2025

//

20 minute read

وأصبحت الخدمات الصغيرة هي بنية "النظام الخطر" الافتراضية.

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

لكن هنا التصحيح معظم المبتدئين لا يتم إعطائهم:

فالخدمات الصغيرة ليست تحديثاً لهيكل التطبيقات، بل هي استراتيجية تنظيمية للتوسع.

إن لم يكن لديك بالفعل الألم التنظيمي الذي يحلونه تبنيهم مبكراً لا يجعلك مانعاً للمستقبل

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

لقد كنت مذنباً كأي شخص في "عمل الخدمات الصغيرة" دون أن أستوعب بالكامل ما يترتب عليها من نفقات تنظيمية. من السهل أن ننشغل في المفردات وننسى أن التحدي الحقيقي هو إدارة التعقيد عبر الفرق والنظم.

في نهاية المطاف يصل إلى أقدم نمط في هندسة البرمجيات: KKSSKSKSS -أبقي الأمر بسيطاً وغبياً

أسطورة الخدمات الصغرى

وتباع الخدمات الصغرى كعمارة افتراضية لأن السرد مغري:

  • الخدمات الصغيرة هي "نظيفة"
  • النظم الموزعة هي "محدثة"
  • الحكم الذاتي هو "حُرّ"
  • يمكنك "تدرج لاحقاً" لأنك بدأت "صحيح"

هذا التأطير هو إلى الوراء.

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

إذا لم يكن لديك:

  • الفرق المتعددة القطاعات التي تقوم بالشحن بشكل مستقل
  • نوع النشر
  • حدود الملكية الحقيقية

إذاً فأنت لا تحل مشكلة تنظيمية بل تشتري واحدة

العمارة هي في نهاية المطاف عن تمكين الناس، وليس تحريك الصناديق حولها.

التخطيط الذي يجب ان يكون تحذيراً رمزاً

لقد رأيت هذا الرسم البياني.

الرسم البياني لرسوم هندسية خدمات دقيقة تحذيرية

هذا ليس "مثل الهندسة المعمارية لنسخها" إنه علامة تحذير.

وكثيراً ما تُدرِّس الدورات الخدمات الصغيرة كرسوم بيانية لأن الرسوم البيانية أسهل من تدريس المسؤولية التشغيلية.

هذا هو: ذلك الرسم التخطيطي ليس حالة مستهدفة. هو a التكلفة الفعلية (التكلفة الفعلية).

كل صندوق هو التزام:

  • وقت تنفيذ التشغيل
  • (أ) النشر إلى الإدارة
  • العقد من العقد إلى النسخة
  • A مُخَلْط OP أنت الآن مالك
  • قصه لا يمكنك تجاهلها

السهام تبدو رائعة إنها أيضاً تخفي الحقيقة

لأن كل سهم هو:

  • متأخرة
  • &
  • المهل
  • (تابع) (تابع)(أ)(ب)(ب)(ب)(ب)(ب)(ب)(أ)ب)(أ)
  • "العمل في التنظيم" الأكاذيب

إذا تطلبت الهندسة المعمارية هذا في اليوم الأول، فأنت لا تبني منتجاً. أنت تبني منصة.

نموذج التكلفة المخفية للخدمات الصغيرة

مثل كل القرارات المعمارية، تأتي الخدمات الجزئية مع درجة الحرارة (انظر ( اللعب بالمدونة: تشعّر الضريبةالفرق هو أن هذه الضريبة تُجمع عبر كل حدود الخدمة، كل انتشار، وكل طريقة فشل.

التكاليف نادراً ما تكون واضحة عادة ما تكون "ممارسة أفضل"

النفقات العامة التشغيلية

كل خدمة تريد:

  • ألف - خط الأساس الخاص بها
  • تشكيلة النشر الخاصة بها
  • رصدها وتنبيهها
  • (أ) عمليات قطع الأشجار، والآلات، والكتب الإدارية الخاصة بها
  • وضعيتها الأمنية الخاصة بها (الأمينات، أوف، أوف، أوف، أوف، أوفوث، أو إنغريس)

إذا لم يتمكن فريق من فعل هذا بطريقة مريحة، فليس لديه خدمات صغرى. مُوزّع بخطوات إضافية.

المتأخّر والفشل

في الأونوليث، النداء هو نداء دالة.

أما في الخدمات الصغرى، فإن "الدعاء" هو اتفاق تفاوضي بين:

  • الشبكات
  • موازن
  • ثالثاً - مقدمات
  • الموالية
  • المهل
  • &
  • الـكبريـس

فشل في الضرب:

  • واحد مصب واحد هو بطء في تكوّم الخيوط المتصاعدة
  • أنت Ddos نفسك بشكل مؤدّب
  • اعتماد واحد يُؤكّدُ ثلاثة خدماتِ تُحلّلُ "مُستوطنة"

أنت لا تزيل الحشرات بعد الآن أنت تزيل الحشرات الولايات المتحدة الأمريكية.

لا احد يتحدث عن الضريبة التسلسلية

هذه هي التكلفة التي تقريباً لا تناقش أبداً في دعاية الخدمات الصغرى: الجدول العامــات العامــة )SERD(.

كل خط حدودي للخدمة يعني:

// Monolith: direct object reference
var user = _userService.GetUser(userId);  // < 1μs
var tier = user.Tier;                      // Memory access

// Microservices: serialize → network → deserialize
var json = JsonSerializer.Serialize(user);        // ~50μs for a complex object
var bytes = Encoding.UTF8.GetBytes(json);         // ~10μs
// ... send over network ...
var responseJson = await response.Content.ReadAsStringAsync();  // ~20μs
var user = JsonSerializer.Deserialize<User>(responseJson);      // ~70μs
var tier = user.Tier;                                           // Finally

بالنسبة للمكالمة، هذه حوالي 150% من وحدات المعالجة المركزية النقية قبل أن تتورط الشبكة حتى.

الآن نضرب ذلك على a دعوة سلسلة:

  • الطلب (150 في المائة)
  • طلب خدمة المستعملين (150 في المائة)
  • خدمة مُستخدِم المُستخدِم المُجَرِّد طلبات
  • متسلسلات خدمات المستعملين
  • رد فعل المستخدم (150 Ims)
  • طلبات الجرد (150 في المائة)
  • وما إلى ذلك على

في سلسلة 5 خدمات، كنت تنفق 5.5 مليون دولار فقط على سيردي إذا كنت تستخدم XML، فإن البروتوكول المجاز مع الانعكاس، أو التسلسلات غير الكفؤة، ضرب ذلك بـ 2-10x.

نعم، يمكنك تقليل هذا مع تقنيات مثل توليد مصدر الـ JJSON:

[JsonSerializable(typeof(User))]
internal partial class UserJsonContext : JsonSerializerContext { }

// ~30-40% faster than reflection-based serialization
var json = JsonSerializer.Serialize(user, UserJsonContext.Default.User);

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

مثال حقيقي : كارثة السير

ذات مرة أوجزت نظام بحث عن العنوان مع هذا الهيكل (كل في حاويات الكوبرنيت):

ASP.NET API → Go Service (fan-out) → ASP.NET Search Service → Elasticsearch

وعالجت خدمة "Go-Service" مسألة الترهيب إلى مصادر بيانات متعددة ونتائج مجمعة.

توزيع البحث عن عنوان نمطي:

  • ASP.net API: طلب بحث تسلسلي
  • الشبكة: الشبكة الأفريقية لشبكة الشبكة العالمية (Go (البيانات حسب حمولة المجموعة)
  • الذهاب إلى الخدمة: طلب إزالة البرمجية (40 في المائة)
  • GWW الخدمة: نشر خارج - تسلسل الطلبات إلى المنافذ الخلفية المتعددة (60
  • الشبكة: تشغيل الشبكة ASP.net Surs (vavies)
  • الفريق العامل: طلب الإزالة من
  • دائرة خدمات البحث: بناء استفسار بحث علمي علمي، تسلسلي (120
  • الشبكة: البحث العلمي
  • Elatstissears: استعلام استعلام استعلام إستفسار استعلام تنفيذ تسلسل النتائج (البحث الفعلي: 5ms, SerDe: 200%s)
  • الشبكة: البحث البحثي (Vairs)
  • الخدمة: إزالة الهجـرة من الاستجابة ESS (300) ، خريطة إلى نموذج النطاق ، مسلسلة (180
  • الشبكة: البحث:
  • Go الخدمة: إزالة ميزات الردود من جميع المنافذ الخلفية (150 x x N)، المجموع، التسلسل (80%)
  • الشبكة: تشغيل الشبكة (الشبكات)
  • SPSP.net API: إزالة البرمجية من الرد النهائي )١٢٠/١٢٠(

لـ a ثلاثة خلفيات مروحة:

  • مجموع نفقات سيرD: ~2m قبل أن يبدأ Elastest Sears حتى
  • الشبكة العامة بين الحاويات:
  • البحث الفعلي + منطق العمل التجاري:

كنا نقضي نفس الوقت تقريبا على سيردي كما كنا على البحث الفعلي.

التكلفة لم تكن خدمة Go Go في حد ذاتها - مر مر مر مر مروّع كان منطقياً لقضية الاستخدام. التكلفة كانت خ ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط( ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط ط طكل حاويات الحدود تعني تسلسل شبكة إزالة الجراثيم.

في المنفردة التي تقوم بنفس المنطق التكهني:

  • استفسارات نفس الشيء عن البحث البحثي
  • نفس منطق التجميع
  • SerD (المكالمات بالطرق العادلة)
  • 40% ناقص المجموع الكلي للتأخر

هذه التكلفة:

  • أحجام مع تعقيد الجسم (أجسام مستعرة، مجموعات، متعددة الأشكال)
  • مجمعات مع عمق الاستدعاء (سلاسل الخدمات)
  • يُحرّر المعالج عند كل طلب (لا يمكن أن يخبئه بعيداً)
  • الزيادات في ضغط GC GC (موازِل المُنتَزَج من المصفوفات الخيطية)
  • يزيد بسرعة عندما تقوم بعمل مئات الطلبات لكل ثانية

في المونوليث، هذه التكلفة هي صفر. الكائن موجود بالفعل في الذاكرة.

أسطورة الأداء: المُسْبَق مقابل المُسْتَمِلَة

ها هو عرض مشترك للمبيعات: "الخدمات الصغيرة تحسن الأداء".

هذا هو إلى الوراء.

(الخدمات الجارية) هي: 1 ف-5، 1 ف-4، 1 ف-3، 1 خ م، 1 م و، 1 م و، 1 م و، 1 م و، 1 م و، 1 م و، 1 م و، 1 م أ م و لنكون دقيقين حول ما نعنيه:

الموضوع (الطلبات لكل ثانية لكل نواة من المعالج المعالج):

  • ****أعلى: أعلى: صفر صفر سيردي، صفر شبكة قفزات، طرق مباشرة المكالمات
  • ****أقل: أقل - سيرد: خطوط عامة، شبكة متباعدة، وحاوية وسيطة

**** (يمكّن من معالجة طلبات أكثر إجمالا بإضافة موارد):

  • ****الحد: محدود بالتدرج العمودي (آلات الحفر)
  • ****: أفقي - يضاف المزيد من حالات خدمات الاختناقات الزجاجية

الخدمات الصغيرة تسمح لك الاستقلاليـةإذا كانت خدمة مخزونك تحتاج إلى 10x موارد لكن خدمة المستخدم الخاصة بك لا تحتاجها، يمكنك قياسها بشكل منفصل. هذا قيّم. عندما تحتاج إليها.

ولكنه ليس تحسيناً أداءياً. إجراء الاستسسسويأتي مع ضريبة.

تُحْسَلَ ٱلْمَوَاتِ ٱلْمَوَاتِ ٱلْمَوَاتِ ٱلْمَيْضِ

والحجة القائلة بأن "حجم الخدمات الصغيرة أفضل" أصبحت أكثر منطقية في عام 2010 عندما كانت الخوادم تحتوي على 4-8 نواة.

الخوادم الحديثة لديها 32-128 نواة يمكن لآلة واحدة أن تدير آلاف العمليات المتزامنة بكفاءة

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

// Process thousands of concurrent operations in a monolith
services.AddEphemeralWorkCoordinator<TranslationRequest>(
    async (request, ct) => await TranslateAsync(request, ct),
    new EphemeralOptions { MaxConcurrency = Environment.ProcessorCount * 4 });

// Bounded, observable, efficient concurrent processing
// No network overhead, no SerDe, no container orchestration
// Can handle 10k+ req/sec on a single machine

هذا يعطيك:

  • المراسلةالعمل يجري بشكل متزامن عبر كل النواة
  • ****: المسار المعلق/النشط/العمليات المشغولة
  • الـكبريـس: الطوابير المضغوطة تمنع استنزاف الذاكرة
  • (النفق العام): لا تسلسلية، لا شبكة، لا تتبع موزع

& لا يُعتمد تحتاج إلى قياس أكثر من آلة واحدة، يمكنك:

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

ما زلتِ تُديرين جهازاً منويّاً، لقد قمتِ بنشره عدة مرّات.

النقطة النقطةلا تنقسم إلى خدمات صغرى مقابل "أداء" الإسناد المستقل لمكونات محددة يُبرر النفقات التشغيلية العامة.

مُلق

خدمات الميكروسيرات لا تقلل من التعقيدات، بل تعيد توزيعها.

ولا تزال "الخدمة البسيطة" تحتاج إلى السياق التالي:

  • مَنْ يَدْعُوه؟
  • ماذا تعني كلمة "صحيحة"؟
  • ماذا يحدث عندما يسقط؟
  • ما هي الخطة؟
  • ما هو الرسم البياني للتبعية؟

الناس يستخفون بهذا لأن الرسومات تخفيه.

النسخ والعقد

وتصبح كل حدود عقدا.
يصبح كل عقد على النحو التالي:

  • قواعد الإصدار
  • ضمانات التوافق
  • القيود المتعلقة بالتعرّض
  • تَظْهرُ بأنّك ما كَانَ عِنْدَكَ

يمكنك تجنب هذا لفترة من الوقت مع "مجرد نشر كل شيء معا".

هذا هو اللكم: إذا قمتم بنشر كل شيء معاً، قمتم ببناء مونوليث. فقط واحد أسوأ.

:الإنفاق المبكر هو نفسه دائماً

  • اكتشاف الخدمة
  • التعقب الموزع
  • قطع الأشجار الذي وُسّط
  • MCMS والإنذار
  • CC CCCCCCCNames
  • قصة محلية محلية غير مؤلمة
  • "طريقة لإدارة كل شيء بدون بكاء"

ولا قيمة من قيمة هذه السفن.

ومعظم الفرق تفعل ذلك قبل أن تثبت أن المنتج يستحق التعقيد.

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

مجتمعة، هذه التكاليف لا تختفي، إنها مركبة، وهي تُجمع ما إذا كانت المنظمة تحتاج خدمات صغرى في المقام الأول أم لا.

ما ينسيه الناس : البشر والفرق

يوجد العمارة لمساعدة مجموعات البشر على تغيير البرمجيات بأمان.

ليس لإبهار المهندسين الآخرين.
ليس إلى a.
ليس لتبرير الفريق الأساسي الذي لا تملكه.

فحجم الفريق وقوائم النشر أكثر من دليل النمط.

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

قانون (كونواي) ليس اختيارياً إنها الفيزياء

هيكلك المعماري سيعكس هيكل تواصلك سواء أعجبك أم لا.

الخدمات الصغيرة لا تخلق استقلالاً ذاتياً بل تتطلب ذلك

الدفاع عن المونوث المائلي

معظم الأنظمة يجب أن تبدأ كمونوليث ولكن ليس مهملاً

A A (منقولية) (أ) ما يلي:

  • وحدة نشر
  • مُرَكَّب
  • مكان واحد لتطهير
  • رأي واحد ثابت للدولة
  • ولكن مع حدود داخلية حقيقية

يعني:

  • دعم تنفيذ مع مع مع
  • & مفتاح
  • لا "كل شيء يشير إلى كل شيء"
  • العقود المنفذة داخل القاعدة

النقطة ليست أن نبقى أحادية الأولثيثيك إلى الأبد النقطة هي إلى "تكسب حدوداً قبل أن تجعلها بعيدة".

يُجبرُك a unolitive uniticative إلى تَعَلّم المهاراتِ progresses تَدْعي إلى حَلّ:

  • نطاق النمز (الحدود الحقيقية، لا حدود المجلدات)
  • الفصل بين الشواغل (وليس "قدّمنا خدمة")
  • 1 م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م م
  • التغيير في درجة السلوك
  • معرفة ما يقوم به نظامك في الواقع

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

التصميم الحجري الجيد : الأنماط التي تُحَدِّد لاحقا

تصميم المونوليث الصحيح يسمح لك قرار التأأأأأأأجأ قرار الخدمات الجزئية بدون حبس نفسك في الداخل.

صندوق المخرجات نمط: Asyn بدون توزيع

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

بدلا من:

// Tightly coupled synchronous code
public async Task PlaceOrder(Order order)
{
    await _orderRepo.Save(order);
    await _emailService.SendConfirmation(order);  // Blocks on external service
    await _inventoryService.Reserve(order.Items); // Blocks on another service
}

تكتب::

// Outbox pattern: write events to a table
public async Task PlaceOrder(Order order)
{
    await using var transaction = await _db.Database.BeginTransactionAsync();
    
    // Save order
    await _orderRepo.Save(order);
    
    // Write events to outbox table (same transaction)
    _db.OutboxMessages.Add(new OutboxMessage
    {
        EventType = "OrderPlaced",
        Payload = JsonSerializer.Serialize(order),
        CreatedAt = DateTime.UtcNow
    });
    
    await _db.SaveChangesAsync();
    await transaction.CommitAsync();
    
    // Background worker picks up outbox events and publishes them
}

ما يعطيك هذا:

  • أولاً - الاتساق:: الأحداث والبيانات تُجمع معاً أو لا تُجمع على الإطلاق
  • ****: البريد الإلكتروني / في المحفوظ المنطق يعمل async، لا يحجب إنشاء النظام
  • المليمالأحداث تستمر حتى لو كانت الأنظمة المُنتَجَة مُنَخَطِطَة
  • ****في وقت لاحق، مبادلة عامل صندوق البريد الخارجي بكافكا/راببيتمQ بدون تغيير منطق النظام

الـ مشروع العينة هذا النمط في الإنتاج:

// Mostlylucid.SegmentCommerce/Services/Queue/PostgresOutbox.cs
public class PostgresOutbox
{
    public async Task PublishAsync<T>(string eventType, T payload)
    {
        var message = new OutboxMessage
        {
            EventType = eventType,
            Payload = JsonSerializer.Serialize(payload),
            CreatedAt = DateTime.UtcNow
        };
        
        _db.OutboxMessages.Add(message);
        // Caller commits transaction
    }
}

// Background service
public class OutboxProcessor : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            var pending = await _db.OutboxMessages
                .Where(m => !m.Processed)
                .OrderBy(m => m.CreatedAt)
                .Take(100)
                .ToListAsync();
                
            foreach (var message in pending)
            {
                await ProcessMessage(message);
                message.Processed = true;
            }
            
            await _db.SaveChangesAsync();
            await Task.Delay(1000, stoppingToken);
        }
    }
}

هذا يعمل في تطبيق واحد اليوم. عندما تحتاج إلى قياس:

  1. يستعاض عن عامل المعلومات الأساسية بمستهلك رسالة بحافلة
  2. نشر الأحداث في صناديق بريد خارجي إلى كافكا/راببيتمQ بدلاً من التجهيز محلياً
  3. لم يتغير رمز الأمر

لقد بنيت بنية تحتية جاهزة للخدمات الصغيرة بدون دفع ضريبة التوزيع

اخرى اخرى اخرى اخرى

  • CQRS (إضاءة): نماذج قراءة/كتابة منفصلة حتى وإن كانت مشتركة في مصرف DB
  • **مصادر مرجعية )انتقائية(**فيما يتعلق بالكيانات الحيوية لمراجعة الحسابات فقط
  • الأعلام: يُنشر من الإصدار
  • الأعمال الأعمال: لا تحجب الطلبات ، معالجة async

لا شيء من هذه يتطلب توزيعاً كلها تسهل التوزيع لاحقاً

متى تُسِع الخدمات

فالخدمات الصغيرة تكون منطقية عندما تكون القيود حقيقية وليست ملهمة.

السؤال الحاسم هو ليس "هل يجب أن نستخدم الخدمات الصغيرة؟" إنه: هل تفوق الفوائد ضريبة التشغيل؟

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

ازجججج جيد

  • (بأ)(أ)(أ)(أ)(كأ)(أ)(كأ)ك: الفرق تحجب بعضها البعض أسبوعياً
  • من الضروري وجود نشرات مستقلة: الإطلاق cadence يختلف عن النطاق
  • جدول جدول:: يحتاج نظام فرعي واحد إلى موارد وانعزال
  • ****عنصر واحد لا يجب أن يطيح بالباقي
  • عزلة التنظيم/البيانات إلزامية:: الحدود الزمنية غير قابلة للتداول
  • هيكل أورج هو بالفعل متعدد الفريق:: وجود واستقرار الملكية:

مُنتفِج

  • "قد ندرج"
  • "Netflix يفعل ذلك"
  • "ممارسة أفضل الممارسات"
  • "سوف تبدو جميلة"
  • "المونوليث الخاص بنا هو فوضوية، لذلك نحن سوف إصلاحه عن طريق تقسيمه "

إذا كان سببك يحتوي على الكلمات قر قد قد, في نهاية الأمرأو معرّل في المستقبلمن المحتمل أنه ليس سبباً

الواقع التقني : ما هي تكلفة الخدمات الصغيرة

دعونا نحصل على الخرسانة. إليكم التغييرات عندما تقسمون المنفردة إلى خدمات.

مُنا C C C C C C C C C C C C C C C C C C C C C C C سلسلة و Lاط

مونوث:

public async Task<Order> PlaceOrder(OrderRequest request)
{
    var user = await _userService.GetUser(request.UserId);
    var inventory = await _inventoryService.CheckStock(request.Items);
    var price = _pricingService.Calculate(request.Items, user.Tier);
    
    var order = new Order { /* ... */ };
    await _orderRepository.Save(order);
    await _emailService.SendConfirmation(order);
    
    return order;
}

عدد حالات التأخير الكلي: حوالي 50 متراً (مكالمات هاتفية في أثناء العملية + 2 استفسارات من مصرف DB)

ما يلي:

public async Task<Order> PlaceOrder(OrderRequest request)
{
    // HTTP call to User Service (network + TLS + serialization)
    var user = await _httpClient.GetAsync<User>($"http://user-service/users/{request.UserId}");
    
    // HTTP call to Inventory Service
    var inventory = await _httpClient.PostAsync<StockResult>(
        "http://inventory-service/check", request.Items);
    
    // HTTP call to Pricing Service
    var price = await _httpClient.PostAsync<PriceResult>(
        "http://pricing-service/calculate", 
        new { items = request.Items, tier = user.Tier });
    
    // HTTP call to Order Service
    var order = await _httpClient.PostAsync<Order>(
        "http://order-service/orders", request);
    
    // Event published to message bus
    await _messageBus.Publish(new OrderPlaced { OrderId = order.Id });
    
    return order;
}

المجموع الكلي للمديونية: حوالي 400 متر (حتى التفاؤل 50 - 80 متر لكل نداء HTTP في البيئات الحقيقية + نشر حافلة الرسالة 20ms)

ما كسبته:

  • يمكن لكل خدمة أن تُنشر بصورة مستقلة
  • يمكن وضع جدول للمخزون والتسعير منفصلاً عن الترتيب
  • فشل في البريد الإلكتروني لا يحجب إنشاء أمر إنشاء (asyync)

ما دفعته:

  • زيادة في حالات التأخير
  • 4 نقاط عطل جديدة (أي خدمة يمكن أن تكون منخفضة/منخفضة)
  • الشبكة، DNS، TLS OS على كل نداء
  • التتبع/النفقات العامة (انظر الفرع السابق)
  • الحاجة لمنطق إعادة الاختبار، ومفرقعات الدوائر، والفترات الزمنية
  • التعقب الموزع لإزالة الأخطاء

مورِد:

try
{
    var order = await PlaceOrder(request);
    return Ok(order);
}
catch (InsufficientStockException)
{
    return BadRequest(new { error = "Out of stock" });
}
catch (Exception ex)
{
    _logger.LogError(ex, "Order placement failed");
    return StatusCode(500);
}

مناولة الخطأ في إطار هذه الخدمات:

try
{
    // Call User Service
    var user = await _httpClient.GetAsync<User>($"http://user-service/users/{request.UserId}");
}
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{
    return NotFound(new { error = "User not found" });
}
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.ServiceUnavailable)
{
    // Retry with exponential backoff?
    // Circuit breaker opened?
    // Fail fast or degrade gracefully?
    _logger.LogWarning("User service unavailable, retrying...");
    await Task.Delay(TimeSpan.FromMilliseconds(100));
    // ... retry logic ...
}
catch (TaskCanceledException ex)
{
    // Timeout - was the request processed? Do we retry?
    _logger.LogError("User service timeout");
    return StatusCode(503, new { error = "Service temporarily unavailable" });
}

try
{
    var inventory = await _httpClient.PostAsync<StockResult>(
        "http://inventory-service/check", request.Items);
}
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.BadRequest)
{
    // Business error from remote service
    var errorDetails = await ex.Content.ReadAsAsync<ErrorResponse>();
    return BadRequest(new { error = errorDetails.Message });
}
catch (HttpRequestException ex)
{
    // Which service failed? Network issue? Service down?
    // Do we have a fallback? Cached data? Fail fast?
    _logger.LogError(ex, "Inventory service failed");
    // Maybe try a backup instance?
    // ... more retry logic ...
}

// And repeat for every service call...

كل شبكة تتصل بالمدخلات:

  • سيناريوهات الوقت المحدد
  • فشلات الشبكة
  • درجة الخدمة
  • حالات القصور الجزئي (أُرسل الطلب، ولم يرد الرد)
  • إعادة تجربة التضخيم (إعادة المحاولة قد تُثير إعادة المحاولة)
  • عدد كوابيس المعاملات الموز توزيعها

النشر من قبل:

# Build
dotnet publish -c Release

# Run migrations
dotnet ef database update

# Deploy
docker push myapp:v1.2.3
kubectl set image deployment/myapp myapp=myapp:v1.2.3

# Rollback if needed
kubectl rollout undo deployment/myapp

نشر الخدمات:

أنت تغير هيكل النظام الآن Order يُدرج UserTier (تُجنى مباشرة إلى مستوى غير عادي بالنسبة للأداء).

# 1. Deploy Pricing Service v2 (understands both old and new Order format)
kubectl set image deployment/pricing-service pricing-service=pricing:v2.0.0

# 2. Wait for rollout and monitor
kubectl rollout status deployment/pricing-service
# Check metrics - is v2 working with old order format?

# 3. Deploy Order Service v2 (starts sending new format)
kubectl set image deployment/order-service order-service=order:v2.0.0

# 4. Monitor for errors
# If Pricing v2 has a bug, you can't just rollback Order service
# You have to rollback both in reverse order

# 5. Deploy User Service v2 (stops including tier in response)
# But wait - old Order Service instances might still be running!
# Need zero-downtime rollout or maintain backward compat

# 6. Eventually clean up old code paths in Pricing Service v3
# (6 months later because you're scared to remove backward compat)

مع خدمات صغيرة، كل تغيير يتقاطع مع خدمات متعددة. يتطلب تطور العقود:

  • إلى الخلف
  • علامة الأعلام عبر الخدمات
  • مصفوفات اختبار ممتدة (الخدمة A v1 + الخدمة B v2، الخدمة A v2 + الخدمة B v1، وما إلى ذلك)

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

الخبرة في تصحيح التأجيل

تقرير مُشْكِلِث: "تنسيب النظام يفشل للمستخدمين الأقسمة"

// Set breakpoint in PlaceOrder
// Step through each call
// User tier is null - ah, there's the bug
// Fix, test, deploy

تقرير عن ميكروسيرات الخدمات: "تنسيب النظام يفشل للمستخدمين الأقسمة"

# 1. Check logs - which service failed?
kubectl logs -l app=order-service --tail=100

# 2. Oh, it's calling Pricing service. Check those logs
kubectl logs -l app=pricing-service --tail=100

# 3. Grep for correlation ID across all services
stern -l app=order-service,app=pricing-service,app=user-service \
  | grep "correlation-id-xyz"

# 4. Reconstruct the call chain from distributed traces
# Open Jaeger/Zipkin, find the trace
# User service returned 200 OK
# Pricing service returned 400 Bad Request
# Error: "user.tier is required"

# 5. Check User service - did it send tier?
# Look at schema version - ah, User v1.2 stopped sending tier
# When did that deploy? Was Pricing service updated?

# 6. Check API contracts
# Pricing expects tier, User stopped sending it
# Who approved this change?

# 7. Fix requires coordinating two teams
# Can't just deploy a fix - need contract negotiation

هذا هو الواقع: حشرات كانت 5 دقائق من التصليحات تصبح تحقيقات متعددة الفرق.

إذا كان هذا يبدو متطرفاً، جيد، الخدمات الصغيرة هندسية متطرفة.

كيف يمكن أن يتطور في أمان: خدمات مصغرة

الخدمات الصغيرة هي باب ذو اتجاه واحد عاملهم كواحد منهم

المسار الآمن يبدو مملاً:

1- تحديد الحدود أولاً

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

إحصلْ على المحارمِ الحقّ الصحيحِ محليّاً أولاً.

2- مقتطفات قراءات قبل الكتابة

القراء أسهل:

  • عدد أقل في الساكنات
  • متطلبات الاتساق مع عدد أكبر من النساء
  • # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

انقل اقرء الزوائد أولاً إذا كنت بحاجة إلى فصل.

أولاً - مقدمة 1 - 3 Assync SA

نداء الخدمة المتزامنة يخلق سلاسل تبعية.

يُنشئ المراسل:

*

  • المُرْكج
  • فك التفريق الذي يمكنك في الواقع البقاء على قيد الحياة

البدء بفصل الأحداث والحقائق، وليس بتقسيم نقاط النهاية.

مُشتق، لا تُعيد الكتابة

لا أحد كبير بانفجار.
لا "سنعيد كتابتها بشكل صحيح"

قطع من الحدود، وقياس ذلك، وتملكه، ومواصلة المضي قدما.

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

:الخدمات الصغيرة تدفع فقط إذا كنت تفهم المتاجرة

فالخدمات الصغيرة ليست نقطة انطلاق بل هي نتيجة.

وينبغي أن يتحقق ذلك. والنظم الموزعة ليست شارة - بل هي أداة للدين.

معادلة المفاضلة بسيطة:

Microservices Value = (Team Autonomy + Independent Scaling + Failure Isolation)
                     - (Latency Tax + SerDe Tax + Operational Overhead + Coordination Cost)

بالنسبة لمعظم الفرق - وخاصة في المراحل المبكرة أو منتجات فريق واحد - فإن الجانب الأيمن يهيمن. تدفع تكاليف باهظة مقابل الفوائد التي لا تحتاجها بعد.

ولكن عندما يكون لديك:

  • 5+ 5 فرق تدوس على أصابع أصابع أصابع بعضها البعض
  • عدد مرات النشر المق قياساً بالأيام
  • نُظم فرعية لها احتياجات مختلفة اختلافاً كبيراً في مجال الإسناد
  • المتطلبات التنظيمية لعزل البيانات

ثم يبدأ الجانب الأيسر بالفوز والضريبة تصبح مبررة

إطار عمل مقرر

وفيما يلي هذه الأسئلة:

  1. هل من الممكن أن فريق واحد لا يزال يملك هذه النهاية إلى النهاية؟
    □ نعم : ابقوا على قيد الحياة . لا : تأملوا في التقسيم .

  2. هل تم حجب الفرق عن طريق دورات إطلاق سراح بعضهم البعض؟
    □ نعم: قد تساعد الخدمات الصغرى في ذلك. لا: التنسيق يعمل.

  3. هل لدينا العضلات التشغيلية لتشغيل الأنظمة الموزعة؟
    □ لا : اصنعها اولا . نعم : امضي قدما بحرص .

  4. هل يمكننا تعقب وتنقية ونشر خدمات متعددة بدون بطولة؟
    □ لا : انت لست مستعدا . نعم ، قد تكون كذلك .

  5. هل أثبتنا الحدود في الشفرة أولاً؟
    □ لا : اصلح هيكلك المنوم . نعم : الاستخراج اكثر امانا .

إذا كنت لا تستطيع الحصول على الماضي السؤال 3 مع الثقة، كنت لست على استعداد للميكرو Services - وهذا على ما يرام. البنيان الممنوع هو ميزة تنافسية.

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

عملك ليس بناء أكثر العمارة روعة، بل تقديم قيمة بينما تقليل التعقيد العرضي.

ولم يدفع أي زبون زيادة لأن نظامك استخدم كافكا

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

Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.