Zajednica programera Raiffeisenbank .NET nastavlja sa kratkim pregledom sadržaja ViennaNET-a. O tome kako i zašto smo došli do ovoga,
U ovom članku ćemo proći kroz biblioteke koje tek treba razmotriti za rad s distribuiranim transakcijama, redovima i bazama podataka, koje se mogu naći u našem GitHub repozitoriju (
ViennaNET.Sagas
Kada se projekat prebaci na DDD i mikroservisnu arhitekturu, onda kada se poslovna logika distribuira na različite servise, nastaje problem vezan za potrebu implementacije mehanizma distribuirane transakcije, jer mnogi scenariji često utiču na nekoliko domena odjednom. S takvim mehanizmima možete se detaljnije upoznati, na primjer,
U naše projekte implementirali smo jednostavan, ali koristan mehanizam: sagu, odnosno sagu zasnovanu na orkestraciji. Njegova suština je sljedeća: postoji određeni poslovni scenario u kojem je potrebno uzastopno obavljati operacije u različitim servisima, a ako se u bilo kojem koraku jave problemi, potrebno je pozvati proceduru povratka za sve prethodne korake, gdje je obezbeđeno. Tako na kraju sage, bez obzira na uspjeh, dobijamo konzistentne podatke u svim domenima.
Naša implementacija je i dalje napravljena u svom osnovnom obliku i nije vezana za korištenje bilo kakvih metoda interakcije sa drugim servisima. Nije teško koristiti: samo napravite potomka osnovne apstraktne klase SagaBase<T>, gdje je T vaša kontekstualna klasa u koju možete pohraniti početne podatke potrebne da saga radi, kao i neke međurezultate. Instanca konteksta će biti proslijeđena svim koracima tokom izvršenja. Sama Saga je klasa bez stanja, tako da se instanca može staviti u DI kao Singleton da bi se dobile potrebne zavisnosti.
Primjer oglasa:
public class ExampleSaga : SagaBase<ExampleContext>
{
public ExampleSaga()
{
Step("Step 1")
.WithAction(c => ...)
.WithCompensation(c => ...);
AsyncStep("Step 2")
.WithAction(async c => ...);
}
}
Primjer poziva:
var saga = new ExampleSaga();
var context = new ExampleContext();
await saga.Execute(context);
Mogu se vidjeti puni primjeri različitih implementacija
ViennaNET.Orm.*
Skup biblioteka za rad sa raznim bazama podataka putem Nhibernatea. Koristimo DB-First pristup koristeći Liquibase, tako da postoji samo funkcionalnost za rad sa podacima u gotovim bazama podataka.
ViennaNET.Orm.Seedwork и ViennaNET.Orm
– glavni sklopovi koji sadrže osnovne interfejse i njihove implementacije, respektivno. Pogledajmo njihov sadržaj detaljnije.
sučelje IEntityFactoryService
i njegovu implementaciju EntityFactoryService
su glavna polazna tačka za rad sa bazom podataka, budući da se ovde kreiraju Jedinica rada, spremišta za rad sa određenim entitetima, kao i izvršioci komandi i direktni SQL upiti. Ponekad je zgodno ograničiti mogućnosti klase za rad sa bazom podataka, na primjer, da bi se obezbijedila mogućnost samo čitanja podataka. Za takve slučajeve IEntityFactoryService
postoji predak - interfejs IEntityRepositoryFactory
, koji samo deklarira metodu za kreiranje spremišta.
Za direktan pristup bazi podataka koristi se mehanizam provajdera. Svaki DBMS koji koristimo u našim timovima ima svoju implementaciju: ViennaNET.Orm.MSSQL, ViennaNET.Orm.Oracle, ViennaNET.Orm.SQLite, ViennaNET.Orm.PostgreSql
.
Istovremeno, više provajdera može biti registrovano u jednoj aplikaciji istovremeno, što omogućava da se, na primer, u okviru jedne usluge, bez ikakvih troškova za modifikaciju infrastrukture, izvrši korak po korak migracija sa jedan DBMS u drugi. Mehanizam za odabir potrebne veze, a samim tim i provajdera za određenu klasu entiteta (za koju se piše mapiranje u tabele baze podataka) implementira se registracijom entiteta u klasu BoundedContext (sadrži metodu za registraciju entiteta domene) ili njenog nasljednika. ApplicationContext (sadrži metode za registraciju entiteta aplikacije, direktne zahtjeve i naredbe), gdje se identifikator veze iz konfiguracije prihvaća kao argument:
"db": [
{
"nick": "mssql_connection",
"dbServerType": "MSSQL",
"ConnectionString": "...",
"useCallContext": true
},
{
"nick": "oracle_connection",
"dbServerType": "Oracle",
"ConnectionString": "..."
}
],
Primjer ApplicationContext:
internal sealed class DbContext : ApplicationContext
{
public DbContext()
{
AddEntity<SomeEntity>("mssql_connection");
AddEntity<MigratedSomeEntity>("oracle_connection");
AddEntity<AnotherEntity>("oracle_connection");
}
}
Ako ID veze nije naveden, tada će se koristiti veza pod nazivom “default”.
Direktno mapiranje entiteta u tablice baze podataka implementirano je korištenjem standardnih NHibernate alata. Opis možete koristiti i kroz xml datoteke i kroz klase. Za praktično pisanje stub repozitorija u jediničnim testovima, postoji biblioteka ViennaNET.TestUtils.Orm
.
Pune primjere korištenja ViennaNET.Orm.* možete pronaći
ViennaNET.Messaging.*
Skup biblioteka za rad sa redovima čekanja.
Za rad sa redovima izabran je isti pristup kao i kod raznih DBMS-ova, odnosno maksimalno mogući objedinjeni pristup u pogledu rada sa bibliotekom, bez obzira na korišćeni upravitelj redova. Biblioteka ViennaNET.Messaging
je upravo odgovoran za ovo ujedinjenje, i ViennaNET.Messaging.MQSeriesQueue, ViennaNET.Messaging.RabbitMQQueue и ViennaNET.Messaging.KafkaQueue
sadrže implementacije adaptera za IBM MQ, RabbitMQ i Kafku, respektivno.
Kada radite sa redovima, postoje dva procesa: primanje poruke i njeno slanje.
Razmislite o primanju. Ovdje postoje 2 opcije: za neprekidno slušanje i za primanje jedne poruke. Da biste stalno slušali red, prvo morate opisati klasu procesora od koje je naslijeđena IMessageProcessor
, koji će biti odgovoran za obradu dolazne poruke. Zatim, mora biti "povezan" sa određenim redom čekanja, to se radi putem registracije; IQueueReactorFactory
označavajući identifikator reda iz konfiguracije:
"messaging": {
"ApplicationName": "MyApplication"
},
"rabbitmq": {
"queues": [
{
"id": "myQueue",
"queuename": "lalala",
...
}
]
},
Primjer početka slušanja:
_queueReactorFactory.Register<MyMessageProcessor>("myQueue");
var queueReactor = queueReactorFactory.CreateQueueReactor("myQueue");
queueReactor.StartProcessing();
Zatim, kada se servis pokrene i metoda je pozvana da započne slušanje, sve poruke iz navedenog reda će ići u odgovarajući procesor.
Za primanje jedne poruke u fabričkom interfejsu IMessagingComponentFactory
postoji metoda CreateMessageReceiver
koji će kreirati primaoca koji čeka poruku iz reda koji mu je naveden:
using (var receiver = _messagingComponentFactory.CreateMessageReceiver<TestMessage>("myQueue"))
{
var message = receiver.Receive();
}
Za slanje poruke morate koristiti isto IMessagingComponentFactory
i kreirajte pošiljaoca poruke:
using (var sender = _messagingComponentFactory.CreateMessageSender<MyMessage>("myQueue"))
{
sender.SendMessage(new MyMessage { Value = ...});
}
Postoje tri gotove opcije za serijalizaciju i deserializaciju poruke: samo tekst, XML i JSON, ali ako je potrebno, lako možete napraviti vlastite implementacije interfejsa IMessageSerializer и IMessageDeserializer
.
Pokušali smo da sačuvamo jedinstvene mogućnosti svakog upravitelja redova, npr. ViennaNET.Messaging.MQSeriesQueue
omogućava vam slanje ne samo tekstualnih, već i bajt poruka, i ViennaNET.Messaging.RabbitMQQueue
podržava rutiranje i čekanje u hodu. Naš omotač adaptera za RabbitMQ također implementira neki privid RPC-a: šaljemo poruku i čekamo odgovor iz posebnog privremenog reda, koji se kreira samo za jednu poruku odgovora.
ovdje
ViennaNET.CallContext
Redove koristimo ne samo za integraciju između različitih sistema, već i za komunikaciju između mikroservisa iste aplikacije, na primjer, unutar sage. To je dovelo do potrebe da se uz poruku prenesu i pomoćni podaci kao što su prijava korisnika, identifikator zahtjeva za end-to-end logovanje, izvorna IP adresa i autorizacijski podaci. Za implementaciju prosljeđivanja ovih podataka razvili smo biblioteku ViennaNET.CallContext
, koji vam omogućava pohranjivanje podataka iz zahtjeva koji ulazi u uslugu. U ovom slučaju, način na koji je zahtjev napravljen, kroz red čekanja ili preko Http-a, nije bitno. Zatim, prije slanja odlaznog zahtjeva ili poruke, podaci se uzimaju iz konteksta i stavljaju u zaglavlja. Dakle, sljedeći servis prima pomoćne podatke i upravlja njima na isti način.
Hvala vam na pažnji, radujemo se vašim komentarima i zahtjevima za povlačenjem!
izvor: www.habr.com