ViennaNET: kumpulan perpustakaan kanggo backend. Bagean 2

Komunitas pangembang Raiffeisenbank .NET terus nliti kanthi ringkes isi ViennaNET. Babagan carane lan ngapa kita teka iki, sampeyan bisa maca bagean pisanan.

Ing artikel iki, kita bakal mbukak perpustakaan sing durung dianggep kanggo nggarap transaksi, antrian lan basis data sing disebarake, sing bisa ditemokake ing repositori GitHub (sumber kene), lan Nuget paket kene.

ViennaNET: kumpulan perpustakaan kanggo backend. Bagean 2

ViennaNET.Sagas

Nalika proyek pindhah menyang arsitektur DDD lan microservice, banjur nalika logika bisnis disebarake ing macem-macem layanan, ana masalah sing ana hubungane karo kabutuhan kanggo ngleksanakake mekanisme transaksi sing disebarake, amarga akeh skenario asring mengaruhi sawetara domain bebarengan. Sampeyan bisa ngerteni mekanisme kasebut kanthi luwih rinci, contone, ing buku "Microservices Patterns", Chris Richardson.

Ing proyek kita, kita wis ngetrapake mekanisme sing prasaja nanging migunani: saga, utawa luwih saga adhedhasar orkestrasi. Intine kaya ing ngisor iki: ana skenario bisnis tartamtu sing kudu nindakake operasi ing macem-macem layanan, lan yen ana masalah ing langkah apa wae, perlu nelpon prosedur rollback kanggo kabeh langkah sadurunge, ing ngendi iku diwenehake. Mangkono, ing pungkasan saga, preduli saka sukses, kita nampa data konsisten ing kabeh domain.

Implementasi kita isih digawe ing wangun dhasar lan ora ana gandhengane karo panggunaan cara interaksi karo layanan liyane. Ora angel digunakake: mung nggawe turunan saka kelas abstrak dasar SagaBase<T>, ing ngendi T minangka kelas konteks sampeyan bisa nyimpen data awal sing perlu kanggo saga, uga sawetara asil penengah. Instance konteks bakal diterusake menyang kabeh langkah sajrone eksekusi. Saga dhewe minangka kelas tanpa negara, mula conto kasebut bisa diselehake ing DI minangka Singleton kanggo entuk dependensi sing dibutuhake.

Tuladha iklan:

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

Tuladha telpon:

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

Conto lengkap implementasine beda bisa dideleng kene lan ing perakitan karo tes.

ViennaNET.Orm.*

Sakumpulan perpustakaan kanggo nggarap macem-macem database liwat Nhibernate. Kita nggunakake pendekatan DB-First nggunakake Liquibase, supaya ana mung fungsi kanggo nggarap data ing database siap-digawe.

ViennaNET.Orm.Seedwork и ViennaNET.Orm - Majelis utama sing ngemot antarmuka dhasar lan implementasine. Ayo dideleng isine kanthi luwih rinci.

antarmuka IEntityFactoryService lan implementasine EntityFactoryService minangka titik wiwitan utama kanggo nggarap database, wiwit Unit Kerja, repositori kanggo nggarap entitas tartamtu, uga pelaksana perintah lan pitakon SQL langsung digawe ing kene. Kadhangkala trep kanggo matesi kemampuan kelas kanggo nggarap database, contone, kanggo menehi kemampuan kanggo mung maca data. Kanggo kasus kaya mengkono IEntityFactoryService ana leluhur - antarmuka IEntityRepositoryFactory, sing mung ngumumake cara kanggo nggawe repositori.

Kanggo ngakses database langsung, mekanisme panyedhiya digunakake. Saben DBMS sing digunakake ing tim duwe implementasine dhewe: ViennaNET.Orm.MSSQL, ViennaNET.Orm.Oracle, ViennaNET.Orm.SQLite, ViennaNET.Orm.PostgreSql.

Ing wektu sing padha, sawetara panyedhiya bisa didaftar ing siji aplikasi sekaligus, sing ngidini, contone, ing kerangka siji layanan, tanpa biaya kanggo ngowahi infrastruktur, kanggo nindakake migrasi langkah-langkah saka siji DBMS menyang liyane. Mekanisme kanggo milih sambungan sing dibutuhake lan, mulane, panyedhiya kanggo kelas entitas tartamtu (kanggo pemetaan menyang tabel database ditulis) dileksanakake liwat ndhaptar entitas ing kelas BoundedContext (ngandhut cara kanggo ndhaptar entitas domain) utawa peneruse. ApplicationContext (ngandhut cara kanggo ndhaptar entitas aplikasi, panjaluk langsung lan printah), ing ngendi pengenal sambungan saka konfigurasi ditampa minangka argumen:

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

