ViennaNET. գրադարանների հավաքածու հետին մասի համար: Մաս 2

Raiffeisenbank .NET ծրագրավորողների համայնքը շարունակում է համառոտ ուսումնասիրել ViennaNET-ի բովանդակությունը: Այն մասին, թե ինչպես և ինչու եկանք դրան, կարող եք կարդալ առաջին մասը.

Այս հոդվածում մենք կանցնենք բաշխված գործարքների, հերթերի և տվյալների բազաների հետ աշխատելու համար դեռևս չհամարվող գրադարանների միջոցով, որոնք կարելի է գտնել մեր GitHub պահոցում (աղբյուրները՝ այստեղ), և Nuget փաթեթներն այստեղ.

ViennaNET. գրադարանների հավաքածու հետին մասի համար: Մաս 2

ViennaNET.Sagas

Երբ նախագիծն անցնում է DDD-ի և միկրոսերվիսային ճարտարապետության, ապա երբ բիզնես տրամաբանությունը բաշխվում է տարբեր ծառայություններում, խնդիր է առաջանում՝ կապված բաշխված գործարքների մեխանիզմի ներդրման անհրաժեշտության հետ, քանի որ շատ սցենարներ հաճախ ազդում են միանգամից մի քանի տիրույթների վրա: Նման մեխանիզմներին կարող եք ավելի մանրամասն ծանոթանալ, օրինակ. «Microservices Patterns» գրքում, Քրիս Ռիչարդսոնը.

Մեր նախագծերում մենք իրականացրել ենք մի պարզ, բայց օգտակար մեխանիզմ՝ սագա, ավելի ճիշտ՝ նվագախմբի վրա հիմնված սագա։ Դրա էությունը հետևյալն է. կա որոշակի բիզնես սցենար, որում անհրաժեշտ է հաջորդաբար գործողություններ կատարել տարբեր ծառայություններում, և եթե որևէ քայլում որևէ խնդիր առաջանա, անհրաժեշտ է կանչել հետադարձ ընթացակարգ բոլոր նախորդ քայլերի համար, որտեղ դա կա. տրամադրվում է. Այսպիսով, սագայի վերջում, անկախ հաջողությունից, մենք ստանում ենք հետևողական տվյալներ բոլոր տիրույթներում։

Մեր ներդրումը դեռևս իրականացվում է իր հիմնական ձևով և կապված չէ այլ ծառայությունների հետ փոխգործակցության որևէ մեթոդի կիրառման հետ: Դժվար չէ օգտագործել. պարզապես ստեղծեք SagaBase<T> բազային վերացական դասի հետնորդը, որտեղ T-ը ձեր համատեքստի դասն է, որտեղ դուք կարող եք պահպանել նախնական տվյալները, որոնք անհրաժեշտ են սագայի աշխատանքի համար, ինչպես նաև որոշ միջանկյալ արդյունքներ: Համատեքստի օրինակը կփոխանցվի կատարման ընթացքում բոլոր քայլերին: Սագան ինքնին քաղաքացիություն չունեցող դաս է, ուստի օրինակը կարող է տեղադրվել DI-ում որպես Singleton՝ անհրաժեշտ կախվածություններ ստանալու համար:

Գովազդի օրինակ.

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

Զանգի օրինակ.

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

Տարբեր իրականացումների ամբողջական օրինակներ կարող են դիտվել այստեղ եւ ժողովում հետ թեստեր.

ViennaNET.Orm.*

Գրադարանների մի շարք Nhibernate-ի միջոցով տարբեր տվյալների բազաների հետ աշխատելու համար: Մենք օգտագործում ենք DB-First մոտեցումը, օգտագործելով Liquibase-ը, այնպես որ կա միայն պատրաստի տվյալների բազայում տվյալների հետ աշխատելու գործառույթ:

ViennaNET.Orm.Seedwork и ViennaNET.Orm – հիմնական հավաքույթներ, որոնք պարունակում են համապատասխանաբար հիմնական միջերեսներ և դրանց իրականացում: Դիտարկենք դրանց բովանդակությունը ավելի մանրամասն։

