ViennaNET: susunan perpustakaan pikeun backend nu. Bagian 2

Komunitas pamekar Raiffeisenbank .NET terus marios sakeudeung eusi ViennaNET. Ngeunaan kumaha sareng kunaon urang dugi ka ieu, anjeun tiasa maca bagian kahiji.

Dina artikel ieu, urang bakal ngaliwat perpustakaan-perpustakaan anu masih kénéh dianggap pikeun gawé bareng transaksi anu disebarkeun, antrian sareng pangkalan data, anu tiasa dipendakan dina gudang GitHub kami (sumber aya di dieu), Jeung Bungkusan Nuget di dieu.

ViennaNET: susunan perpustakaan pikeun backend nu. Bagian 2

ViennaNET.Sagas

Nalika proyék ngalih ka DDD sareng arsitéktur microservice, teras nalika logika bisnis disebarkeun kana jasa anu béda, timbul masalah anu aya hubunganana sareng kabutuhan pikeun nerapkeun mékanisme transaksi anu disebarkeun, sabab seueur skenario sering mangaruhan sababaraha domain sakaligus. Anjeun tiasa kenal sareng mékanisme sapertos langkung rinci, contona, dina buku "Pola Microservices", Chris Richardson.

Dina proyék-proyék kami, kami parantos ngalaksanakeun mékanisme anu sederhana tapi mangpaat: saga, atanapi langkung saga dumasar kana orkestrasi. Intina nyaéta kieu: aya hiji skenario bisnis nu tangtu, nu diperlukeun pikeun sequentially nedunan operasi di layanan béda, sarta lamun aya masalah timbul dina hambalan mana wae, perlu nelepon prosedur rollback pikeun sakabéh hambalan saméméhna, dimana éta. disadiakeun. Ku kituna, dina ahir saga, paduli sukses, urang nampi data konsisten dina sakabéh domain.

Palaksanaan kami masih dilakukeun dina bentuk dasarna sareng henteu aya hubunganana sareng pamakean metode interaksi sareng jasa anu sanés. Teu hésé ngagunakeun: ngan nyieun turunan tina kelas abstrak dasar SagaBase<T>, dimana T nyaeta kelas konteks anjeun nu bisa nyimpen data awal diperlukeun pikeun saga jalan, kitu ogé sababaraha hasil panengah. Instance kontéks bakal diteruskeun ka sadaya léngkah salami palaksanaan. Saga sorangan kelas stateless, jadi conto bisa ditempatkeun di DI salaku Singleton pikeun meunangkeun kagumantungan diperlukeun.

conto iklan:

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

conto panggero:

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

Conto lengkep ngeunaan palaksanaan anu béda tiasa ditingali di dieu sarta di assembly kalawan tés.

ViennaNET.Orm.*

Hiji set perpustakaan pikeun gawé bareng sagala rupa basis data via Nhibernate. Kami nganggo pendekatan DB-Mimiti nganggo Liquibase, janten ngan ukur aya fungsionalitas pikeun damel sareng data dina database anu siap-siap.

ViennaNET.Orm.Seedwork и ViennaNET.Orm - rakitan utama anu ngandung antarmuka dasar sareng palaksanaan masing-masing. Hayu urang nempo eusi maranéhanana dina leuwih jéntré.

interface IEntityFactoryService jeung palaksanaanana EntityFactoryService Éta titik awal utama pikeun gawé bareng database, saprak Unit Gawé, repositories pikeun gawé bareng entitas husus, kitu ogé executors paréntah sarta queries SQL langsung dijieun di dieu. Kadangkala kacida merenah pikeun ngawatesan kamampuhan hiji kelas pikeun gawé bareng database a, contona, nyadiakeun kamampuhan pikeun ngan maca data. Pikeun kasus sapertos kitu IEntityFactoryService aya karuhun - panganteur IEntityRepositoryFactory, anu ngan ukur nyatakeun metode pikeun nyiptakeun repositori.

Pikeun langsung ngaksés pangkalan data, mékanisme panyadia dianggo. Unggal DBMS anu kami anggo dina tim kami gaduh palaksanaan sorangan: ViennaNET.Orm.MSSQL, ViennaNET.Orm.Oracle, ViennaNET.Orm.SQLite, ViennaNET.Orm.PostgreSql.

Dina waktos anu sami, sababaraha panyadia tiasa didaptarkeun dina hiji aplikasi dina waktos anu sami, anu ngamungkinkeun, contona, dina kerangka hiji jasa, tanpa aya biaya pikeun ngarobih infrastruktur, ngalaksanakeun migrasi léngkah-léngkah ti hiji DBMS ka nu sejen. Mékanisme pikeun milih sambungan anu diperyogikeun sareng, ku kituna, panyadia pikeun kelas éntitas khusus (nu pemetaan kana tabel database ditulis) dilaksanakeun ngaliwatan ngadaptar éntitas dina kelas BoundedContext (ngandung metode pikeun ngadaptar éntitas domain) atanapi panerusna. ApplicationContext (ngandung metode pikeun ngadaptar éntitas aplikasi, pamundut langsung sareng paréntah), dimana identifier sambungan tina konfigurasi ditarima salaku 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");
  }
}

