هل يمكنك كتابة Deadlock على Camunda BPM؟ واستطيع

صورة


منذ فترة كتبت عن الهجرة الناجحة من IBM BPM إلى Camunda ، والآن أصبحت حياتنا مليئة بالسعادة والانطباعات السارة. لم يخيب Camunda ونواصل صداقتنا مع محرك BPM هذا.



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



نتدرب على القطط



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



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





الرسم التخطيطي 1. العملية التخطيطية لخدمة فروي



يوضح الرسم التخطيطي الخطوات الأساسية والشوكة والانضمام إلى بوابات.





يمثل هذا الرمز بوابة موازية. البوابة المتوازية هي أسهل بوابة لبناء جزء مواز من العملية.



هناك نوعان من البوابات المتوازية:



  • شوكة - إنشاء تنفيذ منفصل لكل فرع ؛
  • انضمام - ينتظر اكتمال جميع عمليات الإعدام الواردة.


التنفيذ - يمثل "مسار التنفيذ" في نسخة العملية (من الوثائق). أي أنها سلسلة تنفيذ عملية.



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



نظرًا لأننا نعمل مع عملاء فروي ، ستكون الخدمات مناسبة: فاليريان ، ومخلب ، وسادة سادة وأشياء مفيدة أخرى.





الشكل 2. مخطط خدمة العملاء المكرر المضحك يبدو



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



للتوازي مع الشروط ، يتم استخدام البوابة الشاملة ، والتي يشار إليها بالرمز التالي:





البوابة الشاملة هي بوابة موازية بشروط الفرع. سيتم تنفيذ الفروع التي تكون فيها الشروط صحيحة.



هناك نوعان من البوابات:



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


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





الرسم التخطيطي 3. النسخة النهائية للعملية التي يجب أن تعمل



لقد اتضح أنها مرهقة ، لكن العملية تحل المشكلة.



ماذا؟ ماذا حدث؟



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



يتحقق الفرع الثاني من حالة المادة ، وبناءً على النتائج ، يتم تنفيذ المهام المقابلة. علاوة على ذلك ، تتوقف العملية عند البوابة التي تجمع البوابة الشاملة ولا تتحرك أكثر. إذا نظرت إلى Coockpit (لوحة الإدارة لـ Kamunda) ، فسيتم تنفيذ عمليات التنفيذ على بوابة Inclusive Gateway و Parallel Gateway.





الرسم البياني 4. تم تعليق عملية الخدمة تم



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



في البحث عن إجابة ̶̶̶̶̶̶̶̶̶̶̶̶



نظرًا لأنه لم يكن لدي فهم كاف لما حدث ولماذا توقفت العملية ، كان لا بد من حل المشكلة تجريبيًا.



ربما تحتاج إلى فرع افتراضي للبوابة الشاملة ، وبدونه لا يمكن تشغيل العملية بشكل طبيعي؟



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





الشكل التوضيحي 5.



بدء تشغيل الخدمة مع الفرع الافتراضي والحصول على نفس النتيجة - تظل العملية معلقة على بوابة Inclusive Gateway.



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





الشكل 6: انحطاط العملية



اتضح أن Parallel Gateway يؤثر بطريقة ما على البوابة الشاملة. هذا غريب وغير منطقي ولا يجب أن يكون كذلك.



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



ماذا تكون؟ كيف تعمل؟



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



- دينيس ، مرحبًا! هل يمكن أن تخبرني كيف يحدد getway التجميع متى حان الوقت للمضي قدما في العملية؟ في كل مكان يكتبون فيه: "كم خرج - يجب أن يأتي الكثير." ولكن كيف يعتقد ذلك بالضبط؟

- بسيط جدا. يحسب Camunda عدد عمليات الإعدام النشطة.

- شكرا جزيلا لك.




لنتأمل الآن ما حدث. للقيام بذلك ، أذكر مرة أخرى المخطط الأولي ، الذي ظهر:





الرسم البياني 7. عملية معلقة مع فرع افتراضي



من أجل البساطة ، نعتبر الحالة عند استيفاء جميع الشروط. ماذا لدينا في الوقت الذي يتم فيه تحقيق ثلاث مهام بعد هذه الشروط؟



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



اصلاح



