RaiïŹeisenbanki .NET-arendajate kogukond jĂ€tkab ViennaNETi sisuloome lĂŒhikokkuvĂ”tet. Kuidas ja miks me selle juurde jĂ”udsime, .
Selles artiklis kÀsitleme veel mitte kÀsitletud teeke, mis on seotud jaotatud tehingute, jÀrjekordade ja andmebaasidega, mida leiate meie GitHubi repost (), and .
ViennaNET.Sagas
Kui projektis toimub ĂŒleminek DDD-le ja mikroteenuste arhitektuurile, siis Ă€riloogika jagamisel erinevatesse teenustesse tekib probleem, mis on seotud jaotatud tehingute mehhanismi rakendamise vajadusega, kuna paljud stsenaariumid hĂ”lmavad sageli mitmeid domeene. Selliste mehhanismidega saab lĂ€hemalt tutvuda nĂ€iteks .
Meie projektides oleme rakendanud lihtsa, kuid kasuliku mehhanismi: saga, tÀpsemalt orkestreeritud saga. Selle olemus on jÀrgmine: olemas on teatud Àristsenaarium, kus on vaja jÀrjestikku teostada toiminguid erinevates teenustes, samas, kui mis tahes sammus tekib probleeme, tuleb kutsuda esile tagasivÔtmise protseduur kÔikidele varasematele sammudele, kus see on ette nÀhtud. SeelÀbi saame sagade tÀitmise lÔpus, sÔltumata eduka lÔpuleviimise, jÀrjepidevad andmed kÔikides domeenides.
Meie rakendus on seni tehtud pÔhilisel kujul ja ei sÔltu teiste teenustega suhtlemiseks vajalike meetodite kasutamisest. Seda on lihtne rakendada: piisab, kui luua jÀreltulija pÔhiklassist SagaBase<T>, kus T on teie konteksti klass, kus saab hoida algandmeid, mis on vajalikud saga toimimiseks, samuti mÔned vahepealsed tulemused. Konteksti eksemplar edastatakse kÔigile sammustel tÀitmise ajal. Igal juhul on saga staateless klass, seega vÔib eksemplar sisestada DI-sse kui Singleton, et saada vajalikke sÔltuvusi.
NĂ€ide deklaratsioonist:
public class ExampleSaga : SagaBase<ExampleContext>
{
public ExampleSaga()
{
Step("Samm 1")
.WithAction(c => ...)
.WithCompensation(c => ...);
AsyncStep("Samm 2")
.WithAction(async c => ...);
}
}
Kutsumise nÀide:
var saga = new ExampleSaga();
var context = new ExampleContext();
await saga.Execute(context);
TÀielikke nÀiteid erinevatest rakendustest saate vaadata ja kogus, kus .
ViennaNET.Orm.*
Raamatukogude komplekt erinevate andmebaasidega töötamiseks lÀbi Nhibernate. Me kasutame DB-First lÀhenemist koos Liquibase'i rakendamisega, seega on siin ainult andmete haldamiseks vajalik funktsionaalsus valmis andmebaasis.
ViennaNET.Orm.Seedwork ja ViennaNET.Orm â peamised kogud, mis sisaldavad vastavaid pĂ”hiliideseid ja nende rakendusi. JĂ€tkame nende sisu detailsemalt.
Liides IEntityFactoryService ja selle rakendus EntityFactoryService on peamine alguspunkt andmebaasiga töötamiseks, kuna siin luuakse Unit of Work, konkreetsete entiteetidega töötavad repositooriumid, samuti kĂ€su ja otse SQL-pĂ€ringute tĂ€itjad. MĂ”nikord on mugav piirata klassi vĂ”imalusi andmebaasiga töötamiseks, nĂ€iteks lubada ainult andmete lugemist. Selliseid juhtumeid on IEntityFactoryService eelkĂ€ija â liides IEntityRepositoryFactory, milles on deklareeritud ainult meetod repositooriumide loomiseks.
Andmebaasiga otse suhtlemiseks kasutatakse pakkujate mehhanismi. Iga andmebaasi haldamiseks kasutatavale sĂŒsteemile on meie meeskondades oma rakendus: ViennaNET.Orm.MSSQL, ViennaNET.Orm.Oracle, ViennaNET.Orm.SQLite, ViennaNET.Orm.PostgreSql.
Samuti vĂ”ib ĂŒhes rakenduses olla registreeritud mitu pakkujat korraga, mis vĂ”imaldab, nĂ€iteks, ĂŒhe teenuse raames teostada astmelist migratsiooni ĂŒhe andmebaasist teise ilma otseste infrastruktuuri parandusteta. Vajadus vajalikku ĂŒhendust ja seega pakkujat konkreetse entiteediklassi jaoks (mille jaoks kirjutatakse kaardistamine andmebaasi tabelitega) on rakendatud entiteedi registreerimise kaudu klassis BoundedContext (mis sisaldab meetodit domeenide entiteetide registreerimiseks) vĂ”i selle jĂ€reltulijarakenduses ApplicationContext (mis sisaldab meetodeid rakenduse entiteetide, otsepĂ€ringute ja kĂ€skude registreerimiseks), kus argumendina vĂ”etakse ĂŒhenduse identifikaator konfiguratsioonist:
"db": [
{
"nick": "mssql_connection",
"dbServerType": "MSSQL",
"ConnectionString": "...",
"useCallContext": true
},
{
"nick": "oracle_connection",
"dbServerType": "Oracle",
"ConnectionString": "..."
}
],
NĂ€ide ApplicationContextist:
internal sealed class DbContext : ApplicationContext
{
public DbContext()
{
AddEntity<SomeEntity>("mssql_connection");
AddEntity<MigratedSomeEntity>("oracle_connection");
AddEntity<AnotherEntity>("oracle_connection");
}
}
Kui ĂŒhenduse identifikaatorit ei ole mÀÀratud, siis kasutatakse ĂŒhendust nimega «default».
Entiteetide otsemapping andmebaasi tabelitele toimub NHibernate'i standardsete vahenditega. Kirjeldust on vÔimalik kasutada nii XML-failide kui ka klasside kaudu. Repo-zhtestide mugavaks kirjutamiseks on saadaval raamatukogu ViennaNET.TestUtils.Orm.
TÀielikud nÀited ViennaNET.Orm.* kasutamisest leiate .
ViennaNET.Messaging.*
Raamatukogude komplekt, mis tegeleb jÀrjekordadega.
JĂ€rjekordadega töötamiseks valiti sama lĂ€henemine, mis erinevate andmebaasidega, nimelt maksimaalselt vĂ”imalik ĂŒhtne lĂ€henemine raamatukoguga töötamisel, sĂ”ltumata kasutatavast jĂ€rjekorra haldurist. Raamatukogu ViennaNET.Messaging vastutab just selle ĂŒhtsuse eest, ning ViennaNET.Messaging.MQSeriesQueue, ViennaNET.Messaging.RabbitMQQueue ja ViennaNET.Messaging.KafkaQueue sisaldavad adapterite rakendusi IBM MQ, RabbitMQ ja Kafka jaoks vastavalt.
JÀrjekordadega töötamisel on kaks protsessi: sÔnumi vastuvÔtmine ja saatmine.
Uurime sĂ”numi vastuvĂ”tmist. Siin on kaks vĂ”imalust: pidev kuulamine ja ĂŒksiku sĂ”numi vastuvĂ”tt. Pideva kuulamise jaoks tuleb esmalt kirjeldada protsessoriklass, mis on pĂ€ritud IMessageProcessor, mis vastutab sissetuleva sĂ”numi töötlemise eest. Edasi tuleb see âsidudaâ kindla jĂ€rjekorraga, mis toimub registreerimise kaudu IQueueReactorFactory konfiguratsioonist jĂ€rjekorra identifikaatori mÀÀramisega:
"messaging": {
"ApplicationName": "MyApplication"
},
"rabbitmq": {
"queues": [
{
"id": "myQueue",
"queuename": "lalala",
...
}
]
},
NÀide kuulamise kÀivitamisest:
_queueReactorFactory.Register<MyMessageProcessor>("myQueue");
var queueReactor = queueReactorFactory.CreateQueueReactor("myQueue");
queueReactor.StartProcessing();
SeejÀrel, teenuse kÀivitamisel ja meetodi vÀljakutsumisel kuulamise alustamiseks, kÔik sÔnumid mÀÀratud jÀrjekorrast jÔuavad vastavasse protsessorisse.
Ăksiku sĂ”numi vastuvĂ”tmiseks on interfeysifabrikus IMessagingComponentFactory olemas meetod CreateMessageReceiver, mis loob vastuvĂ”tja, mis ootab sĂ”numit mÀÀratud jĂ€rjekorrast:
using (var receiver = _messagingComponentFactory.CreateMessageReceiver<TestMessage>("myQueue"))
{
var message = receiver.Receive();
}
SÔnumi saatmiseks on vajalik kasutada sama IMessagingComponentFactory ja luua sÔnumi saatja:
using (var sender = _messagingComponentFactory.CreateMessageSender<MyMessage>("myQueue"))
{
sender.SendMessage(new MyMessage { Value = ...});
}
SÔnumi seriaalimiseks ja deserialiseerimiseks on kolm valmis varianti: lihtne tekst, XML ja JSON, kuid vajadusel on vÔimalik rahulikult luua oma implementatsioonid liidestele IMessageSerializer ja IMessageDeserializer.
Olemegi pĂŒĂŒdnud sĂ€ilitada iga jĂ€rjekorra halduri unikaalsed vĂ”imalused, nĂ€iteks ViennaNET.Messaging.MQSeriesQueue lubab saata mitte ainult tekstilisi, vaid ka baitide sĂ”numeid, ja ViennaNET.Messaging.RabbitMQQueue toetab marsruutimist ja jĂ€rjekordade loomist 'otse'. Meie RabbitMQ adapteri ĂŒmber ringi on samuti rakendatud teatud sarnasus RPC-le: saadame sĂ”numi ja ootame vastust eraldi ajutisest jĂ€rjekorrast, mis luuakse ainult ĂŒhe vastavas sĂ”numiks.
Siin on .
ViennaNET.CallContext
Kasutame jĂ€rjekordi mitte ainult erinevate sĂŒsteemide integreerimiseks, vaid ka mikroteenuste suhtlemiseks ĂŒhes rakenduses, nĂ€iteks saaga raames. See tĂ”i kaasa vajaduse edastada koos sĂ”numiga selliseid abivĂ”imalusi nagu kasutaja sisselogimise, pĂ€ringu identifikaatori koheseks logimiseks, allika IP-aadress ja autoriseerimise andmed. Need andmed edastamiseks oleme vĂ€lja töötanud raamatukogu ViennaNET.CallContext, mis vĂ”imaldab salvestada andmeid sisenevast teenuse pĂ€ringust. Sel juhul ei ole oluline, kuidas pĂ€ring tehti, kas jĂ€rjekorra vĂ”i HTTP kaudu. Siis, enne vĂ€ljamineva pĂ€ringu vĂ”i sĂ”numi saatmist, vĂ”etakse kontekstist andmed ja kantakse pĂ€istesse. Nii et jĂ€rgmine teenus saab abivĂ”imalusi ja kĂ€sitseb neid samamoodi.
AitÀh tÀhelepanu eest, ootame teie kommentaare ja pull request'e!
Allikas: habr.com
