BPM انداز انضمام

BPM انداز انضمام

هيلو حبر!

اسان جي ڪمپني ERP-ڪلاس سافٽ ويئر حلن جي ترقي ۾ ماهر آهي، جنهن جو وڏو حصو ٽرانزيڪشنل سسٽم تي قبضو ڪيو ويو آهي وڏي مقدار ۾ ڪاروباري منطق ۽ دستاويز جي وهڪري سان لا EDMS. اسان جي پروڊڪٽس جا موجوده ورجن جاوا اي اي ٽيڪنالاجيز تي ٻڌل آهن، پر اسان پڻ فعال طور تي مائڪرو سروسز سان تجربا ڪري رهيا آهيون. اهڙن حلن جي سڀ کان وڌيڪ مشڪلاتي علائقن مان هڪ آهي ڀرپاسي ڊومينز سان تعلق رکندڙ مختلف سب سسٽم جو انضمام. انضمام جي مسئلن هميشه اسان کي هڪ وڏو سر درد ڏنو آهي، بغير ڪنهن تعميراتي انداز، ٽيڪنالاجي اسٽيڪ ۽ فريم ورڪ جيڪي اسان استعمال ڪندا آهيون، پر تازو ئي اهڙن مسئلن کي حل ڪرڻ ۾ ترقي ڪئي وئي آهي.

آرٽيڪل ۾ آئون توهان جي توجه ڏيان ٿو، مان ان تجربي ۽ تعميراتي تحقيق بابت ڳالهائيندس جيڪو اين پي او ڪرسٽا جي نامزد ٿيل علائقي ۾ آهي. اسان هڪ ايپليڪيشن ڊولپر جي نقطي نظر کان انضمام جي مسئلي جي سادي حل جو هڪ مثال پڻ ڏسنداسين ۽ اهو معلوم ڪنداسين ته هن سادگي جي پويان ڇا لڪيل آهي.

رد ڪرڻ

آرٽيڪل ۾ بيان ڪيل تعميراتي ۽ ٽيڪنيڪل حل مون طرفان تجويز ڪيل آهن ذاتي تجربن جي بنياد تي مخصوص ڪمن جي حوالي سان. اهي حل آفاقي هجڻ جي دعويٰ نٿا ڪن ۽ استعمال جي ٻين حالتن ۾ بهتر نه هجن.

BPM جو ان سان ڇا تعلق آهي؟

هن سوال جو جواب ڏيڻ لاء، اسان کي اسان جي حل جي لاڳو ٿيل مسئلن جي وضاحتن ۾ ٿورو وڌيڪ ڌيان ڏيڻ جي ضرورت آهي. اسان جي عام ٽرانزيڪشن سسٽم ۾ ڪاروباري منطق جو بنيادي حصو صارف انٽرفيس ذريعي ڊيٽابيس ۾ ڊيٽا داخل ڪري رهيو آهي، هن ڊيٽا جي دستياب ۽ خودڪار تصديق، ان کي ڪجهه ڪم فلو ذريعي کڻڻ، ان کي ڪنهن ٻئي سسٽم ۾ شايع ڪرڻ / تجزياتي ڊيٽابيس / آرڪائيو، رپورٽون ٺاهڻ. . اهڙيء طرح، گراهڪن لاء سسٽم جو اهم ڪم انهن جي اندروني ڪاروباري عملن جي خودڪار آهي.

سهولت لاءِ، اسان ڪميونيڪيشن ۾ اصطلاح ”دستاويز“ استعمال ڪندا آهيون جيئن ڊيٽا جي هڪ سيٽ جي ڪجهه تجريد جي طور تي هڪ گڏيل ڪنجي سان گڏيل آهي جنهن سان هڪ خاص ورڪ فلو ”ڳنڍ“ ٿي سگهي ٿو.
پر انضمام جي منطق بابت ڇا؟ سڀ کان پوء، انضمام جو ڪم سسٽم جي فن تعمير جي ذريعي پيدا ڪيو ويو آهي، جيڪو "ڪٽ" حصن ۾ نه آهي ڪسٽمر جي درخواست تي، پر مڪمل طور تي مختلف عنصر جي اثر هيٺ:

  • Conway جي قانون جي تابع؛
  • ٻين پراڊڪٽس لاءِ اڳ ۾ ٺاهيل سبسسٽم کي ٻيهر استعمال ڪرڻ جي نتيجي ۾؛
  • معمار جي صوابديد تي، غير فعال گهرجن جي بنياد تي.

مکيه ڪم فلو جي ڪاروباري منطق کان انضمام جي منطق کي الڳ ڪرڻ لاء هڪ وڏو آزمائش آهي، انهي ڪري ته ڪاروباري منطق کي انضمام جي نموني سان آلوده نه ڪيو وڃي ۽ ايپليڪيشن ڊولپر کي سسٽم جي تعميراتي نظارن جي خاصيتن کي ڳولڻ جي ضرورت کان بچايو وڃي. ھن طريقي سان ڪيترائي فائدا آھن، پر عملي طور تي ان جي غير موثريت ڏيکاري ٿو:

  • انضمام جي مسئلن کي حل ڪرڻ عام طور تي آسان اختيارن ڏانهن واپس اچي ٿو هم وقت ساز ڪالن جي صورت ۾ مکيه ڪم فلو جي عمل ۾ محدود توسيع پوائنٽن جي ڪري (هم وقت سازي جي انضمام جي نقصانن تي بحث ڪيو ويو آهي)؛
  • انضمام جا نمونا اڃا تائين بنيادي ڪاروباري منطق ۾ داخل ٿين ٿا جڏهن ٻئي سب سسٽم کان موٽ گهربل هجي؛
  • ايپليڪيشن ڊولپر انضمام کي نظر انداز ڪري ٿو ۽ آساني سان ان کي ٽوڙي سگھي ٿو ڪم فلو کي تبديل ڪندي؛
  • صارف جي نقطي نظر کان سسٽم هڪ مڪمل ٿيڻ بند ڪري ٿو، سب سسٽم جي وچ ۾ "سيمس" قابل ذڪر ٿي ويندا آهن، ۽ غير ضروري صارف آپريشن ظاهر ٿيندا آهن، ڊيٽا جي منتقلي جي شروعات هڪ سب سسٽم کان ٻئي ڏانهن.

هڪ ٻيو طريقو اهو آهي ته انضمام جي ڳالهين کي بنيادي ڪاروباري منطق ۽ ڪم جي فلو جو هڪ لازمي حصو سمجهيو وڃي. ايپليڪيشن ڊولپر جي قابليت کي تيز ٿيڻ کان روڪڻ لاءِ، نئين انٽيگريشن رابطي کي ٺاهڻ آسان ۽ آسان هجڻ گهرجي، حل چونڊڻ لاءِ گهٽ ۾ گهٽ اختيارن سان. اهو ڪم ڪرڻ کان وڌيڪ ڏکيو آهي اهو لڳي ٿو: اوزار ڪافي طاقتور هجڻ گهرجي ته صارف کي ان جي استعمال لاء گهربل مختلف قسم جي اختيارن سان مهيا ڪري، هن کي اجازت ڏيڻ جي بغير "پاڻ کي پيرن ۾ گولي." اهڙا ڪيترائي سوال آهن جن جو جواب هڪ انجنيئر کي انضمام جي ڪمن جي حوالي سان لازمي آهي، پر جيڪو هڪ ايپليڪيشن ڊولپر کي پنهنجي روزاني ڪم ۾ نه سوچڻ گهرجي: ٽرانزيڪشن جون حدون، استحڪام، ايٽمي، سيڪيورٽي، اسڪيلنگ، لوڊ ۽ وسيلن جي ورڇ، روٽنگ، مارشلنگ، تقسيم ۽ مٽائڻ جي حوالي سان، وغيره. اهو ضروري آهي ته ايپليڪيشن ڊولپرز کي پيش ڪرڻ لاء ڪافي سادو حل ٽيمپليٽس جن ۾ اهڙن سڀني سوالن جا جواب اڳ ۾ ئي لڪيل آهن. اهي ٽيمپليٽس لازمي طور تي محفوظ هجڻ گهرجن: ڪاروباري منطق گهڻو ڪري تبديل ٿينديون آهن، جيڪي غلطيون متعارف ڪرائڻ جو خطرو وڌائينديون آهن، غلطين جي قيمت تمام گهٽ سطح تي رهڻ گهرجي.

پر BPM کي ان سان ڇا ڪرڻو آهي؟ ڪم جي فلو کي لاڳو ڪرڻ لاء ڪيترائي اختيار آهن ...
درحقيقت، ڪاروباري عملن جو هڪ ٻيو عمل اسان جي حلن ۾ تمام گهڻو مشهور آهي - هڪ رياستي منتقلي ڊراگرام جي بياناتي تعريف ۽ ٽرانزيڪشن لاءِ ڪاروباري منطق سان هينڊلر جي ڪنيڪشن ذريعي. انهي صورت ۾، رياست جيڪو ڪاروبار جي عمل ۾ "دستاويز" جي موجوده پوزيشن کي طئي ڪري ٿو، اهو خود "دستاويز" جي هڪ خاصيت آهي.

BPM انداز انضمام
اھو اھو آھي جيڪو عمل ھڪڙي منصوبي جي شروعات ۾ ڏسڻ ۾ اچي ٿو

هن عمل درآمد جي مقبوليت جي سبب آهي نسبتا سادگي ۽ سڌر ڪاروباري عمل ٺاهڻ جي رفتار. بهرحال، جيئن سافٽ ويئر سسٽم مسلسل وڌيڪ پيچيده ٿي ويندا آهن، ڪاروباري عمل جو خودڪار حصو وڌندو آهي ۽ وڌيڪ پيچيده ٿي ويندو آهي. ضرورت آهي ته ڊمپوزيشن، پروسيس جي حصن کي ٻيهر استعمال ڪرڻ، انهي سان گڏ برانچنگ جي عملن جي ته جيئن هر شاخ کي متوازي طور تي عمل ڪيو وڃي. اهڙين حالتن ۾، اوزار مشڪل ٿي ويندو آهي، ۽ رياست جي منتقلي ڊراگرام پنهنجي معلوماتي مواد کي وڃائي ڇڏيندو آهي (انضمام جي وچ ۾ لاڳاپا مڪمل طور تي ڊراگرام ۾ ظاهر نه ٿيندا آهن).

