ViennaNET: seti ya maktaba za nyuma. Sehemu ya 2

Jumuiya ya wasanidi programu wa Raiffeisenbank .NET inaendelea kupitia kwa ufupi yaliyomo kwenye ViennaNET. Kuhusu jinsi na kwa nini tulikuja kwa hii, unaweza kusoma sehemu ya kwanza.

Katika nakala hii, tutapitia maktaba ambazo bado hazijazingatiwa kwa kufanya kazi na shughuli zilizosambazwa, foleni na hifadhidata, ambazo zinaweza kupatikana kwenye hazina yetu ya GitHub (vyanzo viko hapa), na Vifurushi vya Nuget hapa.

ViennaNET: seti ya maktaba za nyuma. Sehemu ya 2

ViennaNET.Sagas

Wakati mradi unabadilika kwa DDD na usanifu wa huduma ndogo, basi wakati mantiki ya biashara inasambazwa katika huduma tofauti, tatizo hutokea kuhusiana na haja ya kutekeleza utaratibu wa shughuli iliyosambazwa, kwa sababu matukio mengi mara nyingi huathiri vikoa kadhaa mara moja. Unaweza kufahamiana na mifumo kama hii kwa undani zaidi, kwa mfano, katika kitabu "Microservices Patterns", Chris Richardson.

Katika miradi yetu, tumetekeleza utaratibu rahisi lakini muhimu: sakata, au tuseme sakata ya msingi wa orchestration. Kiini chake ni kama ifuatavyo: kuna hali fulani ya biashara ambayo ni muhimu kufanya shughuli za mfululizo katika huduma tofauti, na ikiwa matatizo yoyote yanatokea kwa hatua yoyote, ni muhimu kupiga utaratibu wa kurejesha kwa hatua zote za awali, ambapo ni. zinazotolewa. Kwa hivyo, mwisho wa sakata, bila kujali mafanikio, tunapokea data thabiti katika nyanja zote.

Utekelezaji wetu bado unafanywa kwa fomu yake ya msingi na hauhusiani na matumizi ya mbinu zozote za mwingiliano na huduma zingine. Si vigumu kutumia: tengeneza tu mzao wa darasa la msingi la mukhtasari SagaBase<T>, ambapo T ni darasa lako la muktadha ambamo unaweza kuhifadhi data ya awali inayohitajika ili sakata ifanye kazi, pamoja na baadhi ya matokeo ya kati. Mfano wa muktadha utapitishwa kwa hatua zote wakati wa utekelezaji. Saga yenyewe ni darasa lisilo na utaifa, kwa hivyo mfano unaweza kuwekwa katika DI kama Singleton kupata utegemezi unaohitajika.

Mfano tangazo:

public class ExampleSaga : SagaBase<ExampleContext>
{
  public ExampleSaga()
  {
    Step("Step 1")
      .WithAction(c => ...)
      .WithCompensation(c => ...);
	
    AsyncStep("Step 2")
      .WithAction(async c => ...);
  }
}

Simu ya mfano:

var saga = new ExampleSaga();
var context = new ExampleContext();
await saga.Execute(context);

Mifano kamili ya utekelezaji tofauti inaweza kutazamwa hapa na katika kusanyiko na vipimo.

ViennaNET.Orm.*

Seti ya maktaba za kufanya kazi na hifadhidata mbalimbali kupitia Nhibernate. Tunatumia mbinu ya DB-First kwa kutumia Liquibase, kwa hivyo kuna utendaji tu wa kufanya kazi na data katika hifadhidata iliyotengenezwa tayari.

ViennaNET.Orm.Seedwork и ViennaNET.Orm - makusanyiko makuu yaliyo na miingiliano ya msingi na utekelezaji wao, kwa mtiririko huo. Wacha tuangalie yaliyomo kwao kwa undani zaidi.