ինտերֆեյս IEntityFactoryService և դրա իրականացումը EntityFactoryService Տվյալների բազայի հետ աշխատելու հիմնական մեկնարկային կետն է, քանի որ այստեղ ստեղծվում են Աշխատանքի միավորը, հատուկ սուբյեկտների հետ աշխատելու պահոցներ, ինչպես նաև հրամանների կատարողներ և ուղղակի SQL հարցումներ: Երբեմն հարմար է սահմանափակել դասի հնարավորությունները տվյալների բազայի հետ աշխատելու համար, օրինակ՝ ապահովել միայն տվյալների ընթերցման հնարավորությունը։ Նման դեպքերի համար IEntityFactoryService կա նախնի - ինտերֆեյս IEntityRepositoryFactory, որը միայն հայտարարում է պահեստներ ստեղծելու մեթոդ։

Տվյալների բազան ուղղակիորեն մուտք գործելու համար օգտագործվում է մատակարարի մեխանիզմը: Յուրաքանչյուր DBMS, որը մենք օգտագործում ենք մեր թիմերում, ունի իր ներդրումը. ViennaNET.Orm.MSSQL, ViennaNET.Orm.Oracle, ViennaNET.Orm.SQLite, ViennaNET.Orm.PostgreSql.

Միևնույն ժամանակ, մի քանի պրովայդերներ կարող են գրանցվել միաժամանակ մեկ հավելվածում, ինչը թույլ է տալիս, օրինակ, մեկ ծառայության շրջանակներում, առանց ենթակառուցվածքի փոփոխման ծախսերի, իրականացնել քայլ առ քայլ միգրացիա: մեկ DBMS մյուսին: Պահանջվող կապի ընտրության մեխանիզմը և, հետևաբար, մատակարարը որոշակի օբյեկտի դասի համար (որի համար գրված է տվյալների բազայի աղյուսակների քարտեզագրումը) իրականացվում է կազմակերպության գրանցման միջոցով BoundedContext դասում (պարունակում է տիրույթի սուբյեկտների գրանցման մեթոդ) կամ դրա իրավահաջորդը: ApplicationContext (պարունակում է կիրառական սուբյեկտների գրանցման մեթոդներ, ուղղակի հարցումներ և հրամաններ), որտեղ կոնֆիգուրացիայից կապի նույնացուցիչն ընդունվում է որպես փաստարկ.

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

Օրինակ ApplicationContext:

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

Եթե ​​կապի ID-ն նշված չէ, ապա կօգտագործվի «default» անունով կապը:

Սուբյեկտների ուղղակի քարտեզագրումը տվյալների բազայի աղյուսակներին իրականացվում է ստանդարտ NHibernate գործիքների միջոցով: Նկարագրությունը կարող եք օգտագործել ինչպես xml ֆայլերի, այնպես էլ դասերի միջոցով։ Unit-ի թեստերում կոճղերի պահեստները հարմար գրելու համար կա գրադարան ViennaNET.TestUtils.Orm.

ViennaNET.Orm.*-ի օգտագործման ամբողջական օրինակներ կարելի է գտնել այստեղ.

ViennaNET.Messaging.*

Գրադարանների հավաքածու՝ հերթերի հետ աշխատելու համար:

Հերթերի հետ աշխատելու համար ընտրվել է նույն մոտեցումը, ինչ տարբեր DBMS-ների դեպքում, այն է՝ գրադարանի հետ աշխատելու առավելագույն հնարավոր միասնական մոտեցումը՝ անկախ օգտագործվող հերթի կառավարիչից: Գրադարան ViennaNET.Messaging հենց այս միավորման պատասխանատուն է, և ViennaNET.Messaging.MQSeriesQueue, ViennaNET.Messaging.RabbitMQQueue и ViennaNET.Messaging.KafkaQueue պարունակում են համապատասխանաբար IBM MQ, RabbitMQ և Kafka ադապտերների ներդրում:

Հերթերի հետ աշխատելիս երկու գործընթաց կա՝ հաղորդագրություն ստանալը և ուղարկելը։

