Comhtháthú stíl BPM

Comhtháthú stíl BPM

Dia dhuit, Habr!

Déanann ár gcuideachta speisialtóireacht i bhforbairt réitigh bogearraí ERP-aicme, a bhfuil sciar an leon de á áitiú ag córais idirbheartaíochta le méid ollmhór loighic ghnó agus sreabhadh doiciméad a la EDMS. Tá leaganacha reatha dár dtáirgí bunaithe ar theicneolaíochtaí JavaEE, ach táimid ag tástáil go gníomhach le micreasheirbhísí freisin. Ar cheann de na réimsí is mó a bhfuil fadhb ag baint leis na réitigh sin tá comhtháthú na bhfochóras éagsúla a bhaineann le fearainn in aice láimhe. Thug fadhbanna comhtháthaithe tinneas cinn ollmhór dúinn i gcónaí, beag beann ar na stíleanna ailtireachta, na stoic theicneolaíochta agus na creataí a úsáidimid, ach le déanaí tá dul chun cinn déanta maidir le fadhbanna den sórt sin a réiteach.

San alt a tharraingeoidh mé d’aird, labhróidh mé faoin taithí agus faoin taighde ailtireachta atá ag NPO Krista sa limistéar ainmnithe. Breathnóimid freisin ar shampla de réiteach simplí ar fhadhb chomhtháthaithe ó thaobh forbróir feidhmchláir de agus faighfimid amach cad atá i bhfolach taobh thiar den simplíocht seo.

Séanadh

Tá na réitigh ailtireachta agus theicniúla a bhfuil cur síos orthu san alt molta agam bunaithe ar thaithí phearsanta i gcomhthéacs tascanna sonracha. Ní mhaíonn na réitigh seo gur réitigh uilíocha iad agus b’fhéidir nach bhfuil siad optamach faoi choinníollacha úsáide eile.

Cad a chaithfidh BPM a dhéanamh leis?

Chun an cheist seo a fhreagairt, ní mór dúinn iniúchadh a dhéanamh beagán níos doimhne ar na sonraí a bhaineann le fadhbanna feidhme ár réitigh. Is í an phríomhchuid den loighic ghnó inár ngnáthchóras idirbheartaíochta ná sonraí a iontráil isteach sa bhunachar sonraí trí chomhéadain úsáideora, fíorú láimhe agus uathoibrithe na sonraí seo, é a dhéanamh trí roinnt sreabhadh oibre, é a fhoilsiú chuig córas eile / bunachar sonraí anailíse / cartlainne, tuarascálacha a ghiniúint. . Mar sin, is é príomhfheidhm an chórais do chustaiméirí uathoibriú a bpróisis ghnó inmheánacha.

Ar mhaithe le caoithiúlacht, bainimid úsáid as an téarma “doiciméad” sa chumarsáid mar astarraingt éigin ar thacar sonraí arna aontú le heochair choiteann ar féidir sreabhadh oibre áirithe a “nascadh leis”.
Ach cad faoi loighic an chomhtháthaithe? Tar éis an tsaoil, gineann ailtireacht an chórais an tasc comhtháthaithe, a "ghearrtar" ina chodanna NACH ar iarratas an chustaiméara, ach faoi thionchar fachtóirí go hiomlán difriúil:

  • faoi ​​réir dhlí Conway;
  • mar thoradh ar fhochórais a forbraíodh roimhe seo le haghaidh táirgí eile a athúsáid;
  • de rogha an ailtire, bunaithe ar riachtanais neamhfheidhmiúla.

Tá temptation mór ann loighic chomhtháthaithe a scaradh ó loighic ghnó an phríomhshreafa oibre, ionas nach ndéanfaidh sé truailliú ar an loighic gnó le déantáin chomhtháthaithe agus forbróir an iarratais a shábháil ón ngá atá le dul isteach i ngnéithe tírdhreacha ailtireachta an chórais. Tá roinnt buntáistí ag baint leis an gcur chuige seo, ach léiríonn cleachtas a neamhéifeachtúlacht:

  • de ghnáth go dtiteann réiteach fadhbanna comhtháthaithe ar ais go dtí na roghanna is simplí i bhfoirm glaonna sioncrónacha mar gheall ar na pointí síneadh teoranta i gcur i bhfeidhm an phríomhshreafa oibre (pléitear thíos na míbhuntáistí a bhaineann le comhtháthú sioncronach);
  • téann déantáin chomhtháthaithe isteach i gcroí-loighic an ghnó fós nuair a bhíonn aiseolas ó fhochóras eile ag teastáil;
  • déanann forbróir an iarratais neamhaird ar an gcomhtháthú agus is féidir é a bhriseadh go héasca tríd an sreabhadh oibre a athrú;
  • scoireann an córas de bheith ina iomláine amháin ó thaobh an úsáideora de, éiríonn “seams” idir fochórais faoi deara, agus tagann oibríochtaí úsáideora iomarcacha le feiceáil, ag cur tús le haistriú sonraí ó fhochóras amháin go fochóras eile.

Cur chuige eile is ea idirghníomhaíochtaí comhtháthaithe a mheas mar chuid lárnach den loighic lárnach gnó agus de shreabhadh oibre. Chun cáilíochtaí forbróirí feidhmchlár a chosc ó skyrocketing, ba cheart go mbeadh cruthú idirghníomhaíochtaí lánpháirtithe nua éasca agus gan stró, le roghanna íosta maidir le réiteach a roghnú. Tá sé seo níos deacra ná mar is cosúil: ní mór don uirlis a bheith cumhachtach go leor chun an éagsúlacht riachtanach roghanna a sholáthar don úsáideoir lena húsáid, gan ligean dó "é féin a lámhach sa chos." Tá go leor ceisteanna ann nach mór d’innealtóir a fhreagairt i gcomhthéacs tascanna comhtháthaithe, ach nár cheart d’fhorbróir feidhmchláir smaoineamh orthu ina chuid oibre laethúil: teorainneacha idirbhirt, comhsheasmhacht, adamhacht, slándáil, scálú, dáileadh ualaigh agus acmhainní, ródú, marsáil, comhthéacsanna dáileacháin agus aistrithe, etc. Is gá teimpléid réitigh simplí go leor a thairiscint d'fhorbróirí feidhmchlár ina bhfuil freagraí na gceisteanna sin i bhfolach cheana féin. Ní mór na teimpléid seo a bheith measartha sábháilte: is minic a athraíonn an loighic gnó, rud a mhéadaíonn an baol go dtabharfar isteach earráidí, ní mór go bhfanfadh costas na n-earráidí ag leibhéal measartha íseal.

