ViennaNET: серверге арналған кітапханалар жинағы. 2-бөлім

Raiffeisenbank .NET әзірлеушілер қауымдастығы ViennaNET мазмұнын қысқаша шолуды жалғастыруда. Бұған қалай және неліктен келгеніміз туралы, бірінші бөлімін оқуға болады.

Бұл мақалада біз GitHub репозиторийінен табуға болатын бөлінген транзакциялармен, кезектермен және дерекқорлармен жұмыс істеуге арналған әлі қарастырылмаған кітапханаларды қарастырамыз (көздері осында), және Nuget пакеттері осында.

ViennaNET: серверге арналған кітапханалар жинағы. 2-бөлім

ViennaNET.Sagas

Жоба DDD және микросервис архитектурасына ауысқанда, содан кейін бизнес логикасы әртүрлі қызметтерге бөлінгенде, таратылған транзакция механизмін енгізу қажеттілігіне байланысты мәселе туындайды, себебі көптеген сценарийлер жиі бірден бірнеше домендерге әсер етеді. Мұндай механизмдермен толығырақ танысуға болады, мысалы, «Микросервис үлгілері» кітабында, Крис Ричардсон.

Біздің жобаларымызда біз қарапайым, бірақ пайдалы механизмді енгіздік: дастан, дәлірек айтсақ, оркестрге негізделген дастан. Оның мәні келесідей: әртүрлі қызметтерде операцияларды дәйекті түрде орындау қажет болатын белгілі бір бизнес-сценарий бар және кез келген қадамда қандай да бір мәселе туындаса, барлық алдыңғы қадамдар үшін кері қайтару процедурасын шақыру қажет, мұнда ол орындалады. қамтамасыз етілген. Осылайша, дастанның соңында, табысқа қарамастан, біз барлық домендерде дәйекті деректерді аламыз.

Біздің іске асыруымыз әлі де оның негізгі нысанында жасалған және басқа қызметтермен өзара әрекеттесу әдістерін пайдаланумен байланысты емес. Оны пайдалану қиын емес: жай ғана SagaBase<T> дерексіз негізгі классының ұрпағын жасаңыз, мұнда T - дастандар жұмысына қажетті бастапқы деректерді, сондай-ақ кейбір аралық нәтижелерді сақтауға болатын мәтінмәндік класс. Мәтінмән данасы орындау кезінде барлық қадамдарға өтеді. Саганың өзі азаматтығы жоқ сынып, сондықтан қажетті тәуелділіктерді алу үшін дананы DI-ға Singleton ретінде орналастыруға болады.

Жарнама мысалы:

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

Мысал шақыру:

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

Әртүрлі енгізулердің толық мысалдарын көруге болады осында және құрастыруда сынақтар.

ViennaNET.Orm.*

Nhibernate арқылы әртүрлі дерекқорлармен жұмыс істеуге арналған кітапханалар жиынтығы. Біз Liquibase көмегімен DB-First әдісін қолданамыз, сондықтан дайын дерекқордағы деректермен жұмыс істеуге ғана мүмкіндік бар.

ViennaNET.Orm.Seedwork и ViennaNET.Orm – тиісінше негізгі интерфейстерді және оларды іске асыруды қамтитын негізгі жинақтар. Олардың мазмұнын толығырақ қарастырайық.

интерфейс IEntityFactoryService және оны жүзеге асыру EntityFactoryService дерекқормен жұмыс істеудің негізгі бастапқы нүктесі болып табылады, өйткені мұнда Жұмыс бірлігі, нақты нысандармен жұмыс істеуге арналған репозиторийлер, сондай-ақ командаларды және тікелей SQL сұрауларын орындаушылар жасалады. Кейде деректер қорымен жұмыс істеу үшін сыныптың мүмкіндіктерін шектеу ыңғайлы, мысалы, тек деректерді оқу мүмкіндігін қамтамасыз ету. Мұндай жағдайлар үшін IEntityFactoryService интерфейсі бар IEntityRepositoryFactory, ол тек репозиторийлерді жасау әдісін жариялайды.

Деректер базасына тікелей қол жеткізу үшін провайдер механизмі қолданылады. Командаларымызда қолданатын әрбір ДҚБЖ-ның өзіндік іске асырылуы бар: ViennaNET.Orm.MSSQL, ViennaNET.Orm.Oracle, ViennaNET.Orm.SQLite, ViennaNET.Orm.PostgreSql.

Бұл ретте бір қосымшада бірнеше провайдерлерді бір уақытта тіркеуге болады, бұл, мысалы, бір қызмет аясында инфрақұрылымды өзгертуге ешқандай шығынсыз, көшіруді келесіден кезең-кезеңімен жүзеге асыруға мүмкіндік береді. бір ДҚБЖ екіншісіне. Қажетті қосылымды және, демек, белгілі бір нысан класы үшін провайдерді таңдау механизмі (ол үшін дерекқор кестелеріне салыстыру жазылады) нысанды BoundedContext сыныбында (домен нысандарын тіркеу әдісін қамтиды) немесе оның мұрагерін тіркеу арқылы жүзеге асырылады. ApplicationContext (бағдарлама нысандарын, тікелей сұрауларды және пәрмендерді тіркеу әдістерін қамтиды), мұнда конфигурациядан қосылым идентификаторы аргумент ретінде қабылданады:

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

