ViennaNET: backend uchun kutubxonalar to'plami. 2-qism

Raiffeisenbank .NET dasturchilar hamjamiyati ViennaNET tarkibini qisqacha ko'rib chiqishda davom etmoqda. Bunga qanday va nima uchun kelganimiz haqida, birinchi qismini o'qishingiz mumkin.

Ushbu maqolada biz GitHub omborimizda joylashgan taqsimlangan tranzaktsiyalar, navbatlar va ma'lumotlar bazalari bilan ishlash uchun hali ko'rib chiqilmagan kutubxonalarni ko'rib chiqamiz (manbalar shu yerda), va Nuget paketlari bu yerda.

ViennaNET: backend uchun kutubxonalar to'plami. 2-qism

ViennaNET.Sagas

Loyiha DDD va mikroservis arxitekturasiga o'tganda, keyin biznes mantig'i turli xizmatlar bo'ylab taqsimlanganda, taqsimlangan tranzaksiya mexanizmini amalga oshirish zarurati bilan bog'liq muammo paydo bo'ladi, chunki ko'plab stsenariylar ko'pincha bir vaqtning o'zida bir nechta domenlarga ta'sir qiladi. Siz bunday mexanizmlar bilan batafsilroq tanishishingiz mumkin, masalan, "Mikroservis naqshlari" kitobida, Kris Richardson.

Loyihalarimizda biz oddiy, ammo foydali mexanizmni amalga oshirdik: doston, toʻgʻrirogʻi, orkestrga asoslangan doston. Uning mohiyati quyidagicha: ma'lum bir biznes stsenariysi mavjud bo'lib, unda turli xizmatlarda operatsiyalarni ketma-ket bajarish kerak bo'ladi va agar biron bir bosqichda biron bir muammo yuzaga kelsa, oldingi barcha bosqichlar uchun orqaga qaytarish protsedurasini chaqirish kerak. taqdim etilgan. Shunday qilib, dostonning oxirida, muvaffaqiyatdan qat'i nazar, biz barcha domenlarda izchil ma'lumotlarni olamiz.

Bizning amalga oshirishimiz hali ham asosiy shaklda amalga oshiriladi va boshqa xizmatlar bilan o'zaro aloqa qilishning hech qanday usullaridan foydalanish bilan bog'liq emas. Foydalanish qiyin emas: shunchaki SagaBase<T> abstrakt sinfining asosiy avlodini yarating, bu erda T sizning kontekst sinfingiz bo'lib, unda dostonning ishlashi uchun zarur bo'lgan dastlabki ma'lumotlarni, shuningdek, ba'zi oraliq natijalarni saqlashingiz mumkin. Kontekst namunasi bajarish paytida barcha bosqichlarga o'tadi. Saga o'zi fuqaroligi bo'lmagan sinfdir, shuning uchun kerakli bog'liqliklarni olish uchun namunani DI-ga Singleton sifatida joylashtirish mumkin.

Misol reklama:

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

Misol chaqiruvi:

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

Turli xil ilovalarning to'liq misollarini ko'rish mumkin shu yerda va yig'ilishda testlar.

ViennaNET.Orm.*

Nhibernate orqali turli ma'lumotlar bazalari bilan ishlash uchun kutubxonalar to'plami. Biz Liquibase-dan foydalangan holda DB-First yondashuvidan foydalanamiz, shuning uchun faqat tayyor ma'lumotlar bazasida ma'lumotlar bilan ishlash uchun funksionallik mavjud.

ViennaNET.Orm.Seedwork и ViennaNET.Orm - mos ravishda asosiy interfeyslarni va ularni amalga oshirishni o'z ichiga olgan asosiy yig'ilishlar. Keling, ularning mazmunini batafsil ko'rib chiqaylik.

Interfeys IEntityFactoryService va uni amalga oshirish EntityFactoryService ma'lumotlar bazasi bilan ishlashning asosiy boshlang'ich nuqtasidir, chunki bu erda ish birligi, aniq ob'ektlar bilan ishlash uchun omborlar, shuningdek buyruqlar va to'g'ridan-to'g'ri SQL so'rovlarini bajaruvchilar yaratilgan. Ba'zan ma'lumotlar bazasi bilan ishlash uchun sinfning imkoniyatlarini cheklash qulay, masalan, faqat ma'lumotlarni o'qish qobiliyatini ta'minlash. Bunday holatlar uchun IEntityFactoryService ajdod interfeysi mavjud IEntityRepositoryFactory, bu faqat omborlarni yaratish usulini e'lon qiladi.

Ma'lumotlar bazasiga bevosita kirish uchun provayder mexanizmi qo'llaniladi. Bizning jamoalarimizda foydalanadigan har bir ma'lumotlar bazasi o'z dasturiga ega: ViennaNET.Orm.MSSQL, ViennaNET.Orm.Oracle, ViennaNET.Orm.SQLite, ViennaNET.Orm.PostgreSql.

Shu bilan birga, bir vaqtning o'zida bir nechta provayderlarni bitta ilovada ro'yxatdan o'tkazish mumkin, bu, masalan, bitta xizmat doirasida, infratuzilmani o'zgartirish uchun hech qanday xarajatlarsiz, bosqichma-bosqich ko'chirishni amalga oshirish imkonini beradi. bir DBMS boshqasiga. Kerakli ulanishni va shuning uchun ma'lum bir ob'ekt sinfi uchun provayderni tanlash mexanizmi (buning uchun ma'lumotlar bazasi jadvallariga xaritalash yoziladi) ob'ektni BoundedContext sinfida (domen ob'ektlarini ro'yxatdan o'tkazish usulini o'z ichiga oladi) yoki uning vorisi sifatida ro'yxatdan o'tkazish orqali amalga oshiriladi. ApplicationContext (ilova ob'ektlarini, to'g'ridan-to'g'ri so'rovlarni va buyruqlarni ro'yxatga olish usullarini o'z ichiga oladi), bu erda konfiguratsiyadan ulanish identifikatori argument sifatida qabul qilinadi:

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