Ach cad a chaithfidh BPM a dhéanamh leis? Tá go leor roghanna ann chun sreabhadh oibre a chur i bhfeidhm ...
Go deimhin, tá an-tóir ar ár gcuid réitigh eile a chur i bhfeidhm ar phróisis ghnó - tríd an sainmhíniú dearbhach ar léaráid aistrithe stáit agus trí láimhseálaithe a nascadh le loighic gnó le haghaidh aistrithe. Sa chás seo, is tréith den “dhoiciméad” féin é an stát a chinneann staid reatha an “dhoiciméid” sa phróiseas gnó.

Comhtháthú stíl BPM
Seo an chuma atá ar an bpróiseas ag tús tionscadail

Tá an tóir a bhí ar an gcur chun feidhme seo mar gheall ar an simplíocht choibhneasta agus an luas a bhaineann le próisis ghnó líneacha a chruthú. Mar sin féin, de réir mar a éiríonn córais bogearraí níos casta i gcónaí, fásann an chuid uathoibrithe den phróiseas gnó agus éiríonn sé níos casta. Tá gá le dianscaoileadh, athúsáid codanna de phróisis, chomh maith le próisis branching ionas go ndéanfar gach brainse a fhorghníomhú go comhthreomhar. Faoi choinníollacha den sórt sin, éiríonn an uirlis deacair, agus cailleann an léaráid trasdula stáit a ábhar faisnéise (ní léirítear idirghníomhaíochtaí comhtháthú sa léaráid ar chor ar bith).

Comhtháthú stíl BPM
Is é seo an chuma atá ar an bpróiseas tar éis roinnt atriallta de shoiléiriú ceanglais.

Ba é an bealach amach as an staid seo ná comhtháthú an innill jBPM isteach i roinnt táirgí a bhfuil na próisis ghnó is casta acu. Sa ghearrthéarma, d’éirigh go maith leis an réiteach seo: bhíothas in ann próisis chasta ghnó a chur i bhfeidhm agus léaráid sách faisnéiseach agus ábhartha a choinneáil sa nodaireacht. BPMN2.

Comhtháthú stíl BPM
Cuid bheag de phróiseas casta gnó

San fhadtéarma, níor chomhlíon an réiteach na hionchais: níor cheadaigh an déine saothair ard a bhaineann le próisis ghnó a chruthú trí uirlisí amhairc táscairí táirgiúlachta inghlactha a bhaint amach, agus tháinig an uirlis féin ar cheann de na cinn is mó nár thaitin leis i measc forbróirí. Bhí gearáin ann freisin faoi struchtúr inmheánach an innill, rud a d’fhág gur chuma go leor “paistí” agus “crutches”.

Ba í an phríomhghné dhearfach a bhain le jBPM a úsáid ná an fheasacht ar na tairbhí agus na dochair a bhaineann le staid marthanach a bheith ag cás próisis ghnó féin. Chonaiceamar freisin go bhféadfaí cur chuige próisis a úsáid chun prótacail chomhtháite casta a chur i bhfeidhm idir feidhmchláir éagsúla ag baint úsáide as idirghníomhaíochtaí asincrónacha trí chomharthaí agus teachtaireachtaí. Tá ról ríthábhachtach ag láithreacht staid mharthanach ina leith seo.

Bunaithe ar an méid thuas, is féidir linn a thabhairt i gcrích: Ligeann cur chuige an phróisis i stíl BPM dúinn raon leathan tascanna a réiteach chun próisis ghnó atá ag éirí níos casta a uathoibriú, gníomhaíochtaí comhtháthaithe a oiriúnú go comhchuí sna próisis seo agus an cumas an próiseas curtha i bhfeidhm a thaispeáint go radhairc i nodaireacht oiriúnach.

Míbhuntáistí glaonna sioncrónacha mar phatrún comhtháthaithe

Tagraíonn comhtháthú sioncrónach don ghlao blocála is simplí. Feidhmíonn fochóras amháin mar thaobh an fhreastalaí agus nochtar an API leis an modh riachtanach. Feidhmíonn fochóras eile mar thaobh an chliaint agus déanann sé glaoch ag an am ceart agus fanann sé leis an toradh. Ag brath ar ailtireacht an chórais, is féidir taobh an chliaint agus an fhreastalaí a lonnú san fheidhmchlár agus sa phróiseas céanna, nó i gcinn éagsúla. Sa dara cás, ní mór duit roinnt cur chun feidhme RPC a chur i bhfeidhm agus marshalling na bparaiméadar agus toradh an ghlao a chur ar fáil.

Comhtháthú stíl BPM

Tá sraith measartha mór míbhuntáistí ag an bpatrún comhtháthaithe seo, ach úsáidtear é go forleathan i gcleachtas mar gheall ar a simplíocht. Meallann luas an chur chun feidhme agus cuireann sé iallach ort é a úsáid arís agus arís eile in aghaidh spriocdhátaí práinneacha, agus an réiteach á thaifeadadh mar fhiachas teicniúil. Ach tarlaíonn sé freisin go n-úsáideann forbróirí gan taithí é gan aithne, gan na hiarmhairtí diúltacha a bhaint amach.