BPM انداز انضمام
اهو اهو آهي جيڪو عمل جي ضرورتن جي وضاحت جي ڪيترن ئي ورهاڱي کان پوء ڏسڻ ۾ اچي ٿو.

هن صورتحال مان نڪرڻ جو طريقو انجڻ جي انضمام هو جي بي پي ايم ڪجھ پراڊڪٽس ۾ سڀ کان وڌيڪ پيچيده ڪاروباري عملن سان. مختصر مدت ۾، هن حل ۾ ڪجهه ڪاميابي هئي: اهو ممڪن ٿيو ته پيچيده ڪاروباري عملن کي لاڳو ڪرڻ، جڏهن ته نوٽيفڪيشن ۾ ڪافي معلوماتي ۽ لاڳاپيل آريگرام برقرار رکندي. بي پي ايم اين 2.

BPM انداز انضمام
ھڪڙي پيچيده ڪاروباري عمل جو ھڪڙو ننڍڙو حصو

ڊگھي مدت ۾، حل اميدن تي پورو نه ٿيو: بصري اوزار جي ذريعي ڪاروباري عملن کي ٺاهڻ جي اعلي محنت جي شدت قابل قبول پيداوار جي اشارن کي حاصل ڪرڻ جي اجازت نه ڏني، ۽ اوزار پاڻ ڊولپرز جي وچ ۾ سڀ کان وڌيڪ ناپسنديده بڻجي ويو. انجڻ جي اندروني ڍانچي جي باري ۾ به شڪايتون آهن، جنهن جي ڪيترن ئي "پيچ" ۽ "crutches" جي ظهور جو سبب بڻيا.

jBPM استعمال ڪرڻ جو بنيادي مثبت پاسو ڪاروبار عمل جي مثال جي پنهنجي مستقل حالت جي فائدن ۽ نقصانن جي آگاهي هئي. اسان مختلف ايپليڪيشنن جي وچ ۾ پيچيدگي انضمام پروٽوڪول کي لاڳو ڪرڻ لاء پروسيس جي طريقيڪار کي استعمال ڪرڻ جو امڪان پڻ ڏٺو آهي سگنلن ۽ پيغامن ذريعي غير مطابقت واري رابطي کي استعمال ڪندي. مستقل رياست جي موجودگي ان ۾ اهم ڪردار ادا ڪري ٿي.

مٿين بنيادن تي، اسان نتيجو ڪري سگھون ٿا: BPM انداز ۾ عمل جو طريقو اسان کي ڪمن جي وسيع رينج کي حل ڪرڻ جي اجازت ڏئي ٿو وڌندڙ پيچيده ڪاروباري عملن کي خودڪار ڪرڻ لاءِ، انهن عملن ۾ هم آهنگيءَ سان انضمام جي سرگرمين کي ترتيب ڏيڻ ۽ قابليت کي برقرار رکڻ جي قابليت کي برقرار رکڻ لاءِ لاڳو ٿيل عمل کي مناسب نوٽيشن ۾ ڏسڻ ۾.

انضمام جي نموني جي طور تي هم وقت سازي ڪالن جا نقصان

هم وقت سازي انضمام آسان ترين بلاڪنگ ڪال ڏانهن اشارو ڪري ٿو. ھڪڙو سب سسٽم ڪم ڪري ٿو سرور جي پاسي ۽ API کي گهربل طريقي سان بي نقاب ڪري ٿو. ٻيو سب سسٽم ڪلائنٽ سائڊ طور ڪم ڪري ٿو ۽ صحيح وقت تي ڪال ڪري ٿو ۽ نتيجو جو انتظار ڪري ٿو. سسٽم جي فن تعمير تي مدار رکندي، ڪلائنٽ ۽ سرور جا پاسا يا ته ساڳي ايپليڪيشن ۽ پروسيس ۾، يا مختلف ۾ واقع ٿي سگهن ٿا. ٻي صورت ۾، توهان کي ڪجهه RPC لاڳو ڪرڻ جي ضرورت آهي ۽ پيٽرولن جي مارشلنگ ۽ ڪال جو نتيجو مهيا ڪرڻ جي ضرورت آهي.

BPM انداز انضمام

هن انضمام جي نموني ۾ ڪافي نقصانن جو هڪ وڏو سيٽ آهي، پر ان جي سادگي جي ڪري عملي طور تي استعمال ڪيو ويندو آهي. عمل درآمد جي رفتار موهيندڙ ٿي ۽ مجبور ڪري ٿي ته توهان ان کي بار بار استعمال ڪرڻ جي لاءِ آخري حدن کي دٻائڻ جي صورت ۾، حل کي ٽيڪنيڪل قرض طور رڪارڊ ڪيو. پر اهو پڻ ٿئي ٿو ته اڻڄاتل ڊولپرز ان کي غير شعوري طور تي استعمال ڪن ٿا، صرف منفي نتيجن کي محسوس نه ڪن.

سبسسٽم رابطي ۾ سڀ کان وڌيڪ واضح اضافو کان علاوه، "وڌندڙ" ۽ "وڌيڪ" ٽرانزيڪشن سان پڻ گهٽ واضح مسئلا آهن. درحقيقت، جيڪڏهن ڪاروباري منطق ڪجهه تبديليون آڻيندي، پوء ٽرانزيڪشن کان بچي نه ٿو سگهجي، ۽ ٽرانزيڪشن، موڙ ۾، انهن تبديلين کان متاثر ٿيل ڪجهه ايپليڪيشن وسيلن کي بلاڪ ڪري ٿو. اهو آهي، جيستائين هڪ سب سسٽم ٻئي کان جواب جو انتظار ڪري، اهو ٽرانزيڪشن کي مڪمل ڪرڻ ۽ تالا کي هٽائڻ جي قابل نه هوندو. اهو خاص طور تي مختلف اثرات جي خطري کي وڌائي ٿو:

  • سسٽم جي ردعمل گم ٿي وئي آهي، صارفين سوالن جي جوابن لاء هڪ ڊگهو وقت انتظار ڪندا آهن؛
  • سرور عام طور تي صارف جي درخواستن جو جواب ڏيڻ بند ڪري ٿو ھڪڙي گھڻائي واري ٿريڊ پول جي ڪري: ٿريڊز جي اڪثريت ھڪڙي ٽرانزيڪشن تي قبضو ڪيل وسيلن تي بند ٿيل آھن؛
  • Deadlocks ظاهر ٿيڻ شروع ٿي ويا آهن: انهن جي واقعن جو امڪان گهڻو ڪري ٽرانزيڪشن جي مدت تي منحصر آهي، ڪاروباري منطق جي مقدار ۽ ٽرانزيڪشن ۾ شامل تالا؛
  • ٽرانزيڪشن جي وقت ختم ٿيڻ واريون غلطيون ظاهر ٿين ٿيون؛
  • سرور OutOfMemory سان ”ناڪام“ ٿي وڃي ٿو جيڪڏهن ڪم کي پروسيسنگ ۽ ڊيٽا جي وڏي مقدار کي تبديل ڪرڻ جي ضرورت آهي، ۽ هم وقت سازي انضمام جي موجودگي پروسيسنگ کي ”لائيٽ“ ٽرانزيڪشن ۾ ورهائڻ تمام ڏکيو بڻائي ٿي.

تعميراتي نقطي نظر کان، انضمام دوران بلاڪنگ ڪالن جو استعمال انفرادي سب سسٽم جي معيار تي ڪنٽرول جي نقصان جي ڪري ٿي: اهو ناممڪن آهي ته هڪ سب سسٽم جي ٽارگيٽ معيار جي اشارن کي ٻئي سب سسٽم جي معيار جي اشارن کان الڳ ڪرڻ ۾. جيڪڏهن سب سسٽم مختلف ٽيمن پاران ترقي ڪئي وئي آهي، اهو هڪ وڏو مسئلو آهي.

شيون اڃا به وڌيڪ دلچسپ ٿي وڃن ٿيون جيڪڏهن سب سسٽم ضم ٿي رهيا آهن مختلف ايپليڪيشنن ۾ ۽ توهان کي ٻنهي پاسن تي هم وقت سازي تبديليون ڪرڻ جي ضرورت آهي. انهن تبديلين جي ٽرانزيڪشن کي ڪيئن يقيني بڻايو وڃي؟

جيڪڏهن تبديليون الڳ الڳ ٽرانزيڪشن ۾ ڪيون وينديون آهن، ته پوء توهان کي قابل اعتماد استثنا فراهم ڪرڻ جي ضرورت پوندي ۽ معاوضو، ۽ اهو مڪمل طور تي هم وقت سازي انضمام جي بنيادي فائدي کي ختم ڪري ٿو - سادگي.

ورهايل ٽرانزيڪشن پڻ ذهن ۾ اچن ٿا، پر اسان انهن کي اسان جي حل ۾ استعمال نه ڪندا آهيون: اهو اعتماد کي يقيني بڻائڻ ڏکيو آهي.

"ساگا" ٽرانزيڪشن جي مسئلي جي حل جي طور تي

microservices جي وڌندڙ مقبوليت سان، جي طلب ساگا نموني.

اهو نمونو مڪمل طور تي ڊگهي ٽرانزيڪشن جي مٿين مسئلن کي حل ڪري ٿو، ۽ ڪاروباري منطق جي پاسي کان سسٽم جي حالت کي منظم ڪرڻ جي صلاحيتن کي پڻ وڌائي ٿو: هڪ ناڪام ٽرانزيڪشن کان پوء معاوضو شايد سسٽم کي ان جي اصل حالت ڏانهن واپس نه آڻي، پر مهيا ڪري ٿو. هڪ متبادل ڊيٽا پروسيسنگ رستو. اهو توهان کي ڪاميابي سان مڪمل ٿيل ڊيٽا پروسيسنگ مرحلن کي ورجائڻ کان پاسو ڪرڻ جي اجازت ڏئي ٿو جڏهن پروسيس کي ”سٺو“ پڄاڻي تي آڻڻ جي ڪوشش ڪئي وڃي.