interface IEntityFactoryService na utekelezaji wake EntityFactoryService ndio sehemu kuu ya kuanza kufanya kazi na hifadhidata, kwani Kitengo cha Kazi, hazina za kufanya kazi na vyombo maalum, pamoja na watekelezaji wa amri na maswali ya moja kwa moja ya SQL huundwa hapa. Wakati mwingine ni rahisi kupunguza uwezo wa darasa kwa kufanya kazi na hifadhidata, kwa mfano, kutoa uwezo wa kusoma data tu. Kwa kesi kama hizo IEntityFactoryService kuna babu - interface IEntityRepositoryFactory, ambayo inatangaza tu njia ya kuunda hazina.

Ili kupata hifadhidata moja kwa moja, utaratibu wa mtoaji hutumiwa. Kila DBMS tunayotumia katika timu zetu ina utekelezaji wake: ViennaNET.Orm.MSSQL, ViennaNET.Orm.Oracle, ViennaNET.Orm.SQLite, ViennaNET.Orm.PostgreSql.

Wakati huo huo, watoa huduma kadhaa wanaweza kusajiliwa katika programu moja kwa wakati mmoja, ambayo inaruhusu, kwa mfano, ndani ya mfumo wa huduma moja, bila gharama yoyote ya kurekebisha miundombinu, kufanya uhamiaji wa hatua kwa hatua kutoka. DBMS moja hadi nyingine. Utaratibu wa kuchagua muunganisho unaohitajika na, kwa hivyo, mtoaji wa darasa maalum la huluki (ambalo kuchora ramani kwa meza za hifadhidata imeandikwa) inatekelezwa kwa kusajili chombo katika darasa la BoundedContext (lina njia ya kusajili vyombo vya kikoa) au mrithi wake. ApplicationContext (ina njia za kusajili vyombo vya maombi , maombi ya moja kwa moja na amri), ambapo kitambulisho cha muunganisho kutoka kwa usanidi kinakubaliwa kama hoja:

"db": [
  {
    "nick": "mssql_connection",
    "dbServerType": "MSSQL",
    "ConnectionString": "...",
    "useCallContext": true
  },
  {
    "nick": "oracle_connection",
    "dbServerType": "Oracle",
    "ConnectionString": "..."
  }
],

Mfano Muktadha wa Maombi:

internal sealed class DbContext : ApplicationContext
{
  public DbContext()
  {
    AddEntity<SomeEntity>("mssql_connection");
    AddEntity<MigratedSomeEntity>("oracle_connection");
    AddEntity<AnotherEntity>("oracle_connection");
  }
}

Ikiwa kitambulisho cha uunganisho hakijainishwa, basi uunganisho unaoitwa "chaguo-msingi" utatumika.

Uwekaji ramani wa moja kwa moja wa huluki kwenye jedwali la hifadhidata hutekelezwa kwa kutumia zana za kawaida za NHibernate. Unaweza kutumia maelezo kupitia faili za xml na kupitia madarasa. Kwa uandishi rahisi wa hazina za mbegu katika majaribio ya Kitengo, kuna maktaba ViennaNET.TestUtils.Orm.

Mifano kamili ya kutumia ViennaNET.Orm.* inaweza kupatikana hapa.

ViennaNET.Ujumbe.*

Seti ya maktaba za kufanya kazi na foleni.

Ili kufanya kazi na foleni, mbinu sawa ilichaguliwa kama ilivyo kwa DBMS mbalimbali, yaani, mbinu ya juu zaidi ya umoja katika suala la kufanya kazi na maktaba, bila kujali meneja wa foleni iliyotumiwa. Maktaba ViennaNET.Messaging inawajibika haswa kwa umoja huu, na ViennaNET.Messaging.MQSeriesQueue, ViennaNET.Messaging.RabbitMQQueue и ViennaNET.Messaging.KafkaQueue vyenye utekelezaji wa adapta kwa IBM MQ, RabbitMQ na Kafka, mtawalia.

Wakati wa kufanya kazi na foleni, kuna taratibu mbili: kupokea ujumbe na kutuma.

