ViennaNET: arxa plan üçün kitabxanalar dəsti. 2-ci hissə

Raiffeisenbank .NET developer icması ViennaNET-in məzmununu qısaca nəzərdən keçirməyə davam edir. Buna necə və niyə gəldiyimiz haqqında, birinci hissəni oxuya bilərsiniz.

Bu yazıda biz GitHub depomuzda tapıla bilən paylanmış əməliyyatlar, növbələr və verilənlər bazası ilə işləmək üçün hələ nəzərdən keçirilməmiş kitabxanaları nəzərdən keçirəcəyik (mənbələr buradadır), və Nuget paketləri burada.

ViennaNET: arxa plan üçün kitabxanalar dəsti. 2-ci hissə

ViennaNET.Sagas

Layihə DDD və mikroservis arxitekturasına keçdikdə, sonra biznes məntiqi müxtəlif xidmətlər üzrə paylandıqda, paylanmış əməliyyat mexanizminin həyata keçirilməsi zərurəti ilə bağlı problem yaranır, çünki bir çox ssenarilər tez-tez bir anda bir neçə domenə təsir göstərir. Bu cür mexanizmlərlə daha ətraflı tanış ola bilərsiniz, məsələn, "Mikroservis nümunələri" kitabında, Chris Richardson.

Layihələrimizdə sadə, lakin faydalı mexanizm həyata keçirmişik: dastan, daha doğrusu orkestr əsaslı dastan. Onun mahiyyəti belədir: müəyyən bir iş ssenarisi var ki, burada müxtəlif xidmətlərdə ardıcıl olaraq əməliyyatlar aparmaq lazımdır və hər hansı bir addımda hər hansı problem yaranarsa, bütün əvvəlki addımlar üçün geri qaytarma prosedurunu çağırmaq lazımdır. təmin edilmişdir. Beləliklə, dastanın sonunda, uğurdan asılı olmayaraq, bütün domenlərdə ardıcıl məlumatlar alırıq.

Bizim həyata keçirməmiz hələ də əsas formada həyata keçirilir və digər xidmətlərlə qarşılıqlı əlaqənin heç bir metodunun istifadəsi ilə bağlı deyil. İstifadəsi çətin deyil: sadəcə SagaBase<T> əsas abstrakt sinifinin nəslini yaradın, burada T sizin kontekst sinifinizdir, burada dastanın işləməsi üçün lazım olan ilkin məlumatları, eləcə də bəzi aralıq nəticələri saxlaya bilərsiniz. Kontekst nümunəsi icra zamanı bütün addımlara ötürüləcək. Saga özü vətəndaşlığı olmayan bir sinifdir, ona görə də nümunə lazımi asılılıqları əldə etmək üçün DI-də Singleton olaraq yerləşdirilə bilər.

Nümunə reklam:

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

Zəng nümunəsi:

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

Müxtəlif tətbiqlərin tam nümunələrinə baxmaq olar burada və ilə montajda testlər.

ViennaNET.Orm.*

Nhibernate vasitəsilə müxtəlif verilənlər bazaları ilə işləmək üçün kitabxanalar dəsti. Biz Liquibase-dən istifadə edərək DB-First yanaşmasından istifadə edirik, ona görə də hazır verilənlər bazasında verilənlərlə işləmək üçün yalnız funksionallıq var.

ViennaNET.Orm.Seedwork и ViennaNET.Orm – müvafiq olaraq əsas interfeysləri və onların tətbiqlərini ehtiva edən əsas montajlar. Onların məzmununa daha ətraflı baxaq.

interface IEntityFactoryService və onun həyata keçirilməsi EntityFactoryService verilənlər bazası ilə işləmək üçün əsas başlanğıc nöqtəsidir, çünki burada İş Vahidi, konkret qurumlarla işləmək üçün depolar, həmçinin əmrlərin icraçıları və birbaşa SQL sorğuları yaradılır. Bəzən verilənlər bazası ilə işləmək üçün bir sinfin imkanlarını məhdudlaşdırmaq, məsələn, yalnız məlumatları oxumaq qabiliyyətini təmin etmək rahatdır. Belə hallar üçün IEntityFactoryService bir əcdad - interfeys var IEntityRepositoryFactory, yalnız depolar yaratmaq üçün bir üsul elan edir.

Verilənlər bazasına birbaşa daxil olmaq üçün provayder mexanizmindən istifadə olunur. Komandalarımızda istifadə etdiyimiz hər bir DBMS-in öz tətbiqi var: ViennaNET.Orm.MSSQL, ViennaNET.Orm.Oracle, ViennaNET.Orm.SQLite, ViennaNET.Orm.PostgreSql.

Eyni zamanda, bir tətbiqdə eyni vaxtda bir neçə provayder qeydiyyata alına bilər ki, bu da, məsələn, bir xidmət çərçivəsində, infrastrukturun dəyişdirilməsi üçün heç bir xərc çəkmədən, addım-addım miqrasiyanı həyata keçirməyə imkan verir. bir DBMS digərinə. Tələb olunan əlaqənin və buna görə də, müəyyən bir obyekt sinfi üçün provayderin seçilməsi mexanizmi (bunun üçün verilənlər bazası cədvəllərinə xəritəçəkmə yazılır) obyektin BoundedContext sinfində (domen obyektlərinin qeydiyyatı metodunu ehtiva edir) və ya onun varisinin qeydiyyatı yolu ilə həyata keçirilir. ApplicationContext (tətbiq obyektlərinin, birbaşa sorğuların və əmrlərin qeydiyyatı üsullarını ehtiva edir), burada konfiqurasiyadan əlaqə identifikatoru arqument kimi qəbul edilir:

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