Chomh maith leis an méadú is soiléire ar nascacht an fhochórais, tá fadhbanna nach bhfuil chomh soiléir céanna le hidirbhearta “fás” agus “sínte”. Go deimhin, má dhéanann an loighic gnó roinnt athruithe, ansin ní féidir idirbhearta a sheachaint, agus idirbhearta, ar a seal, bac a chur ar acmhainní iarratais áirithe tionchar ag na hathruithe seo. Is é sin, go dtí go bhfanfaidh fochóras amháin le freagra ón gceann eile, ní bheidh sé in ann an t-idirbheart a chríochnú agus na glais a bhaint. Méadaíonn sé seo go mór an baol go mbeidh éifeachtaí éagsúla ann:

  • Cailltear freagrúlacht an chórais, fanann úsáideoirí ar feadh i bhfad le haghaidh freagraí ar iarratais;
  • go ginearálta stopann an freastalaí freagra a thabhairt ar iarratais úsáideoirí mar gheall ar chomhthiomsú snáitheanna plódaithe: tá formhór na snáitheanna glasáilte ar acmhainn atá á áitiú ag idirbheart;
  • Tosaíonn spriocanna ama le feiceáil: braitheann an dóchúlacht go dtarlóidh siad go mór ar fhad na n-idirbheart, ar an méid loighic gnó agus na glais a bhaineann leis an idirbheart;
  • tá earráidí teorann ama idirbhirt le feiceáil;
  • “teipeann” ar an bhfreastalaí le OutOfMemory má éilíonn an tasc méideanna móra sonraí a phróiseáil agus a athrú, agus má bhíonn comhtháthú sioncronach ann, bíonn sé an-deacair an phróiseáil a roinnt ina hidirbhearta “níos éadroime”.

Ó thaobh na hailtireachta de, mar thoradh ar úsáid glaonna blocála le linn an chomhtháthaithe go gcailltear smacht ar cháilíocht na bhfochóras aonair: tá sé dodhéanta sprioc-tháscairí cáilíochta fochórais amháin a áirithiú scoite ó tháscairí cáilíochta fochórais eile. Má fhorbraíonn foirne éagsúla fochórais, is fadhb mhór é seo.

Éiríonn rudaí níos suimiúla fós má tá na fochórais atá á gcomhtháthú in iarratais éagsúla agus go gcaithfidh tú athruithe sioncrónacha a dhéanamh ar an dá thaobh. Conas idirbheartaíocht na n-athruithe seo a chinntiú?

Má dhéantar athruithe ar idirbhearta ar leithligh, ansin beidh ort láimhseáil agus cúiteamh eisceachta iontaofa a sholáthar, agus cuireann sé seo deireadh go hiomlán leis an bpríomhbhuntáiste a bhaineann le comhtháthú sioncrónach - simplíocht.

Tagann idirbhearta dáileacháin chun cuimhne freisin, ach ní úsáidimid iad inár réitigh: tá sé deacair iontaofacht a chinntiú.

"Saga" mar réiteach ar an bhfadhb idirbheart

Leis an éileamh atá ag fás ar mhicrosheirbhísí, tá an t-éileamh ar Patrún Saga.

Réitíonn an patrún seo go foirfe na fadhbanna thuasluaite a bhaineann le hidirbhearta fada, agus leathnaíonn sé freisin na cumais a bhaineann le staid an chórais a bhainistiú ó thaobh na loighice gnó: ní fhéadfaidh cúiteamh tar éis idirbheart teipthe an córas a rolladh ar ais go dtí a staid bhunaidh, ach a chur ar fáil. bealach próiseála sonraí eile. Ligeann sé seo duit freisin gan athrá a dhéanamh ar chéimeanna próiseála sonraí a críochnaíodh go rathúil agus tú ag iarraidh an próiseas a thabhairt chun críche “maith”.

Is díol suntais é, i gcórais mhonailiteacha, tá an patrún seo ábhartha freisin maidir le comhtháthú fochóras atá cúpláilte go scaoilte agus breathnaítear ar éifeachtaí diúltacha a bhíonn mar thoradh ar idirbhearta fadtéarmacha agus na glais acmhainní comhfhreagracha.

Maidir lenár bpróisis ghnó i stíl BPM, is léir go bhfuil sé an-éasca “Sagas” a chur i bhfeidhm: is féidir céimeanna aonair an “Saga” a shonrú mar ghníomhaíochtaí laistigh den phróiseas gnó, agus is féidir staid leanúnach an phróisis ghnó a shonrú freisin. chinneann staid inmheánach an "Saga". Is é sin le rá, ní theastaíonn aon sásra comhordaithe breise uainn. Níl uait ach bróicéir teachtaireachtaí a thacaíonn le ráthaíochtaí “uair amháin ar a laghad” mar iompar.

Ach tá a “phraghas” féin ag an réiteach seo freisin:

  • éiríonn loighic ghnó níos casta: ní mór cúiteamh a oibriú amach;
  • beidh sé riachtanach comhsheasmhacht iomlán a thréigean, rud a d'fhéadfadh a bheith go háirithe íogair do chórais monolithic;
  • Éiríonn an ailtireacht beagán níos casta, agus is cosúil go bhfuil gá breise le bróicéir teachtaireachta;
  • beidh gá le huirlisí breise faireacháin agus riaracháin (cé go bhfuil sé seo go maith go ginearálta: tiocfaidh méadú ar cháilíocht na seirbhíse córais).

I gcás córais monolithic, níl an bonn cirt le húsáid "Sag" chomh soiléir. I gcás microservices agus SOA eile, nuair is dóichí go bhfuil bróicéir ann cheana féin, agus go ndéantar comhsheasmhacht iomlán a íobairt ag tús an tionscadail, is féidir na buntáistí a bhaineann leis an bpatrún seo a úsáid go suntasach ná na míbhuntáistí, go háirithe má tá API áisiúil ag an loighic ghnó. leibhéal.