ApplicationContext мысалы:

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

Қосылым идентификаторы көрсетілмесе, «әдепкі» деп аталатын қосылым пайдаланылады.

Нысандарды дерекқор кестелеріне тікелей салыстыру стандартты NHibernate құралдары арқылы жүзеге асырылады. Сипаттаманы xml файлдары арқылы да, сыныптар арқылы да пайдалануға болады. Unit тесттерінде stub репозиторийлерін ыңғайлы жазу үшін кітапхана бар ViennaNET.TestUtils.Orm.

ViennaNET.Orm.* пайдаланудың толық мысалдарын табуға болады осында.

ViennaNET.Messaging.*

Кезекпен жұмыс істеуге арналған кітапханалар жинағы.

Кезектермен жұмыс істеу үшін әртүрлі ДҚБЖ-мен бірдей тәсіл таңдалды, атап айтқанда, пайдаланылған кезек менеджеріне қарамастан кітапханамен жұмыс істеу тұрғысынан барынша мүмкін болатын бірыңғай тәсіл. Кітапхана ViennaNET.Messaging осы біріктіру үшін дәл жауапты, және ViennaNET.Messaging.MQSeriesQueue, ViennaNET.Messaging.RabbitMQQueue и ViennaNET.Messaging.KafkaQueue тиісінше IBM MQ, RabbitMQ және Kafka үшін адаптер енгізулерін қамтиды.

Кезекпен жұмыс істегенде екі процесс бар: хабарламаны қабылдау және оны жіберу.

Қабылдауды қарастырыңыз. Мұнда 2 опция бар: үздіксіз тыңдау және бір хабарламаны алу. Кезекті үнемі тыңдау үшін алдымен мұраланған процессор класын сипаттау керек IMessageProcessor, ол кіріс хабарламаны өңдеуге жауапты болады. Әрі қарай, ол белгілі бір кезекпен «байланыстырылуы» керек; бұл тіркеу арқылы жүзеге асырылады IQueueReactorFactory конфигурациядан кезек идентификаторын көрсете отырып:

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

Тыңдауды бастау мысалы:

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

Содан кейін қызмет іске қосылғанда және тыңдауды бастау үшін әдіс шақырылғанда, көрсетілген кезектегі барлық хабарламалар сәйкес процессорға өтеді.

Зауыттық интерфейсте бір хабарды алу үшін IMessagingComponentFactory әдісі бар CreateMessageReceiverол өзіне көрсетілген кезектен хабар күтетін алушыны жасайды:

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

Хабарлама жіберу үшін бірдей пайдалану керек IMessagingComponentFactory және хабарлама жіберушіні жасаңыз:

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

Хабарламаны сериялау және сериядан шығарудың үш дайын нұсқасы бар: тек мәтін, XML және JSON, бірақ қажет болса, интерфейсті өзіңіздің жеке іске асыруды оңай жасауға болады. IMessageSerializer и IMessageDeserializer.

Біз әрбір кезек менеджерінің бірегей мүмкіндіктерін сақтауға тырыстық, мысалы. ViennaNET.Messaging.MQSeriesQueue мәтінді ғана емес, сонымен қатар байт хабарламаларын жіберуге мүмкіндік береді, және ViennaNET.Messaging.RabbitMQQueue маршруттауды және жедел кезекті қолдайды. RabbitMQ үшін адаптер орауышымыз да RPC-нің кейбір ұқсастығын жүзеге асырады: біз хабарлама жібереміз және тек бір жауап хабарламасы үшін жасалған арнайы уақытша кезектен жауапты күтеміз.

осында негізгі қосылым нюанстары бар кезектерді пайдалану мысалы.

ViennaNET.CallContext

Біз кезектерді әртүрлі жүйелер арасындағы интеграция үшін ғана емес, сонымен қатар бір қолданбаның микросервистері арасындағы байланыс үшін де қолданамыз, мысалы, дастан ішінде. Бұл хабарламамен бірге пайдаланушының логині, үздіксіз тіркеуге арналған сұрау идентификаторы, бастапқы IP мекенжайы және авторизация деректері сияқты көмекші деректерді беру қажеттілігіне әкелді. Бұл деректерді жіберуді жүзеге асыру үшін біз кітапхана жасадық ViennaNET.CallContext, бұл қызметке кіретін сұраудан деректерді сақтауға мүмкіндік береді. Бұл жағдайда сұраныстың кезек немесе Http арқылы қалай жасалғаны маңызды емес. Содан кейін, шығыс сұрауды немесе хабарламаны жібермес бұрын, деректер контекстен алынады және тақырыптарға орналастырылады. Осылайша, келесі қызмет көмекші деректерді алады және оны дәл осылай басқарады.

Назарларыңызға рахмет, пікірлеріңіз бен сұрауларыңызды күтеміз!

Ақпарат көзі: www.habr.com

пікір қалдыру