دلچسپ ڳالهه اها آهي ته، monolithic سسٽم ۾ اهو نمونو ان وقت به لاڳاپيل هوندو آهي جڏهن اهو ٿلهي سان ملندڙ سب سسٽم جي انضمام تي اچي ٿو ۽ ڊگھي عرصي تائين هلندڙ ٽرانزيڪشن ۽ لاڳاپيل وسيلن جي تالان جي ڪري ناڪاري اثرن جو مشاهدو ڪيو وڃي ٿو.

BPM انداز ۾ اسان جي ڪاروباري عملن جي حوالي سان، ”ساگاس“ کي لاڳو ڪرڻ بلڪل آسان ثابت ٿيو آهي: ”ساگا“ جا انفرادي قدم ڪاروباري عمل جي اندر سرگرمين جي طور تي بيان ڪري سگھجن ٿا، ۽ ڪاروباري عمل جي مسلسل حالت پڻ. "ساگا" جي اندروني حالت کي طئي ڪري ٿو. اهو آهي، اسان کي ڪنهن به اضافي ڪوآرڊينيشن ميڪانيزم جي ضرورت ناهي. توهان کي صرف هڪ پيغام بروکر جي ضرورت آهي جيڪا "گهٽ ۾ گهٽ هڪ ڀيرو" ٽرانسپورٽ جي ضمانت جي حمايت ڪري ٿي.

پر اهو حل پڻ پنهنجي "قيمت" آهي:

  • ڪاروباري منطق وڌيڪ پيچيده ٿي ويندي آهي: معاوضي تي ڪم ڪرڻ جي ضرورت آهي؛
  • اهو ضروري آهي ته مڪمل استحڪام کي ڇڏي ڏيو، جيڪو خاص طور تي monolithic سسٽم لاء حساس ٿي سگهي ٿو؛
  • فن تعمير ٿورو وڌيڪ پيچيده ٿي ويندو آهي، ۽ هڪ پيغام بروکر جي اضافي ضرورت ظاهر ٿئي ٿي؛
  • اضافي نگراني ۽ انتظامي اوزارن جي ضرورت پوندي (جيتوڻيڪ عام طور تي اھو سٺو آھي: سسٽم سروس جو معيار وڌندو).

monolithic نظام لاء، "Sag" استعمال ڪرڻ جو جواز ايترو واضح نه آهي. مائڪرو سروسز ۽ ٻين SOA لاءِ، جتي گهڻو ڪري اڳ ۾ ئي هڪ بروکر موجود آهي، ۽ پروجيڪٽ جي شروعات ۾ مڪمل استحڪام قربان ڪيو ويندو آهي، هن نموني کي استعمال ڪرڻ جا فائدا وڏي پئماني تي نقصانن کان وڌي سگهن ٿا، خاص طور تي جيڪڏهن ڪاروباري منطق تي هڪ آسان API آهي. سطح

مائڪرو سروسز ۾ ڪاروباري منطق کي گڏ ڪرڻ

جڏهن اسان microservices سان تجربا ڪرڻ شروع ڪيو، هڪ معقول سوال پيدا ٿيو: ڊومين جي ڪاروباري منطق کي ڪٿي رکڻو آهي خدمت جي سلسلي ۾ جيڪو ڊومين ڊيٽا جي تسلسل کي يقيني بڻائي ٿو؟

جڏهن مختلف BPMSs جي فن تعمير کي ڏسندي، اهو مناسب لڳي سگھي ٿو ته ڪاروباري منطق کي استقامت کان الڳ ڪرڻ: پليٽ فارم ۽ ڊومين-آزاد مائڪرو سروسز جو هڪ پرت ٺاهيو جيڪو هڪ ماحول ۽ ڪنٽينر ٺاهي ٿو ڊومين ڪاروباري منطق تي عمل ڪرڻ لاءِ، ۽ ڊومين ڊيٽا جي تسلسل کي ترتيب ڏيو جيئن تمام سادو ۽ هلڪو وزن مائڪرو سروسز جو هڪ الڳ پرت. هن معاملي ۾ ڪاروباري عمل مسلسل پرت جي خدمتن جي آرڪيسٽريشن کي انجام ڏئي ٿو.

BPM انداز انضمام

هن طريقي سان هڪ تمام وڏو فائدو آهي: توهان پليٽ فارم جي ڪارڪردگي کي وڌائي سگهو ٿا جيترو توهان چاهيو، ۽ صرف پليٽ فارم مائڪرو سروسز جي لاڳاپيل پرت هن مان "ٿلهي" ٿي ويندي. ڪنهن به ڊومين مان ڪاروباري عمل فوري طور تي پليٽ فارم جي نئين ڪارڪردگي کي استعمال ڪرڻ جي قابل هوندا آهن جيئن ئي اپڊيٽ ڪيو ويندو آهي.

هڪ وڌيڪ تفصيلي اڀياس هن طريقي جي اهم نقصانات کي ظاهر ڪيو:

  • هڪ پليٽ فارم سروس جيڪا ڪيترن ئي ڊومينز جي ڪاروباري منطق کي هڪ ئي وقت تي عمل ڪري ٿي ناڪامي جي هڪ واحد نقطي جي طور تي وڏو خطرو کڻندي آهي. ڪاروباري منطق ۾ بار بار تبديليون غلطين جو خطرو وڌائين ٿيون جيڪي سسٽم جي وڏين ناڪامين جي ڪري.
  • ڪارڪردگي جا مسئلا: ڪاروباري منطق ان جي ڊيٽا سان گڏ هڪ تنگ ۽ سست انٽرفيس ذريعي ڪم ڪري ٿو:
    • ڊيٽا کي هڪ ڀيرو ٻيهر مارشل ڪيو ويندو ۽ نيٽ ورڪ اسٽيڪ ذريعي پمپ ڪيو ويندو؛
    • هڪ ڊومين سروس اڪثر ڪري وڌيڪ ڊيٽا فراهم ڪندي جنهن جي عمل لاءِ ڪاروباري منطق لاءِ گهربل آهي ڇاڪاڻ ته خدمت جي خارجي API جي سطح تي درخواستن کي پيرا ميٽرائيز ڪرڻ لاءِ ناکافي صلاحيتون؛
    • ڪاروباري منطق جا ڪيترائي آزاد ٽڪرا بار بار ساڳئي ڊيٽا کي پروسيسنگ لاءِ ٻيهر گذارش ڪري سگھن ٿا (اهو مسئلو سيشن اجزاء شامل ڪري گھٽائي سگهجي ٿو جيڪي ڊيٽا کي ڪيش ڪن ٿا، پر اهو آرڪيٽيڪچر کي وڌيڪ پيچيده ڪري ٿو ۽ ڊيٽا جي مطابقت ۽ ڪيش جي غلطيءَ جا مسئلا پيدا ڪري ٿو)؛
  • واپار جا مسئلا:
    • مسلسل رياست سان ڪاروباري عمل، جيڪو هڪ پليٽ فارم سروس طرفان محفوظ ڪيو ويو آهي، ڊومين ڊيٽا سان متضاد آهن، ۽ هن مسئلي کي حل ڪرڻ لاء ڪي آسان طريقا نه آهن؛
    • ڊومين ڊيٽا کي ٽرانزيڪشن کان ٻاهر بلاڪ ڪرڻ: جيڪڏهن ڊومين ڪاروبار منطق کي تبديل ڪرڻ جي ضرورت آهي پهرين موجوده ڊيٽا جي صحيحيت جي جانچ ڪرڻ کان پوء، اهو ضروري آهي ته پروسيس ٿيل ڊيٽا ۾ مقابلي واري تبديلي جي امڪان کي خارج ڪرڻ لاء. خارجي ڊيٽا کي بلاڪ ڪرڻ مسئلو حل ڪرڻ ۾ مدد ڪري سگهي ٿو، پر اهو حل اضافي خطرن کي کڻندو آهي ۽ سسٽم جي مجموعي اعتبار کي گھٽائي ٿو؛
  • تازه ڪاري ڪرڻ وقت اضافي مشڪلاتون: ڪجهه حالتن ۾، مسلسل خدمت ۽ ڪاروباري منطق کي هم وقت سازي يا سخت ترتيب ۾ اپڊيٽ ڪرڻ جي ضرورت آهي.

بالآخر، اسان کي واپس وڃڻو پوندو بنياديات: ڊومين ڊيٽا ۽ ڊومين ڪاروباري منطق کي هڪ مائڪرو سروس ۾ شامل ڪريو. اهو طريقو هڪ microservice جي تصور کي سسٽم جي هڪ لازمي جزو جي طور تي آسان بڻائي ٿو ۽ مٿين مسئلن کي جنم نٿو ڏئي. اهو پڻ مفت ۾ نه ڏنو ويو آهي:

  • ڪاروباري منطق سان رابطي لاءِ API معيار جي ضرورت آهي (خاص طور تي، صارف جي سرگرمين کي ڪاروباري عملن جي حصي طور مهيا ڪرڻ) ۽ API پليٽ فارم سروسز؛ API تبديلين تي وڌيڪ ڌيان ڏيڻ جي ضرورت آهي، اڳتي ۽ پوئتي مطابقت؛
  • اهو ضروري آهي ته اضافي رن ٽائم لائبريريون شامل ڪيون وڃن ته جيئن ڪاروباري منطق جي ڪارڪردگي کي يقيني بڻائي سگهجي ته جيئن هر هڪ مائڪرو سروس جي حصي جي طور تي، ۽ اهو اهڙن لائبريرين لاء نئين گهرجن کي جنم ڏئي ٿو: روشني ۽ گهٽ ۾ گهٽ منتقلي انحصار؛
  • ڪاروباري منطق ڊولپرز کي لائبريري ورزن جي نگراني ڪرڻ جي ضرورت آهي: جيڪڏهن هڪ microservice ڊگهي عرصي تائين حتمي نه ڪئي وئي آهي، ته پوء گهڻو ڪري ان ۾ لائبريرين جو هڪ پراڻو نسخو هوندو. اهو هڪ نئين خصوصيت شامل ڪرڻ ۾ اڻڄاتل رڪاوٽ ٿي سگهي ٿو ۽ ٿي سگهي ٿو اهڙي خدمت جي پراڻي ڪاروباري منطق کي لڏڻ جي ضرورت هجي لائبريرين جي نئين نسخن ڏانهن جيڪڏهن نسخن جي وچ ۾ غير مطابقت رکندڙ تبديليون هجن.

