د BPM سټایل ادغام

د BPM سټایل ادغام

سلام هبر!

زموږ شرکت د ERP - ټولګي سافټویر حلونو پراختیا کې تخصص لري ، په کوم کې چې د لوی برخه برخه د لیږد سیسټمونو لخوا نیول کیږي د لوی مقدار سوداګرۍ منطق او د لا EDMS کاري فلو سره. زموږ د محصولاتو عصري نسخې د JavaEE ټیکنالوژیو پراساس دي، مګر موږ په فعاله توګه د مایکرو خدماتو سره تجربه کوو. د دې ډول حلونو یو له خورا ستونزمن برخو څخه د نږدې ډومینونو پورې اړوند د مختلف فرعي سیسټمونو ادغام دی. د ادغام کارونو تل موږ ته لوی سرخوږی راکړی دی، پرته له دې چې د معمارۍ سټایلونو، ټیکنالوژۍ سټیکونو او چوکاټونو ته په پام سره چې موږ یې کاروو، مګر پدې وروستیو کې د ورته ستونزو په حل کې پرمختګ شوی.

په مقاله کې چې ستاسو پام ته راوړل شوی، زه به په ټاکل شوي ساحه کې د NPO کریسټا تجربې او معمارۍ څیړنې په اړه وغږیږم. موږ به د غوښتنلیک جوړونکي له نظره د ادغام ستونزې لپاره د ساده حل یوه بیلګه هم په پام کې ونیسو او ومومئ چې د دې سادگي ترشا څه پټ دی.

ردول

په مقاله کې تشریح شوي معماري او تخنیکي حلونه زما لخوا د ځانګړو دندو په شرایطو کې د شخصي تجربې پراساس وړاندیز شوي. دا حلونه د نړیوال کیدو ادعا نه کوي او ممکن د کارولو نورو شرایطو کې مطلوب نه وي.

BPM له دې سره څه تړاو لري؟

د دې پوښتنې د ځواب لپاره، موږ اړتیا لرو چې د خپلو حلونو پلي شوي ستونزو ځانګړتیاوو ته لږ څه وګورو. زموږ په عادي لیږد سیسټم کې د سوداګرۍ منطق اصلي برخه د کاروونکي انٹرفیسونو له لارې ډیټابیس ته ډیټا داخلول ، په لاسي او په اتوماتيک ډول دا ډاټا چیک کول ، د ځینې کاري فلو له لارې لیږدول ، بل سیسټم / تحلیلي ډیټابیس / آرشیف ته خپرول ، د راپورونو رامینځته کول. پدې توګه ، د پیرودونکو لپاره د سیسټم کلیدي دنده د دوی د داخلي سوداګرۍ پروسو اتومات کول دي.

د اسانتیا لپاره، موږ په مخابراتو کې د "سند" اصطلاح د ډیټا سیټ ځینې خلاصون په توګه کاروو، چې د یو عام کلید لخوا متحد کیږي، کوم چې یو ځانګړی کاري جریان "وصل" کیدی شي.
مګر د ادغام منطق په اړه څه؟ په هرصورت ، د ادغام دنده د سیسټم جوړښت لخوا رامینځته کیږي ، کوم چې د پیرودونکي په غوښتنه نه ، مګر د بشپړ مختلف فاکتورونو تر اغیز لاندې برخو کې "څیړل شوي" دي:

  • د کانوی د قانون تر اغیز لاندې؛
  • د نورو محصولاتو لپاره دمخه رامینځته شوي فرعي سیسټمونو د بیا کارولو په پایله کې؛
  • لکه څنګه چې د معمار لخوا پریکړه شوې، د غیر فعال غوښتنو پر بنسټ.

د ادغام منطق د اصلي کاري فلو د سوداګرۍ منطق څخه جلا کولو لپاره عالي لالچ شتون لري ترڅو د ادغام هنري اثارو سره د سوداګرۍ منطق ککړ نه کړي او د غوښتنلیک پراختیا کونکی د سیسټم د معماري منظرې ځانګړتیاو ته د رسیدو څخه وژغوري. دا طریقه یو شمیر ګټې لري، مګر تمرین د هغې بې کفایتي ښیي:

  • د ادغام ستونزو حل کول معمولا د اصلي کاري فلو پلي کولو کې د محدود تمدید ټکو له امله د همغږي کالونو په بڼه ساده اختیارونو ته ښکته کیږي (لاندې د همغږي ادغام نیمګړتیاو په اړه نور)؛
  • د ادغام آثار لاهم د سوداګرۍ اصلي منطق ته ننوځي کله چې د بل فرعي سیسټم څخه فیډبیک ته اړتیا وي؛
  • د غوښتنلیک پراختیا کونکی ادغام له پامه غورځوي او کولی شي په اسانۍ سره د کاري جریان بدلولو سره مات کړي؛
  • سیسټم د کارونکي له نظره یو واحد پاتې کیږي، د فرعي سیسټمونو تر مینځ "سیمونه" د پام وړ کیږي، د کارونکي بې ځایه عملیات ښکاري چې د یو فرعي سیسټم څخه بل ته د معلوماتو لیږد پیل کوي.