Tətbiq kontekstinə nümunə:

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

Bağlantı identifikatoru göstərilməyibsə, "defolt" adlı əlaqə istifadə olunacaq.

Müəssisələrin verilənlər bazası cədvəllərinə birbaşa xəritələşdirilməsi standart NHibernate alətlərindən istifadə etməklə həyata keçirilir. Təsviri həm xml faylları, həm də siniflər vasitəsilə istifadə edə bilərsiniz. Unit testlərində stub depolarının rahat yazılması üçün kitabxana var ViennaNET.TestUtils.Orm.

ViennaNET.Orm.* istifadəsinin tam nümunələri tapıla bilər burada.

ViennaNET.Messaging.*

Növbələrlə işləmək üçün kitabxanalar toplusu.

Növbələrlə işləmək üçün müxtəlif DBMS-lərdə olduğu kimi eyni yanaşma, yəni istifadə olunan növbə menecerindən asılı olmayaraq kitabxana ilə işləmək baxımından maksimum mümkün vahid yanaşma seçildi. Kitabxana ViennaNET.Messaging bu birləşməyə dəqiq cavabdehdir və ViennaNET.Messaging.MQSeriesQueue, ViennaNET.Messaging.RabbitMQQueue и ViennaNET.Messaging.KafkaQueue müvafiq olaraq IBM MQ, RabbitMQ və Kafka üçün adapter tətbiqlərini ehtiva edir.

Növbələrlə işləyərkən iki proses var: mesajın qəbulu və göndərilməsi.

Qəbul etməyi düşünün. Burada 2 seçim var: davamlı dinləmək və tək mesaj almaq üçün. Növbəyə daim qulaq asmaq üçün əvvəlcə ondan miras qalmış prosessor sinfini təsvir etməlisiniz IMessageProcessor, gələn mesajın emalına cavabdeh olacaq. Sonra, müəyyən bir növbə ilə "əlaqələndirilməlidir"; bu, qeydiyyat yolu ilə həyata keçirilir IQueueReactorFactory konfiqurasiyadan növbə identifikatorunu göstərməklə:

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

Dinləməyə başlama nümunəsi:

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

Sonra xidmət işə salındıqda və dinləməyə başlamaq üçün metod çağırıldıqda, göstərilən növbədən gələn bütün mesajlar müvafiq prosessora gedəcək.

Zavod interfeysində tək mesaj almaq üçün IMessagingComponentFactory üsulu var CreateMessageReceiverona göstərilən növbədən mesaj gözləyən bir alıcı yaradacaq:

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

Mesaj göndərmək üçün eynisini istifadə etmək lazımdır IMessagingComponentFactory və mesaj göndərən yaradın:

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

Mesajı seriallaşdırmaq və sıradan çıxarmaq üçün üç hazır seçim var: sadəcə mətn, XML və JSON, lakin lazım gələrsə, asanlıqla öz interfeys tətbiqlərinizi edə bilərsiniz. IMessageSerializer и IMessageDeserializer.

Biz hər növbə menecerinin unikal imkanlarını qorumağa çalışmışıq, məs. ViennaNET.Messaging.MQSeriesQueue yalnız mətn deyil, həm də bayt mesajları göndərməyə imkan verir və ViennaNET.Messaging.RabbitMQQueue marşrutlaşdırma və on-the-fly növbə dəstəkləyir. RabbitMQ üçün adapter paketimiz də RPC-yə bənzəyir: biz mesaj göndəririk və yalnız bir cavab mesajı üçün yaradılan xüsusi müvəqqəti növbədən cavab gözləyirik.

Burada əsas əlaqə nüansları ilə növbələrdən istifadə nümunəsi.

ViennaNET.CallContext

Biz növbələrdən təkcə müxtəlif sistemlər arasında inteqrasiya üçün deyil, həm də eyni proqramın mikroservisləri arasında, məsələn, dastan daxilində ünsiyyət üçün istifadə edirik. Bu, mesajla birlikdə istifadəçi girişi, uç-to-end giriş üçün sorğu identifikatoru, mənbə IP ünvanı və avtorizasiya məlumatları kimi köməkçi məlumatların ötürülməsi ehtiyacına səbəb oldu. Bu məlumatların ötürülməsini həyata keçirmək üçün biz bir kitabxana hazırladıq ViennaNET.CallContext, bu, xidmətə daxil olan sorğudan məlumatları saxlamağa imkan verir. Bu halda sorğunun növbə və ya Http vasitəsilə necə edildiyinin əhəmiyyəti yoxdur. Sonra, gedən sorğu və ya mesajı göndərməzdən əvvəl məlumatlar kontekstdən götürülür və başlıqlara yerləşdirilir. Beləliklə, növbəti xidmət köməkçi məlumatları alır və eyni şəkildə idarə edir.

Diqqətiniz üçün təşəkkür edirik, şərhlərinizi və istəklərinizi gözləyirik!

Mənbə: www.habr.com

Добавить комментарий