Misol ApplicationContext:

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

Agar ulanish identifikatori ko'rsatilmagan bo'lsa, u holda "standart" deb nomlangan ulanish ishlatiladi.

Ob'ektlarni ma'lumotlar bazasi jadvallariga to'g'ridan-to'g'ri xaritalash standart NHibernate vositalari yordamida amalga oshiriladi. Siz tavsifdan xml fayllari orqali ham, sinflar orqali ham foydalanishingiz mumkin. Birlik testlarida stub omborlarini qulay yozish uchun kutubxona mavjud ViennaNET.TestUtils.Orm.

ViennaNET.Orm.* dan foydalanishning to'liq misollarini topish mumkin shu yerda.

ViennaNET.Messaging.*

Navbatlar bilan ishlash uchun kutubxonalar to'plami.

Navbatlar bilan ishlash uchun turli xil ma'lumotlar bazasi tizimlari bilan bir xil yondashuv tanlangan, ya'ni ishlatiladigan navbat menejeridan qat'i nazar, kutubxona bilan ishlash nuqtai nazaridan maksimal mumkin bo'lgan yagona yondashuv. Kutubxona ViennaNET.Messaging bu birlashish uchun aniq mas'uldir va ViennaNET.Messaging.MQSeriesQueue, ViennaNET.Messaging.RabbitMQQueue и ViennaNET.Messaging.KafkaQueue mos ravishda IBM MQ, RabbitMQ va Kafka uchun adapter ilovalarini o'z ichiga oladi.

Navbatlar bilan ishlashda ikkita jarayon mavjud: xabarni qabul qilish va uni jo'natish.

Qabul qilishni o'ylab ko'ring. Bu yerda 2 ta variant mavjud: uzluksiz tinglash va bitta xabarni qabul qilish. Doimiy ravishda navbatni tinglash uchun siz avval meros qilib olingan protsessor sinfini tavsiflashingiz kerak IMessageProcessor, kiruvchi xabarni qayta ishlash uchun javobgar bo'ladi. Keyinchalik, u ma'lum bir navbatga "bog'langan" bo'lishi kerak, bu ro'yxatdan o'tish orqali amalga oshiriladi IQueueReactorFactory konfiguratsiyadan navbat identifikatorini ko'rsatib:

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

Tinglashni boshlash misoli:

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

Keyin, xizmat ishga tushirilganda va usul tinglashni boshlash uchun chaqirilganda, belgilangan navbatdagi barcha xabarlar tegishli protsessorga o'tadi.

Zavod interfeysida bitta xabarni qabul qilish uchun IMessagingComponentFactory usuli bor CreateMessageReceiverunga ko'rsatilgan navbatdan xabar kutayotgan qabul qiluvchini yaratadi:

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

Xabar yuborish uchun xuddi shunday foydalanishingiz kerak IMessagingComponentFactory va xabar jo'natuvchini yarating:

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

Xabarni ketma-ketlashtirish va seriyadan chiqarishning uchta tayyor varianti mavjud: faqat matn, XML va JSON, lekin agar kerak bo'lsa, o'zingizning interfeys dasturlarini osongina qilishingiz mumkin. IMessageSerializer и IMessageDeserializer.

Biz har bir navbat menejerining o'ziga xos imkoniyatlarini saqlab qolishga harakat qildik, masalan. ViennaNET.Messaging.MQSeriesQueue nafaqat matnni, balki bayt xabarlarni ham yuborish imkonini beradi va ViennaNET.Messaging.RabbitMQQueue marshrutlash va tezkor navbatni qo'llab-quvvatlaydi. RabbitMQ uchun bizning adapter o'ramimiz RPC ning ba'zi o'xshashlarini ham amalga oshiradi: biz xabar yuboramiz va faqat bitta javob xabari uchun yaratilgan maxsus vaqtinchalik navbatdan javob kutamiz.

shu yerda asosiy ulanish nuanslari bilan navbatlardan foydalanishga misol.

ViennaNET.CallContext

Biz navbatlardan nafaqat turli tizimlar o'rtasida integratsiya qilish uchun, balki bir xil dasturning mikroservislari o'rtasidagi aloqa uchun ham foydalanamiz, masalan, doston ichida. Bu xabar bilan birga foydalanuvchi login, so'rov identifikatori, manba IP manzili va avtorizatsiya ma'lumotlari kabi yordamchi ma'lumotlarni uzatish zaruratiga olib keldi. Ushbu ma'lumotlarni uzatishni amalga oshirish uchun biz kutubxonani ishlab chiqdik ViennaNET.CallContext, bu sizga xizmatga kirgan so'rovdan ma'lumotlarni saqlash imkonini beradi. Bunday holda, so'rovning navbat yoki Http orqali qanday qilinganligi muhim emas. Keyin, chiquvchi so'rov yoki xabarni yuborishdan oldin, ma'lumotlar kontekstdan olinadi va sarlavhalarga joylashtiriladi. Shunday qilib, keyingi xizmat yordamchi ma'lumotlarni oladi va xuddi shu tarzda boshqaradi.

E'tiboringiz uchun rahmat, sharhlaringizni va so'rovlaringizni kutamiz!

Manba: www.habr.com

a Izoh qo'shish