لتصحيح الوضع ، يجب على بوابة التجميع جمع جميع عمليات الإعدام دفعة واحدة ، ومن ثم ، من الناحية النظرية ، ستستمر العملية. دعنا نحاول ترك بوابة واحدة بدلاً من بوابتي انضمام:





الرسم البياني 8. نسخة مصححة من العملية



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



مثيرة للاهتمام بدأت للتو



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



في البداية ، افترضت أن إصدار Camunda في المثال أعلى منه في المشروع ، وفي الإصدار الجديد تم إصلاح هذه المشكلة بالفعل. لكن تخفيض رتبة كاموندا لم يفعل شيئًا. بالمناسبة ، في جميع الأمثلة يتم استخدام الإصدار 7.8.0 - إنه بعيد عن الأحدث ، ولكن لا يهم. تم فحص المشكلة أيضًا وإعادة إنتاجها في أحدث إصدار في الوقت الحالي - 7.13.



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



اتضح أنه في وجود فرع عكسي ، يتم تكرار المشكلة ونجد أنفسنا في حالة جمود ، ولكن بدون فرع عكسي ، كل شيء يعمل كما ينبغي.



تطلبت القضية الفهم والتحليل. للقيام بذلك ، كان علي أن ألقي نظرة على كود مصدر Camunda BPM. نظرًا لأن المشكلة كانت في البوابة الشاملة ، فقد كان من المنطقي البحث عن إجابة في الفئة المسؤولة عن سلوك هذا العنصر - InclusiveGatewayActivityBehavior . بعد تشغيل التصحيح على كلا الإصدارين من العملية عدة مرات ، اكتشفت كيف تعمل.



إذا لم يكن واضحا - انظر المصادر!



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



دعونا نرى كيف تعمل طريقة ActivatesGateway. لفهم أفضل ، سنعطي أسماء لجميع الفروع التي يتم تنفيذها.





الشكل 9: مخطط العملية مع عمليات الإعدام



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



في حالتنا ، يتم استدعاء هذه الطريقة ثلاث مرات ، لأن عدد عمليات الإعدام القادمة سيزيد من 1 إلى 3. في المكالمة الأخيرة ، سيكون عدد الواصلين والمتوقعين 3 و 4 على التوالي ، وسنترك على الفرع المزيف.



إذا لم يتم استيفاء الشرط ، يتم فحص عمليات الإعدام المتبقية من حيث الانتماء إلى البوابة الشاملة. وبالتحديد ، يتم التحقق من قدرة عمليات التنفيذ النشطة للوصول إلى بوابة Inclusive Gateway.



هنا عليك التحلي بالصبر والزفير والقراءة. الخاتمة قريبة!



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



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



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



ونتيجة لذلك - ينتظر Inclusive Gateway تنفيذًا آخر لن يأتي أبدًا. وبالتالي ، لدينا نوع من الجمود. من حيث المبدأ ، إذا أسقطنا الاتفاقيات ، نحصل على طريق مسدود كلاسيكي: ننضم إلى الانتظار الموازي للفرع مع Inclusive للتنفيذ ، والعكس بالعكس ، الفرع مع الانتظار الشامل لـ Parallel للتنفيذ.



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





الرسم التخطيطي 10. المسار المحتمل من الانضمام المتوازي إلى الانضمام الشامل



يوضح الرسم التخطيطي أن البوابة الشاملة الشاملة متاحة بالفعل من وصلة البوابة المتوازية ، ووفقًا لمنطق Camunda BPM ، لا يهم أن هناك بالفعل "دائرة مستديرة".



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



من الجيد أن تكون المشكلة موضعية. ولكن ماذا عن الآن؟



في الواقع ، الآن - الاستنتاجات:



  1. أعذر من أنذر. نحن بحاجة إلى بناء عملياتنا مع مراعاة هذا السلوك من Camunda.
  2. , . parallel join.
  3. Inclusive Gateway , , executions .
  4. , . , Parallel Gateway .


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



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



الاستنتاج الثاني واضح أيضًا: تحتاج إلى تحليل ليس فقط التعليمات البرمجية ، ولكن أيضًا العمليات.



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



  1. مصادر Camunda BPM
  2. الوصف الوظيفي الشامل للبوابة
  3. كيف تعمل البوابة الموازية



All Articles