ViennaNET: arka uç için bir dizi kütüphane. Bölüm 2

Raiffeisenbank .NET geliştirici topluluğu ViennaNET içeriğini kısaca incelemeye devam ediyor. Bu noktaya nasıl ve neden geldiğimizi, ilk bölümü okuyabilirsiniz.

Bu makalede, GitHub depomuzda (kaynaklar burada), Ve Nuget paketleri burada.

ViennaNET: arka uç için bir dizi kütüphane. Bölüm 2

ViyanaNET.Sagas

Bir proje DDD'ye ve mikro hizmet mimarisine geçtiğinde, iş mantığı farklı hizmetlere dağıtıldığında, dağıtılmış bir işlem mekanizması uygulama ihtiyacıyla ilgili bir sorun ortaya çıkar, çünkü birçok senaryo genellikle aynı anda birden fazla etki alanını etkiler. Bu tür mekanizmaları daha ayrıntılı olarak tanıyabilirsiniz, örneğin, "Mikro Hizmet Modelleri" kitabında, Chris Richardson.

Projelerimizde basit ama kullanışlı bir mekanizmayı hayata geçirdik: bir destan, daha doğrusu orkestrasyona dayalı bir destan. Özü şu şekildedir: Farklı hizmetlerde işlemleri sırayla gerçekleştirmenin gerekli olduğu belirli bir iş senaryosu vardır ve herhangi bir adımda herhangi bir sorun ortaya çıkarsa, önceki tüm adımlar için geri alma prosedürünü, olduğu yerde çağırmak gerekir. tedarik edilen. Böylece destanın sonunda başarıdan bağımsız olarak tüm alanlarda tutarlı veriler elde ederiz.

Uygulamamız hala temel haliyle yapılmaktadır ve diğer hizmetlerle herhangi bir etkileşim yönteminin kullanımına bağlı değildir. Kullanımı zor değil: sadece temel soyut sınıf SagaBase<T>'nin bir soyunu oluşturun; burada T, destanın çalışması için gerekli başlangıç ​​verilerinin yanı sıra bazı ara sonuçları saklayabileceğiniz bağlam sınıfınızdır. Bağlam örneği yürütme sırasında tüm adımlara aktarılacaktır. Saga'nın kendisi durum bilgisi olmayan bir sınıf olduğundan örnek, gerekli bağımlılıkları elde etmek için DI'ye Singleton olarak yerleştirilebilir.

Örnek reklam:

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

Örnek çağrı:

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

Farklı uygulamaların tam örnekleri görülebilir burada ve montaj halinde testler.

ViennaNET.Orm.*

Nhibernate aracılığıyla çeşitli veritabanlarıyla çalışmak için bir dizi kitaplık. Liquibase'i kullanarak DB-First yaklaşımını kullanıyoruz, dolayısıyla yalnızca hazır bir veritabanındaki verilerle çalışmaya yönelik işlevsellik var.

ViennaNET.Orm.Seedwork и ViennaNET.Orm – sırasıyla temel arayüzleri ve bunların uygulamalarını içeren ana düzenekler. İçeriklerine daha detaylı bakalım.

Arayüz. IEntityFactoryService ve uygulanması EntityFactoryService İş Birimi, belirli varlıklarla çalışmaya yönelik depoların yanı sıra komutların yürütücüleri ve doğrudan SQL sorguları burada oluşturulduğundan, veritabanıyla çalışmanın ana başlangıç ​​​​noktasıdır. Bazen bir sınıfın bir veritabanıyla çalışma yeteneklerini sınırlamak, örneğin yalnızca veri okuma yeteneği sağlamak uygun olabilir. Bu gibi durumlar için IEntityFactoryService bir ata var - arayüz IEntityRepositoryFactory, yalnızca depo oluşturmak için bir yöntem bildirir.

Veritabanına doğrudan erişim için sağlayıcı mekanizması kullanılır. Ekiplerimizde kullandığımız her DBMS'nin kendi uygulaması vardır: ViennaNET.Orm.MSSQL, ViennaNET.Orm.Oracle, ViennaNET.Orm.SQLite, ViennaNET.Orm.PostgreSql.

Aynı zamanda, birden fazla sağlayıcı aynı anda bir uygulamaya kaydedilebilir; bu, örneğin tek bir hizmet çerçevesinde, altyapıyı değiştirmek için herhangi bir maliyet olmaksızın, adım adım geçişin gerçekleştirilmesine olanak tanır. bir DBMS'den diğerine. Gerekli bağlantıyı ve dolayısıyla belirli bir varlık sınıfı için sağlayıcıyı (veritabanı tablolarına eşlemenin yazıldığı) seçme mekanizması, varlığın BoundedContext sınıfına (etki alanı varlıklarını kaydetmeye yönelik bir yöntem içerir) veya onun ardılına kaydedilmesi yoluyla uygulanır. ApplicationContext (uygulama varlıklarını, doğrudan istekleri ve komutları kaydetmeye yönelik yöntemleri içerir), burada yapılandırmadaki bağlantı tanımlayıcısı argüman olarak kabul edilir:

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