BPM انداز انضمام

پليٽ فارم سروسز جو هڪ پرت پڻ اهڙي فن تعمير ۾ موجود آهي، پر هي پرت هاڻي ڊومين ڪاروباري منطق کي هلائڻ لاءِ ڪنٽينر نه ٺاهيندي آهي، پر صرف ان جو ماحول، معاون ”پليٽفارم“ افعال مهيا ڪندي آهي. اهڙي پرت جي ضرورت آهي نه رڳو ڊومين مائڪرو سروسز جي هلڪي وزن واري طبيعت کي برقرار رکڻ لاءِ، پر انتظاميا کي مرڪزي ڪرڻ لاءِ.

مثال طور، ڪاروباري عملن ۾ صارف سرگرميون ڪم پيدا ڪن ٿيون. جڏهن ته، ڪمن سان ڪم ڪرڻ وقت، صارف کي عام فهرست ۾ سڀني ڊومينز مان ڪم ڏسڻ گهرجي، جنهن جو مطلب آهي ته اتي هڪ لاڳاپيل پليٽ فارم ٽاسڪ رجسٽريشن سروس هجڻ گهرجي، ڊومين ڪاروباري منطق کان صاف. اهڙي حوالي سان ڪاروباري منطق جي انڪشاف کي برقرار رکڻ ڪافي مشڪل آهي، ۽ اهو هن فن تعمير جو هڪ ٻيو سمجھوتو آهي.

ايپليڪيشن ڊولپر جي اکين ذريعي ڪاروباري عملن جو انضمام

جيئن مٿي ذڪر ڪيو ويو آهي، هڪ ايپليڪيشن ڊولپر کي لازمي طور تي ڪيترن ئي ايپليڪيشنن جي رابطي کي لاڳو ڪرڻ جي ٽيڪنيڪل ۽ انجنيئرنگ خاصيتن کان هٽايو وڃي ته جيئن هڪ سٺي ترقي جي پيداوار تي شمار ڪري سگهي.

اچو ته هڪ بلڪه ڏکيو انضمام جي مسئلي کي حل ڪرڻ جي ڪوشش ڪريون، خاص طور تي آرٽيڪل لاء ٺاهيل. هي هڪ "راند" جو ڪم هوندو جنهن ۾ ٽي ايپليڪيشنون شامل آهن، جتي انهن مان هر هڪ مخصوص ڊومين جو نالو بيان ڪري ٿو: "app1"، "app2"، "app3".

هر ايپليڪيشن جي اندر، ڪاروباري عمل شروع ڪيا ويا آهن جيڪي شروع ڪن ٿا "بال کي راند" انٽيگريشن بس ذريعي. "بال" نالي سان پيغام هڪ بال طور ڪم ڪندو.

راندين جا ضابطا:

  • پهريون پليئر شروعات ڪندڙ آهي. هو ٻين رانديگرن کي راند ۾ دعوت ڏئي ٿو، راند کي شروع ڪري ٿو ۽ ڪنهن به وقت ختم ڪري سگهي ٿو؛
  • ٻيا رانديگر راند ۾ سندن شموليت جو اعلان ڪن ٿا، ”ڄاڻڻ“ ھڪ ٻئي ۽ پھرين رانديگر کي؛
  • بال حاصل ڪرڻ کان پوء، پليئر هڪ ٻيو حصو وٺندڙ رانديگر کي چونڊيندو آهي ۽ هن کي بال پاس ڪري ٿو. ٽرانسميشن جو ڪل تعداد شمار ڪيو ويو آهي؛
  • هر پليئر وٽ ”توانائي“ هوندي آهي جيڪا ان رانديگر طرفان بال جي هر پاس سان گهٽجي ويندي آهي. جڏهن توانائي ختم ٿئي ٿي، پليئر راند کي ڇڏي، پنهنجي استعيفي جو اعلان ڪندي؛
  • جيڪڏهن پليئر اڪيلو ڇڏي ويو آهي، هو فوري طور تي پنهنجي روانگي جو اعلان ڪري ٿو؛
  • جڏهن سڀئي رانديگر ختم ٿي ويا آهن، پهريون رانديگر راند ختم ٿيڻ جو اعلان ڪري ٿو. جيڪڏهن هو راند کي جلدي ڇڏي ٿو، هو ان کي مڪمل ڪرڻ لاء راند جي پيروي ڪرڻ لاء رهي ٿو.

هن مسئلي کي حل ڪرڻ لاء، مان اسان جي ڊي ايس ايل کي ڪاروباري عملن لاء استعمال ڪندس، جيڪو اسان کي اجازت ڏئي ٿو ڪوٽلن ۾ منطق کي بيان ڪرڻ لاء، گهٽ ۾ گهٽ بوائلر پليٽ سان.

پهرين پليئر جو ڪاروباري عمل (اڪا راند جو شروعات ڪندڙ) ايپ 1 ايپليڪيشن ۾ ڪم ڪندو:

ڪلاس شروعاتي پليئر

import ru.krista.bpm.ProcessInstance
import ru.krista.bpm.runtime.ProcessImpl
import ru.krista.bpm.runtime.constraint.UniqueConstraints
import ru.krista.bpm.runtime.dsl.processModel
import ru.krista.bpm.runtime.dsl.taskOperation
import ru.krista.bpm.runtime.instance.MessageSendInstance

data class PlayerInfo(val name: String, val domain: String, val id: String)

class PlayersList : ArrayList<PlayerInfo>()

// Это класс экземпляра процесса: инкапсулирует его внутреннее состояние
class InitialPlayer : ProcessImpl<InitialPlayer>(initialPlayerModel) {
    var playerName: String by persistent("Player1")
    var energy: Int by persistent(30)
    var players: PlayersList by persistent(PlayersList())
    var shotCounter: Int = 0
}

// Это декларация модели процесса: создается один раз, используется всеми
// экземплярами процесса соответствующего класса
val initialPlayerModel = processModel<InitialPlayer>(name = "InitialPlayer",
                                                     version = 1) {

    // По правилам, первый игрок является инициатором игры и должен быть единственным
    uniqueConstraint = UniqueConstraints.singleton

    // Объявляем активности, из которых состоит бизнес-процесс
    val sendNewGameSignal = signal<String>("NewGame")
    val sendStopGameSignal = signal<String>("StopGame")
    val startTask = humanTask("Start") {
        taskOperation {
            processCondition { players.size > 0 }
            confirmation { "Подключилось ${players.size} игроков. Начинаем?" }
        }
    }
    val stopTask = humanTask("Stop") {
        taskOperation {}
    }
    val waitPlayerJoin = signalWait<String>("PlayerJoin") { signal ->
        players.add(PlayerInfo(
                signal.data!!,
                signal.sender.domain,
                signal.sender.processInstanceId))
        println("... join player ${signal.data} ...")
    }
    val waitPlayerOut = signalWait<String>("PlayerOut") { signal ->
        players.remove(PlayerInfo(
                signal.data!!,
                signal.sender.domain,
                signal.sender.processInstanceId))
        println("... player ${signal.data} is out ...")
    }
    val sendPlayerOut = signal<String>("PlayerOut") {
        signalData = { playerName }
    }
    val sendHandshake = messageSend<String>("Handshake") {
        messageData = { playerName }
        activation = {
            receiverDomain = process.players.last().domain
            receiverProcessInstanceId = process.players.last().id
        }
    }
    val throwStartBall = messageSend<Int>("Ball") {
        messageData = { 1 }
        activation = { selectNextPlayer() }
    }
    val throwBall = messageSend<Int>("Ball") {
        messageData = { shotCounter + 1 }
        activation = { selectNextPlayer() }
        onEntry { energy -= 1 }
    }
    val waitBall = messageWaitData<Int>("Ball") {
        shotCounter = it
    }

    // Теперь конструируем граф процесса из объявленных активностей
    startFrom(sendNewGameSignal)
            .fork("mainFork") {
                next(startTask)
                next(waitPlayerJoin).next(sendHandshake).next(waitPlayerJoin)
                next(waitPlayerOut)
                        .branch("checkPlayers") {
                            ifTrue { players.isEmpty() }
                                    .next(sendStopGameSignal)
                                    .terminate()
                            ifElse().next(waitPlayerOut)
                        }
            }
    startTask.fork("afterStart") {
        next(throwStartBall)
                .branch("mainLoop") {
                    ifTrue { energy < 5 }.next(sendPlayerOut).next(waitBall)
                    ifElse().next(waitBall).next(throwBall).loop()
                }
        next(stopTask).next(sendStopGameSignal)
    }

    // Навешаем на активности дополнительные обработчики для логирования
    sendNewGameSignal.onExit { println("Let's play!") }
    sendStopGameSignal.onExit { println("Stop!") }
    sendPlayerOut.onExit { println("$playerName: I'm out!") }
}

private fun MessageSendInstance<InitialPlayer, Int>.selectNextPlayer() {
    val player = process.players.random()
    receiverDomain = player.domain
    receiverProcessInstanceId = player.id
    println("Step ${process.shotCounter + 1}: " +
            "${process.playerName} >>> ${player.name}")
}

ڪاروباري منطق تي عمل ڪرڻ کان علاوه، مٿي ڏنل ڪوڊ ڪاروباري عمل جو هڪ اعتراض ماڊل پيدا ڪري سگهي ٿو، جنهن کي ڊاگرام جي صورت ۾ ڏسي سگهجي ٿو. اسان اڃان تائين visualizer تي عمل نه ڪيو آهي، ان ڪري اسان کي ان کي ڊرائنگ ڪرڻ ۾ ٿورو وقت گذارڻو پيو (هتي مون BPMN نوٽشن کي ٿورو آسان ڪيو آهي گيٽس جي استعمال جي حوالي سان ڏنل ڪوڊ سان ڊاگرام جي تسلسل کي بهتر ڪرڻ لاءِ):