بله لاره دا ده چې د ادغام تعاملات د اصلي سوداګرۍ منطق او کاري فلو د یوې لازمي برخې په توګه په پام کې ونیسئ. د دې لپاره چې د غوښتنلیک پراختیا کونکو مهارتونو اړتیاوې له آسمانه راښکته کیدو څخه وساتي ، د نوي ادغام تعامل رامینځته کول باید په اسانۍ او طبیعي ډول د حل غوره کولو لپاره لږترلږه اختیارونو سره ترسره شي. دا د هغه په ​​​​پرتله خورا ستونزمن دی: وسیله باید دومره ځواکمن وي چې کارونکي ته د دې کارولو لپاره اړین مختلف انتخابونه چمتو کړي او په ورته وخت کې اجازه ورنکړي چې په پښو کې ډزې وشي. ډیری پوښتنې شتون لري چې انجینر باید د ادغام دندو په شرایطو کې ځواب ووایی، مګر کوم چې د غوښتنلیک جوړونکی باید په خپل ورځني کار کې فکر ونکړي: د لیږد حدود، ثبات، اټومي، امنیت، اندازه کول، بار او د سرچینو ویش، روټینګ، مارشلینګ، تبلیغات او بدلول شرایط، او داسې نور. دا اړینه ده چې د غوښتنلیک پراختیا کونکو ته په کافي اندازه ساده پریکړې ټیمپلیټونه وړاندې کړئ، په کوم کې چې د دې ټولو پوښتنو ځوابونه دمخه پټ دي. دا نمونې باید په کافي اندازه خوندي وي: د سوداګرۍ منطق ډیر ځله بدلیږي ، کوم چې د غلطیو پیژندلو خطر ډیروي ، د غلطیو لګښت باید په کافي اندازه ټیټ وي.

مګر بیا هم، BPM د دې سره څه لري؟ د کاري فلو پلي کولو لپاره ډیری اختیارونه شتون لري ...
په حقیقت کې، د سوداګریزو پروسو یو بل تطبیق زموږ په حلونو کې خورا مشهور دی - د دولتي لیږد ډیاګرام د اعلاناتي ترتیب له لارې او لیږد ته د سوداګرۍ منطق سره سمبالونکي نښلول. په ورته وخت کې، هغه دولت چې د سوداګرۍ په بهیر کې د "سند" اوسنی موقعیت ټاکي، پخپله د "سند" ځانګړتیا ده.

د BPM سټایل ادغام
دا د پروژې په پیل کې د پروسې په څیر ښکاري

د دې ډول پلي کولو شهرت د نسبي سادگي او د خطي سوداګرۍ پروسو رامینځته کولو سرعت له امله دی. په هرصورت، لکه څنګه چې د سافټویر سیسټمونه ډیر پیچلي کیږي، د سوداګرۍ پروسې اتوماتیک برخه وده کوي او ډیر پیچلي کیږي. د تخریب، د پروسو د برخو بیا کارولو، او همدارنګه د فورک کولو پروسې ته اړتیا ده ترڅو هره څانګه په موازي توګه اجرا شي. په داسې شرایطو کې، وسیله ناامنه کیږي، او د دولت لیږد ډیاګرام خپل د معلوماتو مینځپانګه له لاسه ورکوي (د ادغام تعامل په ډیاګرام کې هیڅ نه منعکس کیږي).

د BPM سټایل ادغام
دا هغه څه دي چې پروسه د اړتیاو روښانه کولو څو تکرارونو وروسته ښکاري

د دې حالت څخه د وتلو لاره د انجن ادغام وه jBPM په ځینو محصولاتو کې د خورا پیچلي سوداګرۍ پروسې سره. په لنډه موده کې، دې حل یو څه بریالیتوب درلود: دا ممکنه شوه چې پیچلې سوداګریزې پروسې پلي کړي پداسې حال کې چې په یادښت کې د کافي معلوماتي او تازه ډیاګرام ساتل. BPMN2.

د BPM سټایل ادغام
د یوې پیچلې سوداګرۍ پروسې کوچنۍ برخه

په اوږد مهال کې، حل د تمې سره سم نه و: د بصری وسیلو له لارې د سوداګرۍ پروسو رامینځته کولو لوړ کار شدت اجازه نه ورکوي چې د منلو وړ تولید شاخصونه ترلاسه کړي، او دا وسیله پخپله د پراختیا کونکو ترمنځ یو له خورا ناخوښۍ څخه بدل شو. د انجن د داخلي جوړښت په اړه هم شکایتونه شتون درلود، کوم چې د ډیری "پیچونو" او "کرچچونو" څرګندیدو المل شو.

د jBPM کارولو اصلي مثبت اړخ د سوداګرۍ پروسې مثال لپاره د خپل دوامداره حالت درلودو ګټو او زیانونو احساس و. موږ د سیګنالونو او پیغامونو له لارې د غیر متقابل تعاملاتو په کارولو سره د مختلف غوښتنلیکونو ترمینځ د پیچلي ادغام پروتوکولونو پلي کولو لپاره د پروسې طریقې کارولو امکان هم لیدلی. د دوامدار دولت شتون پدې کې مهم رول لوبوي.

د پورتنیو ټکو پر بنسټ، موږ کولی شو پایله وکړو: د BPM سټایل کې د پروسې کړنلاره موږ ته اجازه راکوي چې د خورا پیچلي سوداګریزو پروسو اتومات کولو لپاره پراخه دندې حل کړو ، په همغږي توګه په دې پروسو کې د ادغام فعالیتونه تنظیم کړو او د پلي شوي پروسې لید لید په مناسب یادښت کې ښودلو وړتیا وساتو.

د ادغام نمونې په توګه د همغږي زنګونو نیمګړتیاوې

همغږي ادغام ترټولو ساده بلاک کولو کال ته اشاره کوي. یو فرعي سیسټم د سرور اړخ په توګه کار کوي او API د مطلوب میتود سره افشا کوي. بل فرعي سیسټم د پیرودونکي اړخ په توګه کار کوي او په مناسب وخت کې د پایلې تمه کولو سره تلیفون کوي. د سیسټم جوړښت پورې اړه لري، د پیرودونکي او سرور اړخونه یا په ورته غوښتنلیک او پروسې کې کوربه کیدی شي، یا په مختلفو کې. په دویمه قضیه کې، تاسو اړتیا لرئ چې د RPC ځینې تطبیق پلي کړئ او د پیرامیټونو مارشلینګ او د زنګ پایله چمتو کړئ.