Ag cuimsiú loighic gnó i micreasheirbhísí

Nuair a thosaigh muid ag triail le micreasheirbhísí, tháinig ceist réasúnta chun cinn: cén áit ar cheart an loighic gnó fearainn a chur i ndáil leis an tseirbhís a chinntíonn marthanacht na sonraí fearainn?

Nuair a fhéachtar ar ailtireacht BPMSanna éagsúla, d’fhéadfadh sé a bheith réasúnta loighic ghnó a scaradh ó bhuanseasmhacht: sraith de mhicrisheirbhísí ardáin agus fearainn-neamhspleách a chruthú a chruthaíonn timpeallacht agus coimeádán chun loighic gnó fearainn a fhorghníomhú, agus marthanacht na sonraí fearainn a dhearadh mar sraith ar leith de mhicrisheirbhísí an-simplí agus éadroma. Próisis ghnó sa chás seo a dhéanamh orchestration ar sheirbhísí an ciseal marthanachta.

Comhtháthú stíl BPM

Tá buntáiste an-mhór ag an gcur chuige seo: is féidir leat feidhmiúlacht an ardáin a mhéadú oiread agus is mian leat, agus ní éireoidh ach an ciseal comhfhreagrach de mhicreirbhísí ardáin "saill" as seo. Tá próisis ghnó ó aon fhearann ​​in ann feidhmiúlacht nua an ardáin a úsáid láithreach a luaithe a nuashonraítear é.

Léirigh staidéar níos mionsonraithe míbhuntáistí suntasacha a bhaineann leis an gcur chuige seo:

  • tá rioscaí móra ag baint le seirbhís ardáin a fheidhmíonn loighic ghnó go leor fearainn ag an am céanna mar phointe aonair teipe. Méadaíonn athruithe go minic ar loighic ghnó an riosca earráidí as a dtagann teipeanna ar fud an chórais;
  • saincheisteanna feidhmíochta: oibríonn loighic ghnó lena sonraí trí chomhéadan caol agus mall:
    • déanfar na sonraí a mhaisigh arís agus a phumpáil tríd an stack líonra;
    • is minic a sholáthróidh seirbhís fearainn níos mó sonraí ná mar a theastaíonn chun an loighic ghnó a phróiseáil toisc nach bhfuil dóthain cumais ann chun iarrataí a pharaiméadarú ar leibhéal API seachtrach na seirbhíse;
    • is féidir le roinnt píosaí neamhspleácha loighic gnó na sonraí céanna a ath-iarraidh arís agus arís eile le haghaidh próiseála (is féidir an fhadhb seo a mhaolú trí chomhpháirteanna seisiúin a chuireann sonraí i dtaisce a chur leis, ach déanann sé seo an ailtireacht níos casta agus cruthaíonn sé fadhbanna a bhaineann le hábharthacht sonraí agus neamhbhailíochtú taisce);
  • fadhbanna idirbheartaíochta:
    • tá próisis ghnó le stát leanúnach, atá stóráilte ag seirbhís ardán, ar neamhréir le sonraí fearainn, agus níl aon bhealaí éasca ann chun an fhadhb seo a réiteach;
    • blocáil sonraí fearainn a chur lasmuigh den idirbheart: más gá don loighic gnó fearainn athruithe a dhéanamh tar éis cruinneas na sonraí reatha a sheiceáil ar dtús, is gá an fhéidearthacht go ndéanfaí athrú iomaíoch ar na sonraí próiseáilte a eisiamh. Is féidir le blocáil sonraí seachtracha cuidiú leis an bhfadhb a réiteach, ach tá rioscaí breise ag baint le réiteach den sórt sin agus laghdaíonn sé iontaofacht iomlán an chórais;
  • deacrachtaí breise le linn nuashonrú: i gcásanna áirithe, is gá an tseirbhís marthanachta agus an loighic ghnó a nuashonrú go sioncrónach nó in ord docht.

I ndeireadh na dála, bhí orainn dul ar ais go dtí na bunghnéithe: sonraí fearainn agus loighic gnó fearainn a chuimsiú i micriseirbhís amháin. Simplíonn an cur chuige seo an dearcadh go bhfuil micreasheirbhís mar chuid lárnach den chóras agus ní eascraíonn na fadhbanna thuas dá bharr. Ní thugtar é seo saor in aisce freisin:

  • Tá gá le caighdeánú API le haghaidh idirghníomhú le loighic gnó (go háirithe, chun gníomhaíochtaí úsáideoirí a sholáthar mar chuid de phróisis ghnó) agus seirbhísí ardán API; éilíonn aird níos cúramach ar athruithe API, comhoiriúnacht ar aghaidh agus ar ais;
  • is gá leabharlanna ama rite breise a chur leis chun a áirithiú go bhfeidhmeoidh loighic an ghnó mar chuid de gach micriseirbhís dá leithéid, agus as sin éiríonn ceanglais nua do leabharlanna den sórt sin: éadroime agus íosmhéid spleáchais idirthréimhseacha;
  • ní mór d’fhorbróirí loighic ghnó monatóireacht a dhéanamh ar leaganacha leabharlainne: mura bhfuil micrseirbhís tugtha chun críche le fada an lá, is dóichí go mbeidh leagan as dáta de na leabharlanna ann. D’fhéadfadh sé seo a bheith ina chonstaic gan choinne ar ghné nua a chur leis agus d’fhéadfadh go mbeadh gá le sean-loighic ghnó seirbhíse den sórt sin a aistriú go leaganacha nua de leabharlanna dá mbeadh athruithe neamh-chomhoiriúnacha idir leaganacha.

Comhtháthú stíl BPM