BPM انداز انضمام

app2 ۾ شامل ٿيندو ٻئي پليئر جي ڪاروباري عمل:

ڪلاس RandomPlayer

import ru.krista.bpm.ProcessInstance
import ru.krista.bpm.runtime.ProcessImpl
import ru.krista.bpm.runtime.dsl.processModel
import ru.krista.bpm.runtime.instance.MessageSendInstance

data class PlayerInfo(val name: String, val domain: String, val id: String)

class PlayersList: ArrayList<PlayerInfo>()

class RandomPlayer : ProcessImpl<RandomPlayer>(randomPlayerModel) {

    var playerName: String by input(persistent = true, 
                                    defaultValue = "RandomPlayer")
    var energy: Int by input(persistent = true, defaultValue = 30)
    var players: PlayersList by persistent(PlayersList())
    var allPlayersOut: Boolean by persistent(false)
    var shotCounter: Int = 0

    val selfPlayer: PlayerInfo
        get() = PlayerInfo(playerName, env.eventDispatcher.domainName, id)
}

val randomPlayerModel = processModel<RandomPlayer>(name = "RandomPlayer", 
                                                   version = 1) {

    val waitNewGameSignal = signalWait<String>("NewGame")
    val waitStopGameSignal = signalWait<String>("StopGame")
    val sendPlayerJoin = signal<String>("PlayerJoin") {
        signalData = { playerName }
    }
    val sendPlayerOut = signal<String>("PlayerOut") {
        signalData = { playerName }
    }
    val waitPlayerJoin = signalWaitCustom<String>("PlayerJoin") {
        eventCondition = { signal ->
            signal.sender.processInstanceId != process.id 
                && !process.players.any { signal.sender.processInstanceId == it.id}
        }
        handler = { signal ->
            players.add(PlayerInfo(
                    signal.data!!,
                    signal.sender.domain,
                    signal.sender.processInstanceId))
        }
    }
    val waitPlayerOut = signalWait<String>("PlayerOut") { signal ->
        players.remove(PlayerInfo(
                signal.data!!,
                signal.sender.domain,
                signal.sender.processInstanceId))
        allPlayersOut = players.isEmpty()
    }
    val sendHandshake = messageSend<String>("Handshake") {
        messageData = { playerName }
        activation = {
            receiverDomain = process.players.last().domain
            receiverProcessInstanceId = process.players.last().id
        }
    }
    val receiveHandshake = messageWait<String>("Handshake") { message ->
        if (!players.any { message.sender.processInstanceId == it.id}) {
            players.add(PlayerInfo(
                    message.data!!, 
                    message.sender.domain, 
                    message.sender.processInstanceId))
        }
    }
    val throwBall = messageSend<Int>("Ball") {
        messageData = { shotCounter + 1 }
        activation = { selectNextPlayer() }
        onEntry { energy -= 1 }
    }
    val waitBall = messageWaitData<Int>("Ball") {
        shotCounter = it
    }

    startFrom(waitNewGameSignal)
            .fork("mainFork") {
                next(sendPlayerJoin)
                        .branch("mainLoop") {
                            ifTrue { energy < 5 || allPlayersOut }
                                    .next(sendPlayerOut)
                                    .next(waitBall)
                            ifElse()
                                    .next(waitBall)
                                    .next(throwBall)
                                    .loop()
                        }
                next(waitPlayerJoin).next(sendHandshake).next(waitPlayerJoin)
                next(waitPlayerOut).next(waitPlayerOut)
                next(receiveHandshake).next(receiveHandshake)
                next(waitStopGameSignal).terminate()
            }

    sendPlayerJoin.onExit { println("$playerName: I'm here!") }
    sendPlayerOut.onExit { println("$playerName: I'm out!") }
}

private fun MessageSendInstance<RandomPlayer, Int>.selectNextPlayer() {
    val player = if (process.players.isNotEmpty()) 
        process.players.random() 
    else 
        process.selfPlayer
    receiverDomain = player.domain
    receiverProcessInstanceId = player.id
    println("Step ${process.shotCounter + 1}: " +
            "${process.playerName} >>> ${player.name}")
}

خاڪو:

BPM انداز انضمام

ايپ 3 ايپليڪيشن ۾ اسان هڪ رانديگر کي ٿورڙي مختلف رويي سان ٺاهينداسين: بي ترتيب طور تي ايندڙ رانديگر کي چونڊڻ جي بدران، هو گول رابن الگورتھم مطابق عمل ڪندو:

ڪلاس RoundRobinPlayer

import ru.krista.bpm.ProcessInstance
import ru.krista.bpm.runtime.ProcessImpl
import ru.krista.bpm.runtime.dsl.processModel
import ru.krista.bpm.runtime.instance.MessageSendInstance

data class PlayerInfo(val name: String, val domain: String, val id: String)

class PlayersList: ArrayList<PlayerInfo>()

class RoundRobinPlayer : ProcessImpl<RoundRobinPlayer>(roundRobinPlayerModel) {

    var playerName: String by input(persistent = true, 
                                    defaultValue = "RoundRobinPlayer")
    var energy: Int by input(persistent = true, defaultValue = 30)
    var players: PlayersList by persistent(PlayersList())
    var nextPlayerIndex: Int by persistent(-1)
    var allPlayersOut: Boolean by persistent(false)
    var shotCounter: Int = 0

    val selfPlayer: PlayerInfo
        get() = PlayerInfo(playerName, env.eventDispatcher.domainName, id)
}

val roundRobinPlayerModel = processModel<RoundRobinPlayer>(
        name = "RoundRobinPlayer", 
        version = 1) {

    val waitNewGameSignal = signalWait<String>("NewGame")
    val waitStopGameSignal = signalWait<String>("StopGame")
    val sendPlayerJoin = signal<String>("PlayerJoin") {
        signalData = { playerName }
    }
    val sendPlayerOut = signal<String>("PlayerOut") {
        signalData = { playerName }
    }
    val waitPlayerJoin = signalWaitCustom<String>("PlayerJoin") {
        eventCondition = { signal ->
            signal.sender.processInstanceId != process.id 
                && !process.players.any { signal.sender.processInstanceId == it.id}
        }
        handler = { signal ->
            players.add(PlayerInfo(
                    signal.data!!, 
                    signal.sender.domain, 
                    signal.sender.processInstanceId))
        }
    }
    val waitPlayerOut = signalWait<String>("PlayerOut") { signal ->
        players.remove(PlayerInfo(
                signal.data!!, 
                signal.sender.domain, 
                signal.sender.processInstanceId))
        allPlayersOut = players.isEmpty()
    }
    val sendHandshake = messageSend<String>("Handshake") {
        messageData = { playerName }
        activation = {
            receiverDomain = process.players.last().domain
            receiverProcessInstanceId = process.players.last().id
        }
    }
    val receiveHandshake = messageWait<String>("Handshake") { message ->
        if (!players.any { message.sender.processInstanceId == it.id}) {
            players.add(PlayerInfo(
                    message.data!!, 
                    message.sender.domain, 
                    message.sender.processInstanceId))
        }
    }
    val throwBall = messageSend<Int>("Ball") {
        messageData = { shotCounter + 1 }
        activation = { selectNextPlayer() }
        onEntry { energy -= 1 }
    }
    val waitBall = messageWaitData<Int>("Ball") {
        shotCounter = it
    }

    startFrom(waitNewGameSignal)
            .fork("mainFork") {
                next(sendPlayerJoin)
                        .branch("mainLoop") {
                            ifTrue { energy < 5 || allPlayersOut }
                                    .next(sendPlayerOut)
                                    .next(waitBall)
                            ifElse()
                                    .next(waitBall)
                                    .next(throwBall)
                                    .loop()
                        }
                next(waitPlayerJoin).next(sendHandshake).next(waitPlayerJoin)
                next(waitPlayerOut).next(waitPlayerOut)
                next(receiveHandshake).next(receiveHandshake)
                next(waitStopGameSignal).terminate()
            }

    sendPlayerJoin.onExit { println("$playerName: I'm here!") }
    sendPlayerOut.onExit { println("$playerName: I'm out!") }
}

private fun MessageSendInstance<RoundRobinPlayer, Int>.selectNextPlayer() {
    var idx = process.nextPlayerIndex + 1
    if (idx >= process.players.size) {
        idx = 0
    }
    process.nextPlayerIndex = idx
    val player = if (process.players.isNotEmpty()) 
        process.players[idx] 
    else 
        process.selfPlayer
    receiverDomain = player.domain
    receiverProcessInstanceId = player.id
    println("Step ${process.shotCounter + 1}: " +
            "${process.playerName} >>> ${player.name}")
}

ٻي صورت ۾، پليئر جو رويو پوئين هڪ کان مختلف ناهي، تنهنڪري ڊراگرام تبديل نٿو ڪري.

هاڻي اسان کي اهو سڀ ڪجهه هلائڻ لاءِ ٽيسٽ جي ضرورت آهي. مان صرف ٽيسٽ جو ڪوڊ ڏيندس، ته جيئن مضمون کي بوائلر پليٽ سان گڏ نه ڪيو وڃي (حقيقت ۾، مون ٻين ڪاروباري عملن جي انضمام کي جانچڻ لاءِ اڳ ۾ ٺهيل ٽيسٽ ماحول استعمال ڪيو):

ٽيسٽ گيم()

@Test
public void testGame() throws InterruptedException {
    String pl2 = startProcess(app2, "RandomPlayer", playerParams("Player2", 20));
    String pl3 = startProcess(app2, "RandomPlayer", playerParams("Player3", 40));
    String pl4 = startProcess(app3, "RoundRobinPlayer", playerParams("Player4", 25));
    String pl5 = startProcess(app3, "RoundRobinPlayer", playerParams("Player5", 35));
    String pl1 = startProcess(app1, "InitialPlayer");
    // Теперь нужно немного подождать, пока игроки "познакомятся" друг с другом.
    // Ждать через sleep - плохое решение, зато самое простое. 
    // Не делайте так в серьезных тестах!
    Thread.sleep(1000);
    // Запускаем игру, закрывая пользовательскую активность
    assertTrue(closeTask(app1, pl1, "Start"));
    app1.getWaiting().waitProcessFinished(pl1);
    app2.getWaiting().waitProcessFinished(pl2);
    app2.getWaiting().waitProcessFinished(pl3);
    app3.getWaiting().waitProcessFinished(pl4);
    app3.getWaiting().waitProcessFinished(pl5);
}