د BPM سټایل ادغام

دا ډول ادغام نمونه خورا لوی نیمګړتیاوې لري، مګر دا د ساده کولو له امله په عمل کې خورا پراخه کارول کیږي. د پلي کولو سرعت جذبوي او تاسو ته اړوي چې دا د "سوځولو" ضرب الاجل شرایطو کې بیا بیا پلي کړئ ، په تخنیکي پور کې حل لیکل. مګر دا هم پیښیږي چې بې تجربه پراختیا کونکي دا په غیر شعوري ډول کاروي ، په ساده ډول د منفي پایلو نه پوهیږي.

د فرعي سیسټمونو ارتباط کې د خورا څرګند زیاتوالي سربیره ، د "پراخولو" او "پراخولو" معاملو سره لږ څرګند ستونزې شتون لري. په حقیقت کې ، که چیرې د سوداګرۍ منطق کوم بدلون رامینځته کړي ، نو معاملې لازمي دي ، او لیږدونه په پایله کې د دې بدلونونو لخوا اغیزمن شوي ځینې غوښتنلیک سرچینې لاک کوي. دا، تر هغه چې یو فرعي سیسټم د بل څخه ځواب ته انتظار نه کوي، دا به د لیږد بشپړولو او د بندونو خوشې کولو توان ونلري. دا د پام وړ د مختلفو اغیزو خطر زیاتوي:

  • د سیسټم غبرګون له لاسه ورکړی، کاروونکي د غوښتنو ځوابونو لپاره اوږد انتظار کوي؛
  • سرور په عموم کې د ډیری شوي تار پول له امله د کاروونکو غوښتنو ته ځواب ویل ودروي: ډیری تارونه د لیږد لخوا نیول شوي سرچینې په بند کې "ودریږي"؛
  • تعطلونه څرګندیدل پیل کوي: د دوی د پیښې احتمال په کلکه د راکړې ورکړې مودې پورې اړه لري ، د سوداګرۍ منطق مقدار او په راکړه ورکړه کې دخیل لاکونه؛
  • د لیږد وخت پای ته رسیدو تېروتنې څرګندیږي؛
  • سرور په OutOfMemory کې "غورځیږي" که چیرې دنده د ډیټا لوی مقدار پروسس کولو او بدلولو ته اړتیا ولري ، او د همغږي ادغام شتون دا خورا ستونزمن کوي ​​چې پروسس په "لټر" لیږدونو ویشل شي.

د معمارۍ له نظره ، د ادغام پرمهال د بلاک کولو تلیفونونو کارول د انفرادي فرعي سیسټمونو کیفیت کنټرول له لاسه ورکولو لامل کیږي: دا ناشونې ده چې د یو فرعي سیسټم کیفیت اهداف د بل فرعي سیسټم کیفیت اهدافو څخه په انزوا کې تضمین کړئ. که فرعي سیسټمونه د مختلف ټیمونو لخوا رامینځته شي، دا یوه لویه ستونزه ده.

شیان نور هم په زړه پوري کیږي که چیرې مدغم شوي فرعي سیسټمونه په مختلف غوښتنلیکونو کې وي او همغږي بدلونونه باید په دواړو خواو کې رامینځته شي. څنګه کولای شو چی دا بدلونونه د انتقال؟

که چیرې بدلونونه په جلا معاملو کې رامینځته شي، نو قوي استثنایی اداره کول او جبران به چمتو شي، او دا په بشپړه توګه د همغږي ادغام اصلي ګټه له منځه وړي - سادگي.

ویشل شوي لیږدونه هم په ذهن کې راځي، مګر موږ یې په خپلو حلونو کې نه کاروو: د اعتبار ډاډ ترلاسه کول ستونزمن دي.

"ساګا" د راکړې ورکړې د ستونزې د حل په توګه

د مایکرو خدماتو مخ په ډیریدونکي شهرت سره ، د غوښتنې مخ په ډیریدو دی د ساګا نمونه.

دا نمونه په بشپړه توګه د اوږدې معاملو پورتنۍ ستونزې حل کوي، او همدارنګه د سوداګرۍ منطق له اړخ څخه د سیسټم حالت اداره کولو امکانات پراخوي: د ناکامې معاملې وروسته جبران ممکن سیسټم بیرته خپل اصلي حالت ته نه راولي، مګر یو بدیل وړاندې کوي. د معلوماتو پروسس کولو لاره. دا تاسو ته هم اجازه درکوي چې په بریالیتوب سره بشپړ شوي ډیټا پروسس کولو مرحلې تکرار نه کړئ کله چې تاسو هڅه کوئ چې پروسه "ښه" پای ته ورسوي.

په زړه پورې خبره دا ده چې په monolithic سیسټمونو کې، دا نمونه هم اړونده ده کله چې دا د نرم جوړ شوي فرعي سیسټمونو ادغام ته راځي او د اوږدې راکړې ورکړې او اړوندو سرچینو بندونو له امله منفي اغیزې شتون لري.

د BPM سټایل کې زموږ د سوداګرۍ پروسې په اړه ، دا د ساګاس پلي کول خورا اسانه دي: د ساګاس انفرادي مرحلې د سوداګرۍ پروسې دننه فعالیتونو په توګه تنظیم کیدی شي ، او د سوداګرۍ پروسې دوامداره حالت ټاکي. نور شیان، د ساګاس داخلي حالت. دا، موږ د همغږۍ اضافي میکانیزم ته اړتیا نلرو. ټول هغه څه چې تاسو ورته اړتیا لرئ د پیغام بروکر دی چې د ټرانسپورټ په توګه "لږترلږه یو ځل" تضمینونو ملاتړ کوي.