Tá sraith de sheirbhísí ardáin i láthair freisin in ailtireacht den sórt sin, ach ní coimeádán é an ciseal seo a thuilleadh chun loighic gnó fearainn a chur i gcrích, ach a timpeallacht amháin, ag soláthar feidhmeanna cúnta “ardáin”. Tá gá le ciseal den sórt sin, ní hamháin chun nádúr éadrom na micrisheirbhísí fearainn a choinneáil, ach freisin chun bainistíocht a lárú.

Mar shampla, gineann gníomhaíochtaí úsáideoirí i bpróisis ghnó tascanna. Mar sin féin, nuair a bhíonn sé ag obair le tascanna, ní mór don úsáideoir tascanna a fheiceáil ó gach réimse sa liosta ginearálta, rud a chiallaíonn go gcaithfidh seirbhís clárúcháin tasc ardáin chomhfhreagrach a bheith ann, arna ghlanadh de loighic gnó fearainn. Is fadhb mhór í an loighic ghnó a chuimsiú i gcomhthéacs den sórt sin, agus is comhréiteach eile é seo den ailtireacht seo.

Comhtháthú próisis ghnó trí shúile forbróir feidhmchláir

Mar a luadh thuas, ní mór forbróir feidhmchláir a asbhaint ó na gnéithe teicniúla agus innealtóireachta a bhaineann le hidirghníomhaíocht roinnt iarratas a chur i bhfeidhm ionas gur féidir brath ar tháirgiúlacht forbartha maith.

Déanaimis iarracht fadhb chomhtháthaithe sách deacair a réiteach, a ceapadh go speisialta don alt. Tasc “cluiche” a bheidh anseo ina mbeidh trí fheidhmchlár, ina sainíonn gach ceann acu ainm fearainn áirithe: “app1”, “app2”, “app3”.

Laistigh de gach feidhmchlár, seoltar próisis ghnó a thosaíonn ag “imirt liathróide” tríd an mbus lánpháirtithe. Feidhmeoidh teachtaireachtaí leis an ainm “Liathróid” mar liathróid.

Rialacha an chluiche:

  • is é an chéad imreoir an tionscnóir. Tugann sé cuireadh d’imreoirí eile chuig an gcluiche, tosaíonn sé an cluiche agus féadfaidh sé deireadh a chur leis am ar bith;
  • imreoirí eile a dhearbhú a rannpháirtíocht sa chluiche, "cuir aithne ar" a chéile agus an chéad imreoir;
  • tar éis dó an liathróid a fháil, roghnaíonn an t-imreoir imreoir rannpháirteach eile agus tugann sé an liathróid dó. Déantar líon iomlán na dtarchur a chomhaireamh;
  • Tá "fuinneamh" ag gach imreoir a laghdaíonn gach pas den liathróid ag an imreoir sin. Nuair a ritheann an fuinneamh amach, fágann an t-imreoir an cluiche, ag fógairt go bhfuil sé ag éirí as;
  • má fhágtar an t-imreoir leis féin, fógraíonn sé láithreach go bhfuil sé ag imeacht;
  • Nuair a chuirtear deireadh le gach imreoir, dearbhaíonn an chéad imreoir an cluiche thart. Má fhágann sé an cluiche go luath, fanfaidh sé leis an gcluiche a leanúint chun é a chríochnú.

Chun an fhadhb seo a réiteach, úsáidfidh mé ár DSL le haghaidh próisis ghnó, a ligeann dúinn cur síos a dhéanamh ar an loighic i Kotlin go dlúth, le pláta coire ar a laghad.

Oibreoidh próiseas gnó an chéad imreora (aka thionscnóir an chluiche) san fheidhmchlár app1:

rang TosaighPlayer

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}")
}

Chomh maith le loighic gnó a fhorghníomhú, is féidir leis an gcód thuas samhail réad de phróiseas gnó a tháirgeadh, ar féidir é a léirshamhlú i bhfoirm léaráide. Níl an t-amharcléiritheoir curtha i bhfeidhm againn go fóill, agus mar sin bhí orainn beagán ama a chaitheamh ag tarraingt (anseo rinne mé an nodaireacht BPMN a shimpliú beagán maidir le húsáid geataí chun comhsheasmhacht na léaráide leis an gcód thíos a fheabhsú):

Comhtháthú stíl BPM

Áireoidh app2 próiseas gnó an imreora eile:

RandomPlayer ranga

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}")
}

Léaráid:

Comhtháthú stíl BPM

San fheidhmchlár app3 déanfaimid imreoir a bhfuil iompar beagán difriúil aige: in ionad an chéad imreoir eile a roghnú go randamach, gníomhóidh sé de réir an algartam bhabhta-robín:

RoundRobinPlayer ranga

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}")
}

Seachas sin, ní hionann iompar an imreora agus an ceann roimhe sin, mar sin ní athraíonn an léaráid.

Anois ní mór dúinn tástáil a rith seo go léir. Ní thabharfaidh mé ach cód na tástála féin, ionas nach gcuirfí clutter an t-alt le pláta coire (go deimhin, d'úsáid mé an timpeallacht tástála a cruthaíodh níos luaithe chun comhtháthú próisis ghnó eile a thástáil):

cluiche tástála()

@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;
}

Déanaimis an tástáil a rith agus féachaint ar an loga:

aschur consól

Взята блокировка ключа 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!