Lamun ID sambungan teu dieusian, sambungan ngaranna "standar" bakal dipaké.

Pemetaan langsung éntitas kana tabel database dilaksanakeun nganggo alat NHibernate standar. Anjeun tiasa nganggo pedaran duanana ngaliwatan file xml sarta ngaliwatan kelas. Pikeun merenah nulis repositories rintisan dina tés Unit, aya perpustakaan ViennaNET.TestUtils.Orm.

conto pinuh ngagunakeun ViennaNET.Orm.* bisa kapanggih di dieu.

ViennaNET.Olahtalatah.*

Hiji set perpustakaan pikeun gawé bareng antrian.

Pikeun dianggo sareng antrian, pendekatan anu sami dipilih sareng sababaraha DBMS, nyaéta, pendekatan ngahijikeun maksimal anu mungkin dina hal damel sareng perpustakaan, henteu paduli manajer antrian anu dianggo. Perpustakaan ViennaNET.Messaging persis jawab ngahijikeun ieu, jeung ViennaNET.Messaging.MQSeriesQueue, ViennaNET.Messaging.RabbitMQQueue и ViennaNET.Messaging.KafkaQueue ngandung palaksanaan adaptor pikeun IBM MQ, RabbitMQ sareng Kafka, masing-masing.

Nalika damel sareng antrian, aya dua prosés: nampi pesen sareng ngirimna.

Mertimbangkeun narima. Aya 2 pilihan di dieu: pikeun ngupingkeun kontinyu sareng pikeun nampi pesen tunggal. Pikeun terus ngadangukeun antrian, Anjeun mimitina kudu ngajelaskeun kelas processor diwariskeun ti IMessageProcessor, anu bakal nanggungjawaban kanggo ngolah pesen anu asup. Salajengna, éta kedah "numbu" ka antrian khusus; ieu dilakukeun ngaliwatan pendaptaran di IQueueReactorFactory nunjukkeun identifier antrian tina konfigurasi:

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

Conto ngamimitian ngadangukeun:

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

Teras, nalika jasa dimimitian sareng metodeu disebut pikeun ngamimitian ngupingkeun, sadaya pesen tina antrian anu ditangtukeun bakal angkat ka prosesor anu saluyu.

Pikeun nampa pesen tunggal dina panganteur pabrik IMessagingComponentFactory aya padika CreateMessageReceivernu bakal nyieun panarima ngantosan pesen ti antrian dieusian pikeun eta:

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

Pikeun ngirim pesen anjeun kedah nganggo anu sami IMessagingComponentFactory sareng jieun pangirim pesen:

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

Aya tilu pilihan siap-dijieun pikeun serializing na deserializing pesen: ngan téks, XML jeung JSON, tapi lamun perlu, anjeun bisa kalayan gampang nyieun palaksanaan panganteur sorangan. IMessageSerializer и IMessageDeserializer.

Kami geus diusahakeun pikeun ngawétkeun kamampuhan unik unggal manajer antrian, f.eks. ViennaNET.Messaging.MQSeriesQueue ngidinan Anjeun pikeun ngirim teu ukur téks, tapi ogé pesen bait, jeung ViennaNET.Messaging.RabbitMQQueue ngarojong routing na on-the-fly antrian. Adaptor wrapper kami pikeun RabbitMQ ogé implements sababaraha semblance of RPC: urang ngirim pesen jeung ngadagoan respon ti antrian samentara husus, nu dijieun ngan pikeun hiji pesen respon.

di dieu conto ngagunakeun antrian kalawan nuansa sambungan dasar.

ViennaNET.CallContext

Urang make antrian henteu ngan pikeun integrasi antara sistem béda, tapi ogé pikeun komunikasi antara microservices tina aplikasi anu sarua, Contona, dina saga a. Ieu nyababkeun kabutuhan pikeun ngirimkeun sareng pesen data tambahan sapertos login pangguna, idéntifikasi pamundut pikeun logging tungtung-ka-tungtung, alamat IP sumber sareng data otorisasi. Pikeun ngalaksanakeun diteruskeun data ieu, kami ngembangkeun perpustakaan ViennaNET.CallContext, nu ngidinan Anjeun pikeun nyimpen data ti pamundut ngasupkeun jasa. Dina hal ieu, cara pamundut dijieun, ngaliwatan antrian atawa via Http, henteu masalah. Teras, sateuacan ngirim pamundut atanapi pesen anu kaluar, data dicandak tina kontéks sareng disimpen dina lulugu. Janten, jasa salajengna nampi data bantu sareng ngaturna ku cara anu sami.

Hatur nuhun kana perhatian anjeun, kami ngarepkeun koméntar anjeun sareng paménta tarik!

sumber: www.habr.com

Tambahkeun komentar