مګر دا ډول حل هم خپل "قیمت" لري:

  • د سوداګرۍ منطق ډیر پیچلی کیږي: تاسو اړتیا لرئ د خسارې کار وکړئ؛
  • دا به اړین وي چې بشپړ ثبات پریږدي، کوم چې په ځانګړي ډول د واحد سیسټمونو لپاره حساس کیدی شي؛
  • جوړښت یو څه ډیر پیچلی کیږي، د پیغام بروکر لپاره اضافي اړتیا شتون لري؛
  • اضافي څارنې او ادارې وسیلو ته به اړتیا وي (که څه هم په عمومي ډول دا حتی ښه دی: د سیسټم خدماتو کیفیت به لوړ شي).

د monolithic سیسټمونو لپاره، د "Sags" کارولو توجیه دومره څرګنده نه ده. د مایکرو خدماتو او نورو SOAs لپاره ، چیرې چې ډیری احتمال ، دمخه یو بروکر شتون لري ، او د پروژې په پیل کې بشپړ دوام قرباني شوی و ، د دې نمونې کارولو ګټې کولی شي د پام وړ زیانونو څخه ډیر وي ، په ځانګړي توګه که چیرې په کې مناسب API شتون ولري. د سوداګرۍ منطق کچه.

په مایکرو خدماتو کې د سوداګرۍ منطق ضمیمه کول

کله چې موږ د مایکرو خدماتو سره تجربه پیل کړه، یو معقول پوښتنه راپورته شوه: د ډومین سوداګرۍ منطق د هغه خدمت په اړه چیرته چې د ډومین ډیټا دوام چمتو کوي؟

کله چې د مختلف BPMS جوړښت ته ګورو ، نو دا ممکن مناسب ښکاري چې د سوداګرۍ منطق له دوام څخه جلا کړئ: د پلیټ فارم او ډومین - خپلواک مایکرو خدماتو یوه پرت رامینځته کړئ چې د ډومین سوداګرۍ منطق پلي کولو لپاره چاپیریال او کانټینر رامینځته کوي ، او د ډومین ډیټا دوام د جلا په توګه تنظیموي. د خورا ساده او لږ وزن لرونکي مایکرو خدماتو پرت. پدې حالت کې د سوداګرۍ پروسې د دوام پرت خدمتونه تنظیموي.

د BPM سټایل ادغام

دا طریقه خورا لوی پلس لري: تاسو کولی شئ د پلیټ فارم فعالیت هرڅومره چې وغواړئ ډیر کړئ ، او یوازې د پلیټ فارم مایکرو خدماتو ورته پرت به له دې څخه "غوړ ترلاسه کړي". د هرې ډومین څخه سوداګرۍ پروسې سمدلاسه فرصت ترلاسه کوي چې د پلیټ فارم نوي فعالیت کارولو سره سمدلاسه تازه شي.

یوې ډیرې مفصلې مطالعې د دې طریقې مهمې نیمګړتیاوې په ګوته کړې:

  • د پلیټ فارم خدمت چې په یوځل کې د ډیری ډومینونو سوداګرۍ منطق اجرا کوي د ناکامۍ د یوې نقطې په توګه لوی خطرونه لري. د سوداګرۍ منطق کې پرله پسې بدلونونه د بګ خطر زیاتوي چې د سیسټم پراخه ناکامۍ لامل کیږي؛
  • د فعالیت مسلې: د سوداګرۍ منطق د خپل ډیټا سره د یو تنګ او ورو انٹرفیس له لارې کار کوي:
    • ډاټا به یو ځل بیا د شبکې سټیک له لارې مارشال او پمپ شي؛
    • د ډومین خدمت به ډیری وختونه د پروسس کولو لپاره د سوداګرۍ منطق اړتیا څخه ډیر ډیټا بیرته راستانه کړي، د خدماتو د بهرني API په کچه د ناکافي پوښتنو پیرامیټریز کولو وړتیاو له امله؛
    • د سوداګرۍ منطق څو خپلواکې ټوټې کولی شي په مکرر ډول د پروسس کولو لپاره ورته ډیټا بیا غوښتنه وکړي (تاسو کولی شئ دا ستونزه د سیشن لوبیا په اضافه کولو سره کمه کړئ چې ډیټا کیش کوي ، مګر دا جوړښت نور هم پیچلی کوي او د ډیټا تازه کیدو او کیچ باطلیدو ستونزې رامینځته کوي)؛
  • د راکړې ورکړې ستونزې:
    • د پلیټ فارم خدمت لخوا زیرمه شوي دوامداره حالت سره د سوداګرۍ پروسې د ډومین ډیټا سره متناسب دي ، او د دې ستونزې حل کولو لپاره هیڅ اسانه لار شتون نلري؛
    • د لیږد څخه بهر د ډومین ډیټا تالاش حرکت کول: که چیرې د ډومین سوداګرۍ منطق بدلونونو ته اړتیا ولري ، لومړی د ریښتیني ډیټا درستیت چیک کولو وروسته ، دا اړینه ده چې په پروسس شوي ډیټا کې د رقابتي بدلون احتمال خارج کړئ. د معلوماتو بهرنۍ بلاک کول کولی شي د ستونزې په حل کې مرسته وکړي، مګر دا ډول حل اضافي خطرونه لري او د سیسټم عمومي اعتبار کموي؛
  • اضافي پیچلتیاوې کله چې تازه کول: په ځینو مواردو کې، تاسو اړتیا لرئ چې د دوام خدمت او سوداګرۍ منطق په همغږي یا سخت ترتیب کې تازه کړئ.