As seo go léir is féidir linn roinnt conclúidí tábhachtacha a tharraingt:

  • leis na huirlisí is gá, is féidir le forbróirí feidhmchlár idirghníomhaíochtaí comhtháthú a chruthú idir feidhmchláir gan cur isteach ar loighic gnó;
  • féadfar castacht tasc comhtháthaithe a éilíonn inniúlachtaí innealtóireachta a chur i bhfolach laistigh den chreat má chuirtear é seo san áireamh ar dtús in ailtireacht an chreata. Ní féidir deacracht na faidhbe a chur i bhfolach, mar sin beidh an réiteach ar fhadhb dheacair i gcód cuma air;
  • Agus loighic an chomhtháthaithe á forbairt, tá sé ríthábhachtach comhsheasmhacht sa deireadh agus easpa líneachta na n-athruithe ar staid na rannpháirtithe uile a chur san áireamh. Cuireann sé seo iachall orainn an loighic a chasta chun í a dhéanamh neamhíogair don ord ina dtarlaíonn teagmhais sheachtracha. Inár sampla, cuirtear iallach ar an imreoir páirt a ghlacadh sa chluiche tar éis dó a imeacht ón gcluiche a dhearbhú: leanfaidh imreoirí eile ar aghaidh ag tabhairt na liathróide dó go dtí go sroicheann an t-eolas faoina scoir agus go ndéanann gach rannpháirtí í a phróiseáil. Ní leanann an loighic seo ó rialacha an chluiche agus is réiteach comhréitigh é laistigh de chreat na hailtireachta roghnaithe.

Ansin, beidh muid ag caint faoi na intricacies éagsúla ár réiteach, comhréitigh agus pointí eile.

Tá gach teachtaireacht in aon scuaine amháin

Oibríonn gach feidhmchlár comhtháite le bus comhtháthaithe amháin, a chuirtear i láthair i bhfoirm bróicéir seachtrach, BPMQueue amháin le haghaidh teachtaireachtaí agus topaic BPTopic amháin le haghaidh comharthaí (imeachtaí). Is comhréiteach é gach teachtaireacht a chur trí scuaine amháin. Ag leibhéal loighic an ghnó, is féidir leat a oiread cineálacha nua teachtaireachtaí agus is mian leat a thabhairt isteach anois gan athruithe a dhéanamh ar struchtúr an chórais. Is simpliú suntasach é seo, ach tá rioscaí áirithe ag baint leis, rud nach raibh chomh suntasach dúinn i gcomhthéacs ár ngnáththascanna.

Comhtháthú stíl BPM

Mar sin féin, tá subtlety amháin anseo: scagtar gach feidhmchlár teachtaireachtaí “a” ón scuaine ag an mbealach isteach, faoi ainm a fhearainn. Is féidir an fearann ​​a shonrú i gcomharthaí freisin más gá duit “scóip infheictheachta” an chomhartha a theorannú d’fheidhmchlár amháin. Ba cheart go méadódh sé seo tréchur na mbusanna, ach ní mór don loighic ghnó oibriú anois le hainmneacha fearainn: chun aghaidh a thabhairt ar theachtaireachtaí - éigeantach, le haghaidh comharthaí - inmhianaithe.

Iontaofacht Bus Comhtháthaithe a Chinntiú

Cuimsíonn iontaofacht roinnt pointí:

  • Is comhpháirt ríthábhachtach den ailtireacht agus pointe aonair teip é an bróicéir teachtaireachta roghnaithe: caithfidh sé a bheith sách fulangach le lochtanna. Níor cheart duit ach feidhmiúcháin de réir tástála ama a úsáid, le tacaíocht mhaith agus pobal mór;
  • is gá a áirithiú go mbeidh ard-infhaighteacht ar an mbróicéir teachtaireachtaí, agus ní mór é a dheighilt go fisiciúil ó na feidhmchláir chomhtháite (tá sé i bhfad níos deacra agus níos costasaí a áirithiú go bhfuil ard-infhaighteacht ar fheidhmchláir a bhfuil loighic feidhmeach gnó acu);
  • tá oibleagáid ar an mbróicéir ráthaíochtaí seachadta “uair amháin ar a laghad” a sholáthar. Is riachtanas éigeantach é seo maidir le hoibriú iontaofa an bhus lánpháirtithe. Níl gá le ráthaíochtaí leibhéal “go díreach uair amháin”: mar riail, ní bhíonn próisis ghnó íogair do theachtaireachtaí nó d’imeachtaí arís agus arís eile, agus i dtascanna speisialta a bhfuil sé seo tábhachtach, tá sé níos éasca seiceálacha breise a chur leis an ngnóthas. an loighic ná ráthaíochtaí sách “daor” a úsáid i gcónaí;
  • ní mór go mbeadh baint ag seoladh teachtaireachtaí agus comharthaí le hidirbheart foriomlán le hathruithe ar staid na bpróiseas gnó agus sonraí fearainn. Ba é an rogha tosaíochta patrún a úsáid Bosca Amach Idirbhearta, ach beidh tábla breise sa bhunachar sonraí agus athsheoltóir ag teastáil uaidh. I bhfeidhmchláir JEE, is féidir é seo a shimpliú trí úsáid a bhaint as bainisteoir áitiúil JTA, ach caithfidh an nasc leis an mbróicéir roghnaithe a bheith in ann oibriú i XA;
  • ní mór do láimhseálaithe teachtaireachtaí agus imeachtaí a thagann isteach oibriú freisin le hidirbheart a athraíonn staid próisis ghnó: má chuirtear idirbheart den sórt sin ar ais, ní mór fáil na teachtaireachta a chur ar ceal;
  • ní mór teachtaireachtaí nárbh fhéidir a sheachadadh de bharr earráidí a stóráil i stóras ar leith D.L.Q. (Scuaine Litir Marbh). Chun na críche sin, chruthaíomar microservice ardán ar leith a stórálann teachtaireachtaí den sórt sin ina stóráil, iad a innéacsú de réir tréithe (le haghaidh grúpáil tapa agus cuardach), agus a nochtar API chun breathnú orthu, athsheoladh chuig an seoladh scríbe, agus scriosadh teachtaireachtaí. Is féidir le riarthóirí córais oibriú leis an tseirbhís seo trína gcomhéadan gréasáin;
  • i socruithe an bhróicéir, ní mór duit líon na n-aistriachtaí agus na moilleanna seachadta idir seachadtaí a choigeartú chun an dóchúlacht go dtiocfaidh teachtaireachtaí isteach i DLQ a laghdú (tá sé beagnach dodhéanta na paraiméadair is fearr a ríomh, ach is féidir leat gníomhú go heimpíreach agus iad a choigeartú le linn oibriú );
  • Ní mór monatóireacht leanúnach a dhéanamh ar an stór DLQ, agus ní mór don chóras monatóireachta riarthóirí córais a chur ar an airdeall ionas gur féidir leo freagra a thabhairt chomh tapa agus is féidir nuair a tharlaíonn teachtaireachtaí neamhsheachadta. Laghdóidh sé seo an “réimse lena mbaineann” teip nó earráid loighce gnó;
  • ní mór don bhus comhtháthaithe a bheith neamhíogair maidir le héagmais sealadach feidhmchlár: ní mór do shíntiúis le topaic a bheith buan, agus ní mór ainm fearainn an fheidhmchláir a bheith uathúil ionas nach ndéanfaidh duine éigin eile iarracht a chuid teachtaireachtaí a phróiseáil ón bhfeidhmchlár, cé go bhfuil an feidhmchlár as láthair. scuaine.