Contoh Konteks Aplikasi:

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

Yen ID sambungan ora ditemtokake, sambungan sing jenenge "standar" bakal digunakake.

Pemetaan langsung entitas menyang tabel basis data dileksanakake nggunakake alat NHibernate standar. Sampeyan bisa nggunakake katrangan liwat file xml lan liwat kelas. Kanggo nulis repositori rintisan sing trep ing tes Unit, ana perpustakaan ViennaNET.TestUtils.Orm.

Conto lengkap nggunakake ViennaNET.Orm.* bisa ditemokake kene.

ViennaNET.Pesen.*

Sakumpulan perpustakaan kanggo nggarap antrian.

Kanggo nggarap antrian, pendekatan sing padha dipilih karo macem-macem DBMS, yaiku, pendekatan terpadu maksimal ing babagan nggarap perpustakaan, preduli saka manajer antrian sing digunakake. Pustaka ViennaNET.Messaging sabenere tanggung jawab kanggo manunggalaken iki, lan ViennaNET.Messaging.MQSeriesQueue, ViennaNET.Messaging.RabbitMQQueue и ViennaNET.Messaging.KafkaQueue ngemot implementasi adaptor kanggo IBM MQ, RabbitMQ lan Kafka.

Nalika nggarap antrian, ana rong proses: nampa pesen lan ngirim.

Coba nampa. Ana 2 opsi ing kene: kanggo ngrungokake terus-terusan lan kanggo nampa pesen siji. Kanggo terus-terusan ngrungokake antrian, sampeyan kudu njlèntrèhaké kelas prosesor sing diwarisake IMessageProcessor, sing bakal tanggung jawab kanggo ngolah pesen sing mlebu. Sabanjure, kudu "disambung" menyang antrian tartamtu; iki rampung liwat registrasi ing IQueueReactorFactory nuduhake pengenal antrian saka konfigurasi:

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

Tuladha miwiti ngrungokake:

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

Banjur, nalika layanan diwiwiti lan cara diarani kanggo miwiti ngrungokake, kabeh pesen saka antrian sing ditemtokake bakal pindhah menyang prosesor sing cocog.

Kanggo nampa pesen siji ing antarmuka pabrik IMessagingComponentFactory ana cara CreateMessageReceiversing bakal nggawe panampa nunggu pesen saka antrian kasebut:

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

Kanggo ngirim pesen sampeyan kudu nggunakake padha IMessagingComponentFactory lan nggawe pangirim pesen:

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

Ana telung opsi siap kanggo serializing lan deserializing pesen: mung teks, XML lan JSON, nanging yen perlu, sampeyan bisa kanthi gampang nggawe implementasine antarmuka dhewe. IMessageSerializer и IMessageDeserializer.

Kita wis nyoba kanggo ngreksa kabisan unik saben manager antrian, f.eks. ViennaNET.Messaging.MQSeriesQueue ngijini sampeyan kanggo ngirim ora mung teks, nanging uga pesen byte, lan ViennaNET.Messaging.RabbitMQQueue ndhukung nuntun lan on-the-fly queuing. Pambungkus adaptor kanggo RabbitMQ uga nindakake sawetara mirip RPC: kita ngirim pesen lan ngenteni respon saka antrian sementara khusus, sing digawe mung kanggo siji pesen respon.

kene conto nggunakake antrian karo nuansa sambungan dhasar.

ViennaNET.CallContext

Kita nggunakake antrian ora mung kanggo integrasi antarane sistem beda, nanging uga kanggo komunikasi antarane microservices saka aplikasi padha, contone, ing saga. Iki nyebabake kabutuhan ngirim pesen data tambahan kayata login pangguna, njaluk pengenal kanggo logging end-to-end, alamat IP sumber lan data wewenang. Kanggo ngleksanakake nerusake data iki, kita ngembangaken perpustakaan ViennaNET.CallContext, sing ngijini sampeyan kanggo nyimpen data saka panjalukan ngetik layanan. Ing kasus iki, cara panyuwunan digawe, liwat antrian utawa liwat Http, ora masalah. Banjur, sadurunge ngirim panjalukan utawa pesen sing metu, data dijupuk saka konteks lan diselehake ing header. Mangkono, layanan sabanjure nampa data tambahan lan ngatur kanthi cara sing padha.

Matur nuwun kanggo manungsa waé, kita ngarep-arep komentar lan narik panjalukan!

Source: www.habr.com

Add a comment