په پای کې، زه باید اساساتو ته بیرته لاړ شم: د ډومین ډیټا او د ډومین سوداګرۍ منطق په یو مایکروسافټ کې ځای پرځای کړئ. دا طریقه په سیسټم کې د یوې بشپړې برخې په توګه د مایکرو سرویس تصور ساده کوي او پورته ستونزو ته وده نه ورکوي. دا هم وړیا نه ده:

  • د سوداګرۍ منطق سره د متقابل عمل لپاره د API معیاري کول اړین دي (په ځانګړي توګه د سوداګرۍ پروسو برخې په توګه د کارونکي فعالیتونه چمتو کول) او د API پلیټ فارم خدماتو؛ د API بدلونونو ته ډیر محتاط پاملرنه، مخکې او شاته مطابقت ته اړتیا ده؛
  • دا اړینه ده چې د چلولو اضافي کتابتونونه اضافه کړئ ترڅو د هر ډول مایکرو خدماتو برخې په توګه د سوداګرۍ منطق فعالیت ډاډمن کړي، او دا د دې ډول کتابتونونو لپاره نوي اړتیاوې رامینځته کوي: روښانتیا او لږ تر لږه انتقالي انحصار؛
  • د سوداګرۍ منطق پراختیا کونکي اړتیا لري چې د کتابتون نسخې تعقیب کړي: که چیرې مایکرو خدمت د اوږدې مودې لپاره نه وي بشپړ شوی ، نو دا به ډیری احتمال د کتابتونونو پخوانۍ نسخه ولري. دا کیدی شي د نوي فیچر د اضافه کولو لپاره یو غیر متوقع خنډ وي او کیدای شي د داسې خدمت زاړه سوداګریز منطق ته اړتیا ولري چې د کتابتونونو نوي نسخو ته لیږدول کیږي که چیرې د نسخو ترمنځ غیر متناسب بدلونونه شتون ولري.

د BPM سټایل ادغام

په ورته جوړښت کې د پلیټ فارم خدماتو یوه پرت هم شتون لري ، مګر دا پرت نور د ډومین سوداګرۍ منطق اجرا کولو لپاره کانټینر نه جوړوي ، مګر یوازې د دې چاپیریال ، د معاون "پلیټ فارم" دندې چمتو کوي. دا ډول پرت نه یوازې د ډومین مایکرو خدماتو روښانتیا ساتلو لپاره ، بلکه د مدیریت مرکزي کولو لپاره هم اړتیا لري.

د مثال په توګه، د سوداګرۍ پروسو کې د کاروونکي فعالیتونه دندې تولیدوي. په هرصورت، کله چې د دندو سره کار کوي، کاروونکي باید په عمومي لیست کې د ټولو ډومینونو څخه دندې وګوري، پدې معنی چې د ډومین سوداګرۍ منطق څخه پاک، د کار راجستریشن پلیټ فارم خدمت باید شتون ولري. په دې شرایطو کې د سوداګرۍ منطق ساتل خورا ستونزمن کار دی، او دا د دې جوړښت یو بل جوړجاړی دی.

د غوښتنلیک جوړونکي د سترګو له لارې د سوداګرۍ پروسو ادغام

لکه څنګه چې مخکې یادونه وشوه، د غوښتنلیک پراختیا کونکي باید د ډیری غوښتنلیکونو تعامل پلي کولو تخنیکي او انجینري ځانګړتیاو څخه خلاص شي ترڅو وکوالی شي د ښه پراختیا تولیداتو باندې حساب وکړي.

راځئ هڅه وکړو چې د ادغام یوه ستونزمنه ستونزه حل کړو، په ځانګړې توګه د مقالې لپاره اختراع شوې. دا به د "لوبې" دنده وي چې درې غوښتنلیکونه پکې شامل وي، چیرې چې هر یو یې د ځینې ډومین نوم تعریفوي: "app1"، "app2"، "app3".

د هر غوښتنلیک دننه، د سوداګرۍ پروسې پیل کیږي چې د ادغام بس له لارې "بال لوبې" پیل کوي. د "بال" په نوم پیغامونه به د بال په توګه عمل وکړي.

د لوبې اصول:

  • لومړی لوبغاړی ابتکار دی. هغه نورو لوبغاړو ته لوبې ته بلنه ورکوي، لوبه پیل کوي او هر وخت یې پای ته رسولی شي؛
  • نور لوبغاړي په لوبه کې خپل ګډون اعلانوي، د یو بل او لومړي لوبغاړي سره "پیژني"؛
  • د توپ ترلاسه کولو وروسته، لوبغاړی بل ګډون کوونکی لوبغاړی غوره کوي او توپ هغه ته ورکوي. د پاسونو ټول شمیر شمیرل کیږي؛
  • هر لوبغاړی "انرژی" لري، کوم چې د هغه لوبغاړي لخوا د بال هر پاس سره کمیږي. کله چې انرژي پای ته ورسیږي، لوبغاړی د لوبې څخه لیرې کیږي، د دوی تقاعد اعلانوي؛
  • که لوبغاړی یوازې پریښودل شي، هغه سمدستي د وتلو اعلان کوي؛
  • کله چې ټول لوبغاړي له منځه یوړل شي، لومړی لوبغاړی د لوبې پای اعلانوي. که هغه مخکې لوبه پریښوده، نو دا د بشپړولو لپاره د لوبې تعقیب ته پاتې کیږي.

د دې ستونزې حل کولو لپاره ، زه به زموږ د سوداګرۍ پروسو لپاره DSL وکاروم ، کوم چې تاسو ته اجازه درکوي په کوټلین کې منطق په کلکه توضیح کړئ ، لږترلږه د بویلر پلیټ سره.

په ایپ 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}")
}