Sábháilteacht snáithe na loighic gnó a chinntiú

Is féidir leis an gcás céanna de phróiseas gnó roinnt teachtaireachtaí agus imeachtaí a fháil ag an am céanna, agus cuirfear tús lena bpróiseáil ag an am céanna. Ag an am céanna, le haghaidh forbróir iarratais, ba chóir go mbeadh gach rud simplí agus sábháilte ó thaobh snáitheanna.

Déanann loighic ghnó próisis gach imeacht seachtrach a mbíonn tionchar aige ar an bpróiseas gnó sin ina aonar. D’fhéadfadh imeachtaí mar seo a bheith:

  • cás próisis ghnó a sheoladh;
  • gníomhaíocht úsáideora a bhaineann le gníomhaíocht laistigh de phróiseas gnó;
  • teachtaireacht nó comhartha a fháil a bhfuil ásc próisis ghnó sínithe aige;
  • lasc ama a chur faoi deara a shocraítear de bharr próiseas gnó;
  • gníomh rialaithe trí API (mar shampla, briseadh próisis).

Is féidir le gach imeacht den sórt sin staid ásc próisis ghnó a athrú: d’fhéadfadh go dtiocfaidh deireadh le roinnt gníomhaíochtaí agus d’fhéadfadh go dtosófar ar ghníomhaíochtaí eile, agus d’fhéadfadh go n-athróidh luachanna maoine marthanacha. D'fhéadfadh go gcuirfí ceann amháin nó níos mó de na gníomhaíochtaí seo a leanas i bhfeidhm mar thoradh ar aon ghníomhaíocht a dhúnadh. Is féidir leo siúd, ar a seal, stop a bheith ag fanacht le himeachtaí eile nó, mura bhfuil aon sonraí breise ag teastáil uathu, is féidir leo a chomhlánú san idirbheart céanna. Sula ndúnfar an t-idirbheart, sábhálfar staid nua an phróisis ghnó sa bhunachar sonraí, áit a bhfanfaidh sé go dtarlóidh an chéad imeacht seachtrach eile.

Pointe an-áisiúil chun próiseáil a shioncronú is ea sonraí próisis sheasmhacha gnó atá stóráilte i mbunachar sonraí coibhneasta má úsáideann tú SELECT FOR Update. Má d'éirigh le hidirbheart amháin staid próisis ghnó a fháil ón mbonn chun é a athrú, ansin ní bheidh aon idirbheart eile ag an am céanna in ann an stát céanna a fháil le haghaidh athrú eile, agus tar éis an chéad idirbheart a chríochnú, is é an dara ceann ráthaithe a fháil ar an stát athraithe cheana féin.

Ag baint úsáide as glais Doirbh ar thaobh an DBMS, comhlíonaimid na ceanglais riachtanacha go léir Aigéad, agus freisin an cumas an t-iarratas a scála le loighic ghnó a choinneáil trí líon na n-imeachtaí reatha a mhéadú.

Mar sin féin, cuireann glais dhoirbh ag bagairt orainn, rud a chiallaíonn gur cheart go mbeadh ROGHNÚ LE hAGHAIDH Nuashonrú fós teoranta do roinnt teorainn ama réasúnta ar eagla go dtarlódh stopanna glasa ar roinnt cásanna uafásacha sa loighic ghnó.

Fadhb eile is ea an sioncrónú ar thús próisis ghnó. Cé nach bhfuil aon chás de phróiseas gnó ann, níl aon stát sa bhunachar sonraí, mar sin ní oibreoidh an modh a thuairiscítear. Más gá duit uathúlacht shampla próisis ghnó a chinntiú i raon feidhme sonrach, beidh ort cineál éigin de réad sioncrónaithe a bhaineann leis an rang próisis agus leis an raon feidhme comhfhreagrach. Chun an fhadhb seo a réiteach, bainimid úsáid as meicníocht ghlasála dhifriúil a ligeann dúinn glas a ghlacadh ar acmhainn treallach atá sonraithe ag eochair i bhformáid URI trí sheirbhís sheachtrach.

Inár samplaí, tá dearbhú sa phróiseas gnó BeginPlayer

uniqueConstraint = UniqueConstraints.singleton

Mar sin, tá teachtaireachtaí sa logáil faoi ghlas na heochrach comhfhreagrach a ghlacadh agus a scaoileadh. Níl aon teachtaireachtaí den sórt sin ann do phróisis ghnó eile: ní shocraítear srian uathúil.

Fadhbanna a bhaineann le próisis ghnó le staid leanúnach