Մտածեք ստանալը: Այստեղ կա 2 տարբերակ՝ շարունակական լսելու և մեկ հաղորդագրություն ստանալու համար: Հերթին անընդհատ լսելու համար նախ պետք է նկարագրեք ժառանգված պրոցեսորի դասը IMessageProcessor, որը պատասխանատու կլինի մուտքային հաղորդագրության մշակման համար։ Այնուհետև այն պետք է «կապվի» որոշակի հերթի հետ, դա արվում է գրանցման միջոցով IQueueReactorFactory նշելով հերթի նույնացուցիչը կազմաձևից.

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

Լսելը սկսելու օրինակ.

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

Այնուհետև, երբ ծառայությունը սկսվի, և մեթոդը կանչվի լսել սկսելու համար, նշված հերթից բոլոր հաղորդագրությունները կգնան համապատասխան պրոցեսոր:

Գործարանային միջերեսում մեկ հաղորդագրություն ստանալու համար IMessagingComponentFactory կա մեթոդ CreateMessageReceiverորը կստեղծի հասցեատեր, որը սպասում է հաղորդագրության իրեն նշված հերթից.

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

Հաղորդագրություն ուղարկելու համար դուք պետք է օգտագործեք նույնը IMessagingComponentFactory և ստեղծել հաղորդագրություն ուղարկող.

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

Հաղորդագրությունը սերիալացնելու և ապասերիալիզացնելու երեք պատրաստ տարբերակ կա՝ պարզապես տեքստ, XML և JSON, բայց անհրաժեշտության դեպքում կարող եք հեշտությամբ կատարել ձեր սեփական ինտերֆեյսի իրականացումները: IMessageSerializer и IMessageDeserializer.

Մենք փորձել ենք պահպանել յուրաքանչյուր հերթի մենեջերի յուրահատուկ հնարավորությունները, օրինակ. ViennaNET.Messaging.MQSeriesQueue թույլ է տալիս ուղարկել ոչ միայն տեքստային, այլև բայթային հաղորդագրություններ և ViennaNET.Messaging.RabbitMQQueue աջակցում է երթուղային և թռիչքային հերթագրմանը: RabbitMQ-ի մեր ադապտերների փաթաթանն իրականացնում է նաև RPC-ի որոշակի տեսք. մենք հաղորդագրություն ենք ուղարկում և սպասում ենք պատասխանի հատուկ ժամանակավոր հերթից, որը ստեղծվում է միայն մեկ պատասխան հաղորդագրության համար:

Այստեղ միացման հիմնական նրբերանգներով հերթերի օգտագործման օրինակ.

ViennaNET.CallContext

Մենք օգտագործում ենք հերթեր ոչ միայն տարբեր համակարգերի միջև ինտեգրվելու, այլև նույն հավելվածի միկրոծառայությունների միջև հաղորդակցության համար, օրինակ՝ սագայի շրջանակներում: Սա հանգեցրեց հաղորդագրության հետ միասին այնպիսի օժանդակ տվյալներ փոխանցելու անհրաժեշտությանը, ինչպիսիք են օգտատիրոջ մուտքը, վերջից մինչև վերջ գրանցման հարցումի նույնացուցիչը, աղբյուրի IP հասցեն և թույլտվության տվյալները: Այս տվյալների վերահասցեավորումն իրականացնելու համար մենք մշակեցինք գրադարան ViennaNET.CallContext, որը թույլ է տալիս պահպանել տվյալներ ծառայություն մուտքագրող հարցումից: Այս դեպքում, թե ինչպես է հարցումն արվել՝ հերթի միջոցով, թե Http-ի միջոցով, նշանակություն չունի։ Այնուհետև, նախքան ելքային հարցումը կամ հաղորդագրությունն ուղարկելը, տվյալները վերցվում են համատեքստից և տեղադրվում վերնագրերում: Այսպիսով, հաջորդ ծառայությունը ստանում է օժանդակ տվյալները և նույն կերպ կառավարում դրանք։

Շնորհակալություն ուշադրության համար, մենք անհամբեր սպասում ենք ձեր մեկնաբանություններին և խնդրանքներին:

Source: www.habr.com

Добавить комментарий