د سوداګرۍ منطق پلي کولو سربیره، پورته کوډ کولی شي د سوداګرۍ پروسې یو اعتراض ماډل تولید کړي چې د ډیاګرام په توګه لیدل کیدی شي. موږ تر دې دمه ویژولائزر نه دی پلي کړی، نو موږ باید یو څه وخت په انځور کولو کې تیر کړو (دلته ما د پورتني کوډ سره د ډیاګرام ثبات ته وده ورکولو لپاره د دروازو کارولو په اړه د 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 سټایل ادغام

په هرصورت، دلته یو لنډیز شتون لري: هر غوښتنلیک د ننوتلو په کتار کې د خپل ډومین نوم په واسطه "خپل" پیغامونه فلټر کوي. همچنان ، ډومین په سیګنالونو کې مشخص کیدی شي ، که تاسو اړتیا لرئ د سیګنال "موقع" یو واحد غوښتنلیک ته محدود کړئ. دا باید د بس بینډ ویت زیات کړي، مګر د سوداګرۍ منطق باید اوس د ډومین نومونو سره کار وکړي: د پیغامونو پته کولو لپاره لازمي، د سیګنالونو لپاره مطلوب.

د ادغام بس اعتبار یقیني کول

اعتبار د څو شیانو څخه جوړ شوی دی:

  • د غوره شوي پیغام بروکر د جوړښت یوه مهمه برخه او د ناکامۍ یو واحد ټکی دی: دا باید په کافي اندازه د غلطۍ زغم وي. تاسو باید یوازې د وخت ازمول شوي تطبیقونه د ښه ملاتړ او لویې ټولنې سره وکاروئ.
  • دا اړینه ده چې د پیغام بروکر لوړ شتون یقیني کړي، د کوم لپاره چې دا باید په فزیکي توګه د مدغم شوي غوښتنلیکونو څخه جلا شي (د پلي شوي سوداګرۍ منطق سره د غوښتنلیکونو لوړ شتون خورا ستونزمن او ګران دی)؛
  • بروکر مکلف دی چې "لږترلږه یو ځل" د تحویلي تضمین چمتو کړي. دا د ادغام بس د باور وړ عملیاتو لپاره لازمي اړتیا ده. د "دقیق یو ځل" کچې تضمینونو ته اړتیا نشته: د سوداګرۍ پروسې معمولا د پیغامونو یا پیښو تکرار ته حساس نه وي، او په ځانګړو دندو کې چیرې چې دا مهم وي، د دوامداره کارولو په پرتله د سوداګرۍ منطق ته د اضافي چکونو اضافه کول اسانه دي. بلکه "ګران" " ضمانتونه؛
  • د پیغامونو او سیګنالونو لیږل باید د سوداګرۍ پروسو او ډومین ډیټا حالت کې بدلون سره په ګډه معامله کې دخیل وي. غوره انتخاب به د نمونې کارول وي د راکړې ورکړې بهر بکس، مګر دا به په ډیټابیس کې اضافي میز او ریل ته اړتیا ولري. د JEE غوښتنلیکونو کې، دا د محلي JTA مدیر په کارولو سره ساده کیدی شي، مګر د ټاکل شوي بروکر سره اړیکه باید په حالت کې کار کولو وړ وي XA;
  • د راتلونکو پیغامونو او پیښو سمبالونکي باید د سوداګرۍ پروسې حالت بدلولو لیږد سره هم کار وکړي: که دا ډول معامله بیرته وګرځول شي، نو د پیغام رسید هم باید لغوه شي؛
  • هغه پیغامونه چې د غلطیو له امله نشي رسولی باید په جلا پلورنځي کې زیرمه شي د ‏‎DLQ‎‏ پاڼې اړوند نور معلومات په فسبوک کې اوګورئ (مړ لیک ​​کتار). د دې کولو لپاره، موږ یو جلا پلیټ فارم مایکرو سرویس رامینځته کړی چې دا ډول پیغامونه په خپل ذخیره کې ذخیره کوي، دوی د ځانګړتیاوو (د چټک ګروپ کولو او لټون لپاره) په واسطه شاخص کوي، او API د لیدلو، د منزل پتې ته بیرته لیږل، او د پیغامونو حذف کولو لپاره افشا کوي. د سیسټم مدیران کولی شي د دې خدمت سره د دوی ویب انٹرفیس له لارې کار وکړي؛
  • د بروکر په ترتیباتو کې، تاسو اړتیا لرئ چې د سپارلو تر مینځ د لیږد شمیرې او ځنډونه تنظیم کړئ ترڅو DLQ ته د پیغامونو د رسیدلو احتمال کم کړي (د غوره پیرامیټونو محاسبه کول تقریبا ناممکن دي، مګر تاسو کولی شئ په تجربه سره عمل وکړئ او په جریان کې یې تنظیم کړئ. عملیات)
  • د DLQ پلورنځي باید په دوامداره توګه وڅارل شي، او د څارنې سیسټم باید د سیسټم مدیرانو ته خبر ورکړي ترڅو دوی ژر تر ژره ځواب ووایي کله چې نه لیږل شوي پیغامونه پیښیږي. دا به د ناکامۍ یا سوداګرۍ منطق غلطۍ "د زیان زون" کم کړي؛
  • د ادغام بس باید د غوښتنلیکونو لنډمهاله نشتوالي لپاره حساس وي: د موضوع ګډون باید دوامدار وي، او د غوښتنلیک ډومین نوم باید ځانګړی وي ترڅو بل څوک د غوښتنلیک د نشتوالي په جریان کې د قطار څخه د دې پیغام پروسس کولو هڅه ونه کړي.

د سوداګرۍ منطق د تار خوندیتوب ډاډمن کول

د سوداګرۍ پروسې ورته بیلګه کولی شي په یوځل کې ډیری پیغامونه او پیښې ترلاسه کړي ، چې پروسس به یې په موازي ډول پیل شي. په ورته وخت کې، د غوښتنلیک جوړونکي لپاره، هرڅه باید ساده او د تار څخه خوندي وي.

د پروسې سوداګرۍ منطق هره بهرنۍ پیښه پروسس کوي چې پدې سوداګرۍ پروسه په انفرادي ډول اغیزه کوي. دا پیښې کیدی شي:

  • د مثال په توګه د سوداګرۍ پروسې پیل کول؛
  • د کارونکي عمل د سوداګرۍ پروسې کې د فعالیت پورې اړوند؛
  • د یو پیغام یا سیګنال رسید چې د سوداګرۍ پروسې مثال پکې ګډون کوي؛
  • د سوداګرۍ پروسې مثال لخوا ټاکل شوي ټایمر پای ته رسیدل؛
  • د API له لارې کنټرول عمل (د بیلګې په توګه د پروسې بندول).

هره ورته پیښه کولی شي د سوداګرۍ پروسې حالت بدل کړي مثال: ځینې فعالیتونه پای ته رسیدلی شي او نور پیل شي ، د دوامداره ملکیتونو ارزښتونه بدلیدلی شي. د هر فعالیت بندول ممکن د لاندې فعالیتونو څخه یو یا ډیرو فعالولو پایله ولري. دوی، په بدل کې، کولی شي د نورو پیښو انتظار ودروي، یا، که دوی اضافي معلوماتو ته اړتیا نلري، دوی کولی شي په ورته لیږد کې بشپړ کړي. د لیږد بندولو دمخه، د سوداګرۍ پروسې نوی حالت په ډیټابیس کې زیرمه شوی، چیرته چې دا به د راتلونکي بهرني پیښې انتظار وکړي.

په اړونده ډیټابیس کې زیرمه شوي د دوامداره سوداګرۍ پروسې ډیټا د پروسس کولو خورا مناسب ترکیب دی کله چې د تازه کولو لپاره SELECT کارول کیږي. که یوه معامله د ډیټابیس څخه د سوداګرۍ پروسې حالت د دې بدلولو لپاره اداره کړي ، نو په موازي ډول هیڅ بل معامله نشي کولی د بل بدلون لپاره ورته حالت ترلاسه کړي ، او د لومړۍ معاملې له بشپړیدو وروسته ، دویمه معامله ده. د مخکې بدل شوي حالت ترلاسه کولو تضمین.

د DBMS اړخ کې د نا امیدۍ لاکونو کارول ، موږ ټول اړین اړتیاوې پوره کوو اسيد، او د چلولو مثالونو شمیر په زیاتولو سره د سوداګرۍ منطق سره د غوښتنلیک اندازه کولو وړتیا هم ساتي.

په هرصورت، نا امیدي قلفونه موږ ته د ځنډیدو ګواښ کوي، پدې معنی چې د تازه کولو لپاره انتخاب باید لاهم د سوداګرۍ منطق کې په ځینو سختو قضیو کې د ځنډیدو په صورت کې یو څه مناسب وخت ته محدود وي.

بله ستونزه د سوداګرۍ پروسې د پیل ترکیب دی. پداسې حال کې چې د سوداګرۍ پروسې هیڅ مثال شتون نلري ، په ډیټابیس کې هیڅ حالت شتون نلري ، نو تشریح شوی میتود به کار ونکړي. که تاسو غواړئ په یوه ځانګړي دائره کې د سوداګرۍ پروسې مثال انفراديتوب ډاډ ترلاسه کړئ ، نو تاسو د پروسې ټولګي او اړونده ساحې پورې تړلي یو ډول همغږي کولو څیز ته اړتیا لرئ. د دې ستونزې د حل لپاره، موږ د تالاشۍ مختلف میکانیزم کاروو چې موږ ته اجازه راکوي چې د یو بهرني خدمت له لارې د URI په بڼه کې د کیلي لخوا مشخص شوي په خپل سري سرچینې باندې یو لاک واخلو.

زموږ په مثالونو کې، د ابتدايي پلیر سوداګرۍ پروسه یوه اعلامیه لري

uniqueConstraint = UniqueConstraints.singleton

له همدې امله، لاګ د اړونده کیلي د قلف اخیستلو او خوشې کولو په اړه پیغامونه لري. د نورو سوداګریزو پروسو لپاره هیڅ ډول پیغامونه شتون نلري: یو ځانګړی محدودیت ندی ټاکل شوی.

د دوامداره حالت سره د سوداګرۍ پروسې ستونزې

ځینې ​​​​وختونه د دوامداره حالت درلودل نه یوازې مرسته کوي، بلکې په حقیقت کې د پرمختګ مخه نیسي.
ستونزې پیل کیږي کله چې تاسو د سوداګرۍ منطق او / یا د سوداګرۍ پروسې ماډل کې بدلونونو ته اړتیا لرئ. هیڅ داسې بدلون نه موندل کیږي چې د سوداګرۍ پروسو له زاړه حالت سره مطابقت ولري. که چیرې په ډیټابیس کې ډیری "ژوندی" مثالونه شتون ولري، نو د نامناسب بدلونونو رامینځته کول د ډیرو ستونزو لامل کیدی شي، کوم چې موږ ډیری وختونه د jBPM کارولو په وخت کې ورسره مخ کیږو.

د بدلون په ژوروالي پورې اړه لري، تاسو کولی شئ په دوو لارو عمل وکړئ:

  1. د نوي سوداګرۍ پروسې ډول رامینځته کړئ ترڅو په زاړه کې نامناسب بدلونونه رامینځته نشي ، او د نوي مثالونو پیل کولو پرمهال د زاړه پرځای یې وکاروئ. زاړه مثالونه به "زوړ لاره" کار ته دوام ورکړي؛
  2. د سوداګرۍ منطق تازه کولو پر مهال د سوداګرۍ پروسو دوامداره حالت ته مهاجرت وکړئ.

لومړی لاره ساده ده، مګر خپل محدودیتونه او زیانونه لري، د بیلګې په توګه:

  • د ډیری سوداګرۍ پروسې ماډلونو کې د سوداګرۍ منطق نقل کول ، د سوداګرۍ منطق حجم کې زیاتوالی؛
  • ډیری وختونه د نوي سوداګرۍ منطق ته سمدستي لیږد ته اړتیا وي (تقریبا تل د ادغام دندو په شرایطو کې)؛
  • پراختیا کونکی نه پوهیږي چې په کوم وخت کې د ناپاک ماډلونو حذف کول ممکن دي.

په عمل کې، موږ دواړه طریقې کاروو، مګر زموږ د ژوند ساده کولو لپاره یو شمیر پریکړې کړې دي:

  • په ډیټابیس کې، د سوداګرۍ پروسې دوامداره حالت په اسانۍ سره د لوستلو وړ او په اسانۍ سره پروسس شوي بڼه کې زیرمه کیږي: د JSON فارمیټ تار کې. دا تاسو ته اجازه درکوي د غوښتنلیک دننه او بهر دواړه مهاجرتونه ترسره کړئ. په سختو قضیو کې، تاسو کولی شئ دا د لاسونو سره ټیک کړئ (په ځانګړې توګه د ډیبګ کولو پرمهال په پراختیا کې ګټور)؛
  • د ادغام سوداګرۍ منطق د سوداګرۍ پروسو نومونه نه کاروي، نو په هر وخت کې دا ممکنه ده چې د ګډون کوونکو پروسو څخه یو پلي کول په نوي نوم سره بدل کړئ (د مثال په توګه، "InitialPlayerV2"). پابند د پیغامونو او سیګنالونو نومونو له لارې رامینځته کیږي؛
  • د پروسې ماډل د نسخې شمیره لري، کوم چې موږ یې زیاتوو که چیرې موږ په دې ماډل کې نامناسب بدلونونه رامنځته کړو، او دا شمیره د پروسې د حالت سره یوځای ساتل کیږي؛
  • د پروسې دوامداره حالت لومړی له بیس څخه په مناسب موډل کې لوستل کیږي چې د مهاجرت کړنلاره کولی شي کار وکړي که چیرې د ماډل نسخه شمیره بدله شوې وي؛
  • د مهاجرت طرزالعمل د سوداګرۍ منطق سره څنګ ته ایښودل شوی او د ډیټابیس څخه د بیا رغولو په وخت کې د سوداګرۍ پروسې د هرې بیلګې لپاره "سست" بلل کیږي؛
  • که تاسو اړتیا لرئ د ټولو پروسې مثالونو حالت ګړندي او همغږي کړئ ، د ډیټابیس ډیر کلاسیک مهاجرت حلونه کارول کیږي ، مګر تاسو باید هلته د JSON سره کار وکړئ.

ایا زه د سوداګرۍ پروسو لپاره بل چوکاټ ته اړتیا لرم؟

په مقاله کې بیان شوي حلونه موږ ته اجازه راکوي چې خپل ژوند د پام وړ ساده کړو ، د غوښتنلیک پراختیا کچه کې حل شوي مسلو پراخه کړو ، او د سوداګرۍ منطق جلا کولو نظر په مایکرو خدماتو کې ډیر په زړه پوري کړو. د دې لپاره، ډیری کار ترسره شوی، د سوداګرۍ پروسو لپاره خورا "لږ وزن" چوکاټ رامینځته شوی، او همدارنګه د پراخو پلي شویو دندو په شرایطو کې د پیژندل شویو ستونزو حل کولو لپاره د خدماتو برخې. موږ هیله لرو چې دا پایلې شریکې کړو، ترڅو د ګډو برخو پراختیا د وړیا جواز لاندې خلاص لاسرسي ته راوړو. دا به یو څه هڅې او وخت ته اړتیا ولري. د دې ډول حلونو غوښتنې پوهیدل زموږ لپاره اضافي هڅونه کیدی شي. په وړاندیز شوې مقاله کې، پخپله د چوکاټ وړتیاوو ته ډیره لږه پاملرنه شوې، مګر ځینې یې د وړاندې شویو مثالونو څخه څرګندیږي. که بیا هم موږ خپل چوکاټ خپور کړو، یو جلا مقاله به ورته وقف شي. په ورته وخت کې، موږ به مننه وکړو که تاسو د پوښتنې په ځواب کې یو څه نظر پریږدئ:

یوازې راجستر شوي کاروونکي کولی شي په سروې کې برخه واخلي. ننوزئمهرباني وکړئ

ایا زه د سوداګرۍ پروسو لپاره بل چوکاټ ته اړتیا لرم؟

  • ۸۵٪هو، زه له ډیرې مودې راهیسې د دې په لټه کې یم.

  • ۸۵٪دا په زړه پورې ده چې ستاسو د پلي کولو په اړه نور معلومات زده کړئ، دا ممکن ګټور وي2

  • ۸۵٪موږ یو له موجوده چوکاټونو څخه کار اخلو، مګر موږ د هغې د ځای په ځای کولو فکر کوو

  • ۸۵٪موږ یو له موجوده چوکاټونو څخه کار اخلو، هرڅه مناسب دي

  • ۸۵٪له چوکاټ پرته مقابله 3

  • ۸۵٪خپل ځان ولیکئ 4

16 کاروونکو رایه ورکړه. 7 کاروونکي منع شوي.

سرچینه: www.habr.com

Add a comment