Uaireanta ní hamháin go gcabhraíonn staid leanúnach, ach cuireann sé bac ar fhorbairt freisin.
Tosaíonn fadhbanna nuair is gá athruithe a dhéanamh ar an loighic ghnó agus/nó ar an tsamhail próisis ghnó. Níl gach athrú den sórt sin ag luí le sean-staid na bpróiseas gnó. Má tá go leor cásanna beo sa bhunachar sonraí, ansin is féidir go leor trioblóide a dhéanamh trí athruithe neamh-chomhoiriúnacha a dhéanamh, rud a tháinig orainn go minic agus jBPM á úsáid.

Ag brath ar dhoimhneacht na n-athruithe, is féidir leat gníomhú ar dhá bhealach:

  1. cineál próiseas gnó nua a chruthú ionas nach ndéanfar athruithe neamh-chomhoiriúnacha ar an seancheann, agus é a úsáid in ionad an tseancheann agus cásanna nua á seoladh. Leanfaidh seanchóipeanna ag obair “mar a rinneadh cheana”;
  2. staid leanúnach na bpróiseas gnó a ascnamh agus an loighic gnó á nuashonrú.

Is é an chéad bhealach níos simplí, ach tá a teorainneacha agus míbhuntáistí, mar shampla:

  • dúbailt ar loighic gnó i go leor samhlacha próiseas gnó, ag méadú méid na loighic gnó;
  • Go minic is gá aistriú láithreach chuig loighic gnó nua (i dtéarmaí tascanna comhtháthaithe - beagnach i gcónaí);
  • níl a fhios ag an bhforbróir cén pointe ar féidir samhlacha atá as dáta a scriosadh.

Go praiticiúil bainimid úsáid as an dá chur chuige, ach tá roinnt cinntí déanta againn chun ár saol a dhéanamh níos éasca:

  • Sa bhunachar sonraí, déantar staid mharthanach próisis ghnó a stóráil i bhfoirm atá inléite go héasca agus a phróiseáiltear go héasca: i teaghrán formáid JSON. Ligeann sé seo ascnaimh a dhéanamh laistigh den fheidhmchlár agus go seachtrach. Mar rogha dheireanach, is féidir leat é a cheartú de láimh (go háirithe úsáideach i bhforbairt le linn debugging);
  • ní úsáideann loighic an ghnó comhtháthaithe ainmneacha na bpróiseas gnó, ionas gur féidir tráth ar bith ceann nua a chur in ionad chur chun feidhme ceann de na próisis rannpháirteacha le hainm nua (mar shampla, “InitialPlayerV2”). Tarlaíonn an ceangal trí ainmneacha teachtaireachta agus comhartha;
  • tá uimhir leagain ag múnla an phróisis, a ardóimid má dhéanaimid athruithe neamh-chomhoiriúnacha ar an múnla seo, agus déantar an uimhir seo a shábháil mar aon le staid an phróisis;
  • déantar staid leanúnach an phróisis a léamh ón mbunachar sonraí ar dtús i múnla réad áisiúil, ar féidir leis an nós imeachta imirce oibriú leis má tá uimhir an leagain mhúnla athraithe;
  • cuirtear an nós imeachta ascnaimh in aice leis an loighic ghnó agus tugtar “leisciúil” air do gach cás den phróiseas gnó nuair a dhéantar é a athbhunú ón mbunachar sonraí;
  • más gá duit staid na gcásanna próisis go léir a aistriú go tapa agus go sioncronach, úsáidtear réitigh imirce bunachar sonraí níos clasaiceach, ach caithfidh tú oibriú le JSON.

An bhfuil creat eile uait le haghaidh próisis ghnó?

Cheadaigh na réitigh a thuairiscítear san alt dúinn ár saol a shimpliú go suntasach, an raon saincheisteanna a réitíodh ag leibhéal forbartha an iarratais a leathnú, agus an smaoineamh ar loighic gnó a scaradh i micreasheirbhísí a dhéanamh níos tarraingtí. Chun é seo a bhaint amach, rinneadh go leor oibre, cruthaíodh creat an-"éadrom" do phróisis ghnó, chomh maith le comhpháirteanna seirbhíse chun na fadhbanna aitheanta a réiteach i gcomhthéacs raon leathan fadhbanna feidhmchláir. Tá fonn orainn na torthaí seo a roinnt agus forbairt na gcomhpháirteanna coitianta a dhéanamh le rochtain oscailte faoi cheadúnas in aisce. Beidh gá le roinnt iarracht agus am. D’fhéadfadh tuiscint a bheith againn ar an éileamh ar réitigh den sórt sin a bheith ina dhreasacht bhreise dúinn. San alt atá beartaithe, is beag aird a thugtar ar chumais an chreata féin, ach tá cuid acu le feiceáil ó na samplaí a chuirtear i láthair. Má fhoilsímid ár gcreat, tabharfar alt ar leith dó. Idir an dá linn, bheimis buíoch dá bhfágfaidh tú beagán aiseolais tríd an cheist a fhreagairt:

Ní féidir ach le húsáideoirí cláraithe páirt a ghlacadh sa suirbhé. Sínigh isteach, le do thoil.

An bhfuil creat eile uait le haghaidh próisis ghnó?

  • 18,8%Sea, tá mé ag lorg rud éigin mar seo le fada an lá

  • 12,5%Tá suim agam níos mó a fhoghlaim faoi do chur i bhfeidhm, b'fhéidir go mbeadh sé úsáideach2

  • 6,2%Bainimid úsáid as ceann de na creataí atá ann cheana féin, ach táimid ag smaoineamh ar athsholáthar1

  • 18,8%Bainimid úsáid as ceann de na creataí atá ann cheana féin, tá gach rud ceart go leor3

  • 18,8%déanaimid bainistiú gan chreat3

  • 25,0%scríobh mise4

Vótáil 16 úsáideoir. Staon 7 úsáideoir.

Foinse: will.com

Add a comment