private Map<String, Object> playerParams(String name, int energy) {
    Map<String, Object> params = new HashMap<>();
    params.put("playerName", name);
    params.put("energy", energy);
    return params;
}

اچو ته ٽيسٽ هلون ۽ لاگ ڏسو:

ڪنسول جي پيداوار

Взята блокировка ключа lock://app1/process/InitialPlayer
Let's play!
Снята блокировка ключа lock://app1/process/InitialPlayer
Player2: I'm here!
Player3: I'm here!
Player4: I'm here!
Player5: I'm here!
... join player Player2 ...
... join player Player4 ...
... join player Player3 ...
... join player Player5 ...
Step 1: Player1 >>> Player3
Step 2: Player3 >>> Player5
Step 3: Player5 >>> Player3
Step 4: Player3 >>> Player4
Step 5: Player4 >>> Player3
Step 6: Player3 >>> Player4
Step 7: Player4 >>> Player5
Step 8: Player5 >>> Player2
Step 9: Player2 >>> Player5
Step 10: Player5 >>> Player4
Step 11: Player4 >>> Player2
Step 12: Player2 >>> Player4
Step 13: Player4 >>> Player1
Step 14: Player1 >>> Player4
Step 15: Player4 >>> Player3
Step 16: Player3 >>> Player1
Step 17: Player1 >>> Player2
Step 18: Player2 >>> Player3
Step 19: Player3 >>> Player1
Step 20: Player1 >>> Player5
Step 21: Player5 >>> Player1
Step 22: Player1 >>> Player2
Step 23: Player2 >>> Player4
Step 24: Player4 >>> Player5
Step 25: Player5 >>> Player3
Step 26: Player3 >>> Player4
Step 27: Player4 >>> Player2
Step 28: Player2 >>> Player5
Step 29: Player5 >>> Player2
Step 30: Player2 >>> Player1
Step 31: Player1 >>> Player3
Step 32: Player3 >>> Player4
Step 33: Player4 >>> Player1
Step 34: Player1 >>> Player3
Step 35: Player3 >>> Player4
Step 36: Player4 >>> Player3
Step 37: Player3 >>> Player2
Step 38: Player2 >>> Player5
Step 39: Player5 >>> Player4
Step 40: Player4 >>> Player5
Step 41: Player5 >>> Player1
Step 42: Player1 >>> Player5
Step 43: Player5 >>> Player3
Step 44: Player3 >>> Player5
Step 45: Player5 >>> Player2
Step 46: Player2 >>> Player3
Step 47: Player3 >>> Player2
Step 48: Player2 >>> Player5
Step 49: Player5 >>> Player4
Step 50: Player4 >>> Player2
Step 51: Player2 >>> Player5
Step 52: Player5 >>> Player1
Step 53: Player1 >>> Player5
Step 54: Player5 >>> Player3
Step 55: Player3 >>> Player5
Step 56: Player5 >>> Player2
Step 57: Player2 >>> Player1
Step 58: Player1 >>> Player4
Step 59: Player4 >>> Player1
Step 60: Player1 >>> Player4
Step 61: Player4 >>> Player3
Step 62: Player3 >>> Player2
Step 63: Player2 >>> Player5
Step 64: Player5 >>> Player4
Step 65: Player4 >>> Player5
Step 66: Player5 >>> Player1
Step 67: Player1 >>> Player5
Step 68: Player5 >>> Player3
Step 69: Player3 >>> Player4
Step 70: Player4 >>> Player2
Step 71: Player2 >>> Player5
Step 72: Player5 >>> Player2
Step 73: Player2 >>> Player1
Step 74: Player1 >>> Player4
Step 75: Player4 >>> Player1
Step 76: Player1 >>> Player2
Step 77: Player2 >>> Player5
Step 78: Player5 >>> Player4
Step 79: Player4 >>> Player3
Step 80: Player3 >>> Player1
Step 81: Player1 >>> Player5
Step 82: Player5 >>> Player1
Step 83: Player1 >>> Player4
Step 84: Player4 >>> Player5
Step 85: Player5 >>> Player3
Step 86: Player3 >>> Player5
Step 87: Player5 >>> Player2
Step 88: Player2 >>> Player3
Player2: I'm out!
Step 89: Player3 >>> Player4
... player Player2 is out ...
Step 90: Player4 >>> Player1
Step 91: Player1 >>> Player3
Step 92: Player3 >>> Player1
Step 93: Player1 >>> Player4
Step 94: Player4 >>> Player3
Step 95: Player3 >>> Player5
Step 96: Player5 >>> Player1
Step 97: Player1 >>> Player5
Step 98: Player5 >>> Player3
Step 99: Player3 >>> Player5
Step 100: Player5 >>> Player4
Step 101: Player4 >>> Player5
Player4: I'm out!
... player Player4 is out ...
Step 102: Player5 >>> Player1
Step 103: Player1 >>> Player3
Step 104: Player3 >>> Player1
Step 105: Player1 >>> Player3
Step 106: Player3 >>> Player5
Step 107: Player5 >>> Player3
Step 108: Player3 >>> Player1
Step 109: Player1 >>> Player3
Step 110: Player3 >>> Player5
Step 111: Player5 >>> Player1
Step 112: Player1 >>> Player3
Step 113: Player3 >>> Player5
Step 114: Player5 >>> Player3
Step 115: Player3 >>> Player1
Step 116: Player1 >>> Player3
Step 117: Player3 >>> Player5
Step 118: Player5 >>> Player1
Step 119: Player1 >>> Player3
Step 120: Player3 >>> Player5
Step 121: Player5 >>> Player3
Player5: I'm out!
... player Player5 is out ...
Step 122: Player3 >>> Player5
Step 123: Player5 >>> Player1
Player5: I'm out!
Step 124: Player1 >>> Player3
... player Player5 is out ...
Step 125: Player3 >>> Player1
Step 126: Player1 >>> Player3
Player1: I'm out!
... player Player1 is out ...
Step 127: Player3 >>> Player3
Player3: I'm out!
Step 128: Player3 >>> Player3
... player Player3 is out ...
Player3: I'm out!
Stop!
Step 129: Player3 >>> Player3
Player3: I'm out!

هن سڀني مان اسان ڪيترائي اهم نتيجا ڪڍي سگهون ٿا:

  • ضروري اوزارن سان، ايپليڪيشن ڊولپرز ٺاهي سگھن ٿا ايپليڪيشنن جي وچ ۾ انٽيگريشن لاڳاپا بغير ڪاروباري منطق جي مداخلت جي؛
  • انضمام جي ڪم جي پيچيدگي جيڪا انجنيئرنگ جي صلاحيتن جي ضرورت هوندي آهي، فريم ورڪ جي اندر لڪائي سگهجي ٿي جيڪڏهن اهو شروعاتي طور تي فريم ورڪ جي فن تعمير ۾ شامل آهي. مسئلي جي ڏکيائي کي لڪائي نه ٿو سگهجي، تنهنڪري ڪوڊ ۾ هڪ مشڪل مسئلي جو حل ان وانگر نظر ايندو؛
  • جڏهن انضمام جي منطق کي ترقي ڪندي، اهو ضروري آهي ته اڪائونٽ ۾ حتمي استحڪام ۽ سڀني انضمام شرڪت ڪندڙن جي حالت ۾ تبديلين جي لڪيرائيزيشن جي کوٽ کي. اهو اسان کي مجبور ڪري ٿو ته منطق کي پيچيده ڪرڻ لاءِ ان کي ترتيب سان غير حساس بڻائڻ لاءِ جنهن ۾ ٻاهرين واقعا ٿين ٿا. اسان جي مثال ۾، رانديگر کي راند ۾ حصو وٺڻ تي مجبور ڪيو ويندو آهي جڏهن هو راند مان نڪرڻ جو اعلان ڪري ٿو: ٻيا رانديگر ان کي بال پاس ڪندا رهندا جيستائين سندس نڪرڻ جي معلومات پهچي وڃي ۽ سڀني شرڪت ڪندڙن طرفان عمل ڪيو وڃي. هي منطق راند جي ضابطن جي پيروي نٿو ڪري ۽ چونڊيل فن تعمير جي فريم ورڪ ۾ هڪ سمجھوتي حل آهي.

اڳيون، اسان اسان جي حل جي مختلف پيچيدگين، سمجھوتن ۽ ٻين نقطن بابت ڳالهائينداسين.

سڀئي پيغام هڪ قطار ۾ آهن

سڀئي مربوط ايپليڪيشنون هڪ انٽيگريشن بس سان ڪم ڪن ٿيون، جيڪو هڪ خارجي بروکر جي صورت ۾ پيش ڪيو ويو آهي، پيغامن لاءِ هڪ BPMQueue ۽ سگنلز (واقعات) لاءِ هڪ BPMTopic موضوع. سڀني پيغامن کي هڪ قطار ذريعي رکڻ خود هڪ سمجھوتو آهي. ڪاروباري منطق جي سطح تي، توھان ھاڻي متعارف ڪرائي سگھو ٿا گھڻا نوان پيغام جا قسم جيڪي توھان چاھيو بغير سسٽم جي جوڙجڪ ۾ تبديليون ڪرڻ جي. اها هڪ اهم سادگي آهي، پر ان ۾ ڪجهه خطرا آهن، جيڪي اسان جي عام ڪمن جي حوالي سان اسان لاءِ ايترا اهم نه ٿا لڳي.

BPM انداز انضمام

بهرحال، هتي هڪ ذيلي ذخيري آهي: هر ايپليڪيشن پنهنجي ڊومين جي نالي سان، داخلا تي قطار مان "پنهنجي" پيغامن کي فلٽر ڪري ٿو. ڊومين پڻ سگنلن ۾ بيان ڪري سگھجي ٿو جيڪڏھن توھان کي محدود ڪرڻ جي ضرورت آھي ”منظر جي دائري“ کي سگنل جي ھڪڙي ايپليڪيشن تائين. انهي کي بس ذريعي وڌائڻ گهرجي، پر ڪاروباري منطق هاڻي ڊومين نالن سان هلائڻ گهرجي: پيغامن کي خطاب ڪرڻ لاء - لازمي، سگنلن لاء - گهربل.