Fikiria kupokea. Kuna chaguo 2 hapa: kwa kusikiliza kwa kuendelea na kupokea ujumbe mmoja. Ili kusikiliza foleni kila wakati, lazima kwanza uelezee darasa la processor lililorithiwa kutoka IMessageProcessor, ambayo itakuwa na jukumu la kuchakata ujumbe unaoingia. Ifuatayo, lazima "iunganishwe" kwa foleni maalum; hii inafanywa kupitia usajili IQueueReactorFactory ikionyesha kitambulisho cha foleni kutoka kwa usanidi:

"messaging": {
    "ApplicationName": "MyApplication"
},
"rabbitmq": {
    "queues": [
      {
        "id": "myQueue",
        "queuename": "lalala",
        ...
      }
    ]
},

Mfano wa kuanza kusikiliza:

_queueReactorFactory.Register<MyMessageProcessor>("myQueue");
var queueReactor = queueReactorFactory.CreateQueueReactor("myQueue");
queueReactor.StartProcessing();

Kisha, wakati huduma inapoanza na njia inaitwa kuanza kusikiliza, ujumbe wote kutoka kwa foleni maalum utaenda kwa processor inayofanana.

Ili kupokea ujumbe mmoja katika kiolesura cha kiwanda IMessagingComponentFactory kuna mbinu CreateMessageReceiverambayo itaunda mpokeaji akingojea ujumbe kutoka kwa foleni iliyoainishwa kwake:

using (var receiver = _messagingComponentFactory.CreateMessageReceiver<TestMessage>("myQueue"))
{
    var message = receiver.Receive();
}

Ili kutuma ujumbe unahitaji kutumia sawa IMessagingComponentFactory na unda mtumaji wa ujumbe:

using (var sender = _messagingComponentFactory.CreateMessageSender<MyMessage>("myQueue"))
{
    sender.SendMessage(new MyMessage { Value = ...});
}

Kuna chaguzi tatu zilizotengenezwa tayari za kusawazisha na kuondoa ujumbe: maandishi tu, XML na JSON, lakini ikiwa ni lazima, unaweza kufanya utekelezaji wako wa kiolesura kwa urahisi. IMessageSerializer и IMessageDeserializer.

Tumejaribu kuhifadhi uwezo wa kipekee wa kila msimamizi wa foleni, k.m. ViennaNET.Messaging.MQSeriesQueue hukuruhusu kutuma sio maandishi tu, bali pia ujumbe wa kawaida, na ViennaNET.Messaging.RabbitMQQueue inasaidia uelekezaji na kupanga foleni popote ulipo. Kifungashio chetu cha adapta cha RabbitMQ pia hutekeleza mfananisho fulani wa RPC: tunatuma ujumbe na kusubiri jibu kutoka kwa foleni maalum ya muda, ambayo imeundwa kwa ajili ya ujumbe mmoja tu wa majibu.

Hapa mfano wa kutumia foleni na nuances ya msingi ya uunganisho.

ViennaNET.CallContext

Tunatumia foleni sio tu kwa ujumuishaji kati ya mifumo tofauti, lakini pia kwa mawasiliano kati ya huduma ndogo za programu sawa, kwa mfano, ndani ya sakata. Hii ilisababisha hitaji la kusambaza pamoja na ujumbe data saidizi kama vile kuingia kwa mtumiaji, kuomba kitambulisho cha ukataji wa miti kutoka mwisho hadi mwisho, anwani ya IP ya chanzo na data ya uidhinishaji. Ili kutekeleza usambazaji wa data hii, tulitengeneza maktaba ViennaNET.CallContext, ambayo inakuwezesha kuhifadhi data kutoka kwa ombi la kuingia kwenye huduma. Katika kesi hii, jinsi ombi lilifanywa, kwa njia ya foleni au kupitia Http, haijalishi. Kisha, kabla ya kutuma ombi au ujumbe unaotoka, data inachukuliwa kutoka kwa muktadha na kuwekwa kwenye vichwa. Kwa hivyo, huduma inayofuata inapokea data ya msaidizi na inasimamia kwa njia ile ile.

Asante kwa umakini wako, tunatarajia maoni yako na maombi ya kuvuta!

Chanzo: mapenzi.com

Kuongeza maoni