Örnek Uygulama Bağlamı:

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

Bağlantı ID'si belirtilmezse “varsayılan” adlı bağlantı kullanılacaktır.

Varlıkların veritabanı tablolarına doğrudan eşlenmesi, standart NHibernate araçları kullanılarak uygulanır. Açıklamayı hem xml dosyaları hem de sınıflar aracılığıyla kullanabilirsiniz. Birim testlerinde saplama havuzlarının uygun şekilde yazılması için bir kütüphane bulunmaktadır. ViennaNET.TestUtils.Orm.

ViennaNET.Orm.* kullanımının tam örneklerini burada bulabilirsiniz burada.

ViennaNET.Messaging.*

Kuyruklarla çalışmak için bir dizi kitaplık.

Kuyruklarla çalışmak için çeşitli DBMS'lerde olduğu gibi aynı yaklaşım, yani kullanılan kuyruk yöneticisinden bağımsız olarak kütüphaneyle çalışma açısından mümkün olan maksimum birleşik yaklaşım seçildi. Kütüphane ViennaNET.Messaging bu birleşmeden kesinlikle sorumludur ve ViennaNET.Messaging.MQSeriesQueue, ViennaNET.Messaging.RabbitMQQueue и ViennaNET.Messaging.KafkaQueue sırasıyla IBM MQ, RabbitMQ ve Kafka için bağdaştırıcı uygulamalarını içerir.

Kuyruklarla çalışırken iki süreç vardır: mesajın alınması ve gönderilmesi.

Almayı düşünün. Burada 2 seçenek var: sürekli dinlemek ve tek mesaj almak için. Kuyruğu sürekli dinlemek için öncelikle devralınan işlemci sınıfını tanımlamanız gerekir. IMessageProcessor, gelen mesajın işlenmesinden sorumlu olacak. Daha sonra belirli bir kuyruğa "bağlanması" gerekir; bu, kayıt yoluyla yapılır; IQueueReactorFactory konfigürasyondaki kuyruk tanımlayıcısını belirterek:

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

Dinlemeye başlama örneği:

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

Daha sonra hizmet başladığında ve dinlemeye başlamak için yöntem çağrıldığında, belirtilen kuyruktaki tüm mesajlar ilgili işlemciye gidecektir.

Fabrika arayüzünde tek bir mesaj almak için IMessagingComponentFactory bir yöntem var CreateMessageReceiverbu, kendisine belirtilen kuyruktan mesaj bekleyen bir alıcı yaratacaktır:

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

Mesaj göndermek için aynısını kullanmanız gerekiyor IMessagingComponentFactory ve bir mesaj göndereni oluşturun:

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

Bir mesajı serileştirmek ve seri durumdan çıkarmak için üç hazır seçenek vardır: yalnızca metin, XML ve JSON, ancak gerekirse kendi arayüz uygulamalarınızı kolayca yapabilirsiniz. IMessageSerializer и IMessageDeserializer.

Her kuyruk yöneticisinin benzersiz yeteneklerini korumaya çalıştık; ViennaNET.Messaging.MQSeriesQueue yalnızca metin değil aynı zamanda bayt mesajları da göndermenize olanak tanır ve ViennaNET.Messaging.RabbitMQQueue Yönlendirmeyi ve anında sıraya almayı destekler. RabbitMQ için bağdaştırıcı sarmalayıcımız aynı zamanda bir tür RPC'yi de uygular: bir mesaj göndeririz ve yalnızca bir yanıt mesajı için oluşturulan özel bir geçici kuyruktan yanıt bekleriz.

Burada temel bağlantı nüanslarıyla kuyrukların kullanılmasına bir örnek.

ViennaNET.CallContext

Kuyrukları yalnızca farklı sistemler arasındaki entegrasyon için değil, aynı uygulamanın mikro hizmetleri arasındaki iletişim için de (örneğin bir destan içinde) kullanırız. Bu, kullanıcı girişi, uçtan uca kayıt için istek tanımlayıcı, kaynak IP adresi ve yetkilendirme verileri gibi yardımcı verilerin mesajla birlikte iletilmesi ihtiyacını doğurdu. Bu verilerin iletilmesini uygulamak için bir kütüphane geliştirdik ViennaNET.CallContext, hizmete giren bir istekten gelen verileri saklamanıza olanak tanır. Bu durumda isteğin kuyruk yoluyla mı yoksa Http aracılığıyla mı yapıldığı önemli değildir. Daha sonra giden istek veya mesajı göndermeden önce veriler bağlamdan alınır ve başlıklara yerleştirilir. Böylece bir sonraki servis yardımcı verileri alır ve aynı şekilde yönetir.

İlginiz için teşekkür ederiz, yorumlarınızı ve çekme isteklerinizi bekliyoruz!

Kaynak: habr.com

Yorum ekle