انٽيگريشن بس جي اعتبار کي يقيني بڻائڻ

Reliability ڪيترن ئي نقطن تي مشتمل آهي:

  • منتخب ٿيل پيغام بروکر فن تعمير جو هڪ نازڪ حصو ۽ ناڪامي جو هڪ واحد نقطو آهي: اهو ڪافي طور تي غلطي برداشت ڪرڻ گهرجي. توهان کي صرف وقت جي آزمائشي عملن کي استعمال ڪرڻ گهرجي، سٺي مدد ۽ وڏي ڪميونٽي سان؛
  • اهو ضروري آهي ته پيغام بروکر جي اعلي دستيابي کي يقيني بڻائي، جنهن لاء ان کي جسماني طور تي الڳ ٿيل ايپليڪيشنن کان الڳ ڪيو وڃي (اپلائيڊ ڪاروباري منطق سان ايپليڪيشنن جي اعلي دستيابي کي يقيني بڻائڻ تمام گهڻو ڏکيو ۽ قيمتي آهي)؛
  • بروکر "گهٽ ۾ گهٽ هڪ ڀيرو" پهچائڻ جي ضمانت فراهم ڪرڻ جو پابند آهي. انضمام بس جي قابل اعتماد آپريشن لاء هڪ لازمي گهربل آهي. "بلڪل هڪ ڀيرو" سطح جي ضمانت جي ڪا ضرورت ناهي: ڪاروباري عمل، ضابطي جي طور تي، پيغامن يا واقعن جي بار بار اچڻ لاءِ حساس نه هوندا آهن، ۽ خاص ڪمن ۾ جتي اهو ضروري آهي، ڪاروبار ۾ اضافي چيڪ شامل ڪرڻ آسان آهي. منطق مسلسل استعمال ڪرڻ جي ڀيٽ ۾ ڪافي "مهانگي" " ضمانتون؛
  • پيغام ۽ سگنل موڪلڻ لازمي طور تي ڪاروباري عملن ۽ ڊومين ڊيٽا جي حالت ۾ تبديلين سان گڏ مجموعي ٽرانزيڪشن ۾ شامل ٿيڻ گهرجي. ترجيحي اختيار ھڪڙو نمونو استعمال ڪرڻ آھي ٽرانزيڪشنل آئوٽ باڪس، پر ان کي ڊيٽابيس ۾ اضافي ٽيبل ۽ ريپٽر جي ضرورت پوندي. JEE ايپليڪيشنن ۾، هن کي مقامي JTA مينيجر استعمال ڪندي آسان بڻائي سگهجي ٿو، پر چونڊيل بروکر سان ڪنيڪشن ڪم ڪرڻ جي قابل هوندو. XA;
  • ايندڙ پيغامن ۽ واقعن کي سنڀاليندڙن کي پڻ هڪ ٽرانزيڪشن سان ڪم ڪرڻ گهرجي جيڪو ڪاروباري عمل جي حالت کي تبديل ڪري ٿو: جيڪڏهن اهڙي ٽرانزيڪشن کي واپس ڪيو وڃي، پوء پيغام جي وصولي کي منسوخ ڪيو وڃي.
  • نياپا جيڪي نقصن جي ڪري ڊليور نه ٿي سگھيا آھن تن کي الڳ اسٽوريج ۾ رکڻ گھرجي ڊي ايل ق (ميل خط جي قطار). هن مقصد لاءِ، اسان هڪ الڳ پليٽ فارم microservice ٺاهيو آهي جيڪو اهڙن پيغامن کي پنهنجي اسٽوريج ۾ محفوظ ڪري ٿو، انهن کي خاصيتن جي حساب سان ترتيب ڏئي ٿو (جلدي گروپ بندي ۽ ڳولا لاءِ)، ۽ هڪ API کي ظاهر ڪري ٿو ڏسڻ لاءِ، منزل جي پتي تي ٻيهر موڪلڻ، ۽ پيغامن کي حذف ڪرڻ. سسٽم منتظم پنهنجي ويب انٽرفيس ذريعي هن خدمت سان ڪم ڪري سگهن ٿا؛
  • بروکر سيٽنگن ۾، توهان کي پهچائڻ جي ڪوششن جي تعداد کي ترتيب ڏيڻ جي ضرورت آهي ۽ ترسيل جي وچ ۾ دير جي وچ ۾ پيغامن جي DLQ ۾ اچڻ جي امڪان کي گھٽائڻ لاء (اهو سڀ کان بهتر پيٽرولر کي ڳڻڻ تقريبا ناممڪن آهي، پر توهان تجرباتي طور تي عمل ڪري سگهو ٿا ۽ آپريشن دوران انهن کي ترتيب ڏئي سگهو ٿا. ؛
  • DLQ اسٽور کي مسلسل مانيٽر ڪيو وڃي، ۽ مانيٽرنگ سسٽم کي لازمي طور تي سسٽم ايڊمنسٽريٽرن کي خبردار ڪرڻ گهرجي ته جيئن جڏهن اڻپورا پيغام اچي وڃن، اهي جلدي ممڪن طور تي جواب ڏئي سگهن. اهو گھٽائي ڇڏيندو "متاثر ٿيل علائقو" جي ناڪامي يا ڪاروباري منطق جي غلطي؛
  • انضمام بس ايپليڪيشنن جي عارضي غير موجودگيءَ لاءِ حساس نه هجڻ گهرجي: هڪ موضوع جي رڪنيت پائيدار هجڻ گهرجي، ۽ ايپليڪيشن جو ڊومين نالو منفرد هجڻ گهرجي، انهي ڪري جڏهن ايپليڪيشن غير حاضر آهي، ڪو ٻيو ماڻهو ان جي پيغامن تي عمل ڪرڻ جي ڪوشش نه ڪندو. قطار.

ڪاروباري منطق جي سلسلي جي حفاظت کي يقيني بڻائڻ

ڪاروباري عمل جو ساڳيو مثال هڪ ئي وقت ۾ ڪيترائي پيغام ۽ واقعا حاصل ڪري سگھن ٿا، جن جي پروسيسنگ متوازي شروع ٿيندي. ساڳئي وقت، هڪ ايپليڪيشن ڊولپر لاء، هر شيء سادو ۽ موضوع کان محفوظ هجڻ گهرجي.

عمل جي ڪاروباري منطق هر خارجي واقعي تي عمل ڪري ٿي جيڪا انفرادي طور تي ڪاروباري عمل کي متاثر ڪري ٿي. اهڙا واقعا ٿي سگهن ٿا:

  • ڪاروباري عمل جو مثال شروع ڪرڻ؛
  • ڪاروباري عمل جي اندر سرگرمي سان لاڳاپيل صارف عمل؛
  • هڪ پيغام يا سگنل جي وصولي جنهن ۾ ڪاروباري عمل جو مثال سبسڪرائب ڪيو ويو آهي؛
  • ڪاروباري عمل جي مثال سان ٽائمر مقرر ڪرڻ؛
  • API ذريعي عمل کي ڪنٽرول ڪريو (مثال طور، عمل ۾ مداخلت).

هر اهڙو واقعو ڪاروباري عمل جي حالت کي تبديل ڪري سگهي ٿو مثال طور: ڪجهه سرگرميون ختم ٿي سگهن ٿيون ۽ ٻيون شروع ٿي سگهن ٿيون، ۽ مسلسل ملڪيت جا قدر تبديل ٿي سگهن ٿا. ڪنهن به سرگرمي کي بند ڪرڻ جي نتيجي ۾ ٿي سگهي ٿو هڪ يا وڌيڪ هيٺين سرگرمين کي چالو ڪرڻ. اهي، موڙ ۾، ٻين واقعن جي انتظار ۾ روڪي سگهن ٿا، يا، جيڪڏهن انهن کي ڪنهن به اضافي ڊيٽا جي ضرورت ناهي، ساڳئي ٽرانزيڪشن ۾ مڪمل ڪري سگهن ٿا. ٽرانزيڪشن کي بند ڪرڻ کان اڳ، ڪاروباري عمل جي نئين حالت ڊيٽابيس ۾ محفوظ ڪئي وئي آهي، جتي اهو ايندڙ خارجي واقعي جو انتظار ڪندو.

مسلسل ڪاروباري پروسيسنگ ڊيٽا هڪ تعلقي ڊيٽابيس ۾ ذخيرو ٿيل آهي پروسيسنگ کي هم وقت سازي ڪرڻ لاءِ هڪ تمام آسان نقطو آهي جيڪڏهن توهان استعمال ڪريو SELECT FOR UPDATE. جيڪڏهن هڪ ٽرانزيڪشن ان کي تبديل ڪرڻ لاءِ بنياد کان ڪاروباري عمل جي حالت حاصل ڪرڻ ۾ ڪامياب ٿي وئي، ته پوءِ متوازي طور تي ٻيو ڪو به ٽرانزيڪشن ٻي تبديلي لاءِ ساڳي حالت حاصل ڪرڻ جي قابل نه هوندو، ۽ پهرين ٽرانزيڪشن جي مڪمل ٿيڻ کان پوءِ، ٻيو آهي. اڳ ۾ ئي تبديل ٿيل حالت حاصل ڪرڻ جي ضمانت.

ڊي بي ايم ايس پاسي تي مايوسي لاڪ استعمال ڪندي، اسان سڀني ضروري گهرجن کي پورو ڪريون ٿا امل، ۽ پڻ ايپليڪيشن کي ماپڻ جي صلاحيت برقرار رکون ٿا ڪاروباري منطق سان هلندڙ مثالن جو تعداد وڌائيندي.

تنهن هوندي، مايوسي لاڪ اسان کي ڊيڊ لاڪ سان خطرو ڪري ٿو، جنهن جو مطلب آهي ته SELECT FOR UPDATE اڃا تائين محدود هجڻ گهرجي ڪجهه مناسب وقت ختم ٿيڻ جي صورت ۾ جيڪڏهن ڊيڊ لاڪ ڪاروبار منطق ۾ ڪجهه سخت ڪيسن تي واقع ٿين.

ٻيو مسئلو هڪ ڪاروباري عمل جي شروعات جي هم وقت سازي آهي. جڏهن ته ڪاروباري عمل جو ڪو مثال نه آهي، ڊيٽابيس ۾ ڪا به رياست ناهي، تنهنڪري بيان ڪيل طريقو ڪم نه ڪندو. جيڪڏهن توهان کي هڪ مخصوص دائري ۾ ڪاروباري عمل جي مثال جي انفراديت کي يقيني بڻائڻ جي ضرورت آهي، ته پوء توهان کي پروسيس ڪلاس ۽ لاڳاپيل دائري سان لاڳاپيل ڪجهه قسم جي هم وقت سازي اعتراض جي ضرورت پوندي. ھن مسئلي کي حل ڪرڻ لاءِ، اسان ھڪ مختلف لاڪنگ ميکانيزم استعمال ڪريون ٿا جيڪو اسان کي اجازت ڏئي ٿو ھڪ لاڪ کڻڻ لاءِ ھڪ غير ارادي وسيلن تي جيڪو بيان ڪيل ڪيئي طرفان URI فارميٽ ۾ ھڪ خارجي خدمت ذريعي.

اسان جي مثالن ۾، InitialPlayer ڪاروباري عمل ۾ هڪ اعلان شامل آهي

uniqueConstraint = UniqueConstraints.singleton

تنهن ڪري، لاگ ان ۾ لاڳاپيل ڪي جي تالا کڻڻ ۽ ڇڏڻ بابت پيغام شامل آهن. ٻين ڪاروباري عملن لاءِ اهڙا نياپا نه آهن: uniqueConstraint مقرر نه آهي.

مسلسل رياست سان ڪاروباري عملن جا مسئلا

ڪڏهن ڪڏهن هڪ مستقل رياست هجڻ نه رڳو مدد ڪري ٿي، پر حقيقت ۾ ترقي ۾ رڪاوٽ پڻ.
مسئلا تڏهن شروع ٿين ٿا جڏهن ڪاروباري منطق ۽/يا ڪاروباري عمل جي ماڊل ۾ تبديليون ڪرڻ گهرجن. هر اهڙي تبديلي ڪاروباري عمل جي پراڻي حالت سان مطابقت ناهي. جيڪڏهن ڊيٽابيس ۾ ڪيترائي زنده مثالون آهن، ته پوءِ غير مطابقت واريون تبديليون ڪرڻ تمام گهڻيون مشڪلاتون پيدا ڪري سگهن ٿيون، جن جو اسان اڪثر سامنا ڪندا آهيون جڏهن jBPM استعمال ڪندا آهيون.

تبديلين جي کوٽائي تي مدار رکندي، توھان ٻن طريقن سان ڪم ڪري سگھو ٿا:

  1. نئين ڪاروباري عمل جو قسم ٺاهيو ته جيئن پراڻي ۾ غير مطابقت رکندڙ تبديليون نه ڪيون وڃن، ۽ نوان مثال شروع ڪرڻ وقت پراڻي بدران ان کي استعمال ڪريو. پراڻيون ڪاپيون ”اڳي وانگر“ ڪم ڪنديون رهنديون.
  2. ڪاروباري منطق کي اپڊيٽ ڪرڻ دوران ڪاروباري عملن جي مستقل حالت کي منتقل ڪريو.

پهريون طريقو آسان آهي، پر ان جون حدون ۽ نقصان آهن، مثال طور:

  • ڪيترن ئي ڪاروباري عمل جي ماڊل ۾ ڪاروباري منطق جي نقل، ڪاروباري منطق جي مقدار کي وڌائڻ؛
  • اڪثر ڪري نئين ڪاروباري منطق ڏانهن فوري منتقلي جي ضرورت هوندي آهي (انضمام جي ڪمن جي لحاظ کان - تقريبن هميشه)؛
  • ڊولپر کي خبر ناهي ته ڪهڙي نقطي تي پراڻي ماڊلز کي ختم ڪري سگهجي ٿو.

عملي طور تي اسان ٻنهي طريقن کي استعمال ڪندا آهيون، پر اسان جي زندگين کي آسان بڻائڻ لاء ڪيترائي فيصلا ڪيا آهن:

  • ڊيٽابيس ۾، ڪاروباري عمل جي مسلسل حالت هڪ آساني سان پڙهڻ جي قابل ۽ آساني سان پروسيس ٿيل فارم ۾ ذخيرو ٿيل آهي: هڪ JSON فارميٽ اسٽرنگ ۾. هي لڏپلاڻ کي ايپليڪيشن جي اندر ۽ ٻاهران ٻنهي کي انجام ڏيڻ جي اجازت ڏئي ٿو. آخري حل جي طور تي، توهان ان کي دستي طور تي درست ڪري سگهو ٿا (خاص طور تي ڊيبگنگ دوران ترقي ۾ مفيد)؛
  • انضمام ڪاروباري منطق ڪاروباري عملن جا نالا استعمال نه ڪندو آهي، انهي ڪري ته ڪنهن به وقت ممڪن آهي ته ڪنهن به وقت ۾ حصو وٺندڙ عملن مان هڪ تي عمل درآمد کي نئين نالي سان تبديل ڪيو وڃي (مثال طور، "InitialPlayerV2"). پابند پيغام ۽ سگنل جي نالن ذريعي ٿئي ٿي؛
  • پروسيس ماڊل وٽ هڪ نسخو نمبر آهي، جنهن کي اسين وڌايون ٿا جيڪڏهن اسان هن ماڊل ۾ غير مطابقت رکندڙ تبديليون ڪيون، ۽ اهو نمبر پروسيس مثال جي حالت سان گڏ محفوظ ڪيو وڃي.
  • پروسيس جي مسلسل حالت کي ڊيٽابيس مان پهريون ڀيرو هڪ آسان اعتراض ماڊل ۾ پڙهيو ويندو آهي، جيڪو لڏپلاڻ وارو طريقو ڪم ڪري سگهي ٿو جيڪڏهن ماڊل ورزن نمبر تبديل ٿي ويو آهي؛
  • لڏپلاڻ وارو عمل ڪاروباري منطق جي اڳيان رکيل آهي ۽ "سست" سڏيو ويندو آهي ڪاروباري عمل جي هر مثال لاءِ ڊيٽابيس مان بحالي جي وقت؛
  • جيڪڏهن توهان سڀني عملن جي حالت کي جلدي ۽ هم وقت سازي سان منتقل ڪرڻ جي ضرورت آهي، وڌيڪ کلاسک ڊيٽابيس لڏپلاڻ حل استعمال ڪيا ويندا آهن، پر توهان کي JSON سان ڪم ڪرڻو پوندو.

ڇا توهان کي ڪاروباري عملن لاءِ ٻئي فريم ورڪ جي ضرورت آهي؟

مضمون ۾ بيان ڪيل حل اسان کي اسان جي زندگي کي خاص طور تي آسان ڪرڻ جي اجازت ڏني، ايپليڪيشن ڊولپمينٽ جي سطح تي حل ٿيل مسئلن جي حد کي وڌايو، ۽ ڪاروباري منطق کي مائڪرو سروسز ۾ الڳ ڪرڻ جي خيال کي وڌيڪ پرڪشش بڻايو. هن کي حاصل ڪرڻ لاء، تمام گهڻو ڪم ڪيو ويو، ڪاروباري عملن لاء هڪ تمام "هلڪو وزن" فريم ورڪ ٺاهي وئي، انهي سان گڏ خدمت جي اجزاء جي سڃاڻپ مسئلن کي حل ڪرڻ لاء ايپليڪيشن مسئلن جي وسيع رينج جي حوالي سان. اسان کي انهن نتيجن کي حصيداري ڪرڻ جي خواهش آهي ۽ عام اجزاء جي ترقي کي مفت لائسنس تحت کليل رسائي فراهم ڪرڻ آهي. اهو ڪجهه ڪوشش ۽ وقت جي ضرورت پوندي. اهڙن حلن جي طلب کي سمجهڻ اسان لاءِ هڪ اضافي حوصلا افزائي ٿي سگهي ٿي. تجويز ڪيل مضمون ۾، تمام ٿورو ڌيان پاڻ فريم ورڪ جي صلاحيتن کي ادا ڪيو ويو آهي، پر انهن مان ڪجهه پيش ڪيل مثالن مان نظر اچن ٿا. جيڪڏهن اسان پنهنجو فريم ورڪ شايع ڪريون ٿا، هڪ الڳ مضمون ان لاءِ وقف ڪيو ويندو. ساڳئي وقت ۾، اسان شڪرگذار ٿينداسين جيڪڏهن توهان سوال جو جواب ڏيندي ٿورو موٽ ڏيو:

صرف رجسٽرڊ استعمال ڪندڙ سروي ۾ حصو وٺي سگهن ٿا. سائن ان ڪريو، توهان جي مهرباني.

ڇا توهان کي ڪاروباري عملن لاءِ ٻئي فريم ورڪ جي ضرورت آهي؟

  • 18,8٪ها، مان ڪافي عرصي کان اهڙي شيءِ ڳولي رهيو آهيان

  • 12,5٪مان توهان جي عمل درآمد بابت وڌيڪ سکڻ ۾ دلچسپي وٺان ٿو، اهو ٿي سگهي ٿو مفيد2

  • 6,2٪اسان موجوده فريم ورڪ مان ھڪڙو استعمال ڪريون ٿا، پر 1 کي تبديل ڪرڻ بابت سوچي رھيا آھيون

  • 18,8٪اسان موجوده فريم ورڪ مان ھڪڙو استعمال ڪريون ٿا، سڀ ڪجھ ٺيڪ آھي3

  • 18,8٪اسان بغير فريم ورڪ جي انتظام ڪريون ٿا 3

  • 25,0٪پنهنجو لکو 4

16 صارفين ووٽ ڏنو. 7 استعمال ڪندڙن کي روڪيو ويو.

جو ذريعو: www.habr.com

تبصرو شامل ڪريو