ViennaNET: پس منظر لاءِ لائبريرين جو هڪ سيٽ. حصو 2

Raiffeisenbank .NET ڊولپر ڪميونٽي ViennaNET جي مواد جو مختصر جائزو وٺڻ جاري رکي ٿي. ان بابت اسان ڪيئن ۽ ڇو آيا آهيون، توهان پهريون حصو پڙهي سگهو ٿا.

هن آرٽيڪل ۾، اسان ورهايل ٽرانزيڪشن، قطار ۽ ڊيٽابيس سان ڪم ڪرڻ لاء اڃا تائين غور ڪيو ويو لائبريرين ذريعي وڃون ٿا، جيڪي اسان جي GitHub مخزن ۾ ڳولهي سگهجن ٿا (ذريعن هتي آهن)، ۽ Nuget پيڪيجز هتي.

ViennaNET: پس منظر لاءِ لائبريرين جو هڪ سيٽ. حصو 2

ViennaNET.Sagas

جڏهن هڪ پروجيڪٽ DDD ۽ microservice architecture ڏانهن سوئچ ڪري ٿو، پوءِ جڏهن ڪاروباري منطق مختلف خدمتن ۾ ورهائجي ٿي، هڪ مسئلو پيدا ٿئي ٿو ورهايل ٽرانزيڪشن ميڪانيزم کي لاڳو ڪرڻ جي ضرورت سان، ڇاڪاڻ ته ڪيتريون ئي منظرنامو اڪثر هڪ ئي وقت ڪيترن ئي ڊومينز کي متاثر ڪن ٿا. توهان وڌيڪ تفصيل سان اهڙي ميڪانيزم سان واقف ٿي سگهو ٿا، مثال طور، ڪتاب ۾ "Microservices Patterns"، ڪرس رچرڊسن.

اسان جي منصوبن ۾، اسان هڪ سادي پر مفيد ميکانيزم تي عمل ڪيو آهي: هڪ ساگا، يا بلڪه هڪ آرڪيسٽريشن تي ٻڌل ساگا. ان جو خلاصو هن ريت آهي: اتي هڪ خاص ڪاروباري منظرنامو آهي جنهن ۾ مختلف خدمتن ۾ ترتيب وار آپريشن ڪرڻ ضروري آهي، ۽ جيڪڏهن ڪنهن به قدم تي ڪو مسئلو پيدا ٿئي، ته اهو ضروري آهي ته سڀني پوئين قدمن لاءِ رولبڪ جي طريقيڪار کي سڏڻ، جتي اهو آهي. مهيا ڪيل. اهڙيء طرح، ساگا جي آخر ۾، ڪاميابي کان سواء، اسان سڀني ڊومينز ۾ مسلسل ڊيٽا حاصل ڪندا آهيون.

اسان جو عمل اڃا تائين ان جي بنيادي شڪل ۾ ٺاهيو ويو آهي ۽ ٻين خدمتن سان رابطي جي ڪنهن به طريقن جي استعمال سان ڳنڍيل ناهي. اهو استعمال ڪرڻ ڏکيو ناهي: صرف بنيادي خلاصو ڪلاس SagaBase<T> جو اولاد ٺاهيو، جتي T توهان جو حوالو ڪلاس آهي جنهن ۾ توهان ساگا جي ڪم ڪرڻ لاءِ ضروري ابتدائي ڊيٽا محفوظ ڪري سگهو ٿا، انهي سان گڏ ڪجهه وچولي نتيجا. حوالن جو مثال عمل جي دوران سڀني مرحلن ذريعي گذريو ويندو. ساگا پاڻ هڪ بي رياست طبقو آهي، تنهن ڪري مثال DI ۾ رکي سگهجي ٿو هڪ سنگلٽن جي طور تي ضروري انحصار حاصل ڪرڻ لاءِ.

مثال اشتهار:

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، جيڪو صرف مخزن ٺاهڻ لاءِ هڪ طريقو بيان ڪري ٿو.

سڌو سنئون ڊيٽابيس تائين رسائي حاصل ڪرڻ لاء، مهيا ڪندڙ ميڪانيزم استعمال ڪيو ويندو آهي. هر DBMS جيڪو اسان پنهنجي ٽيمن ۾ استعمال ڪريون ٿا ان جو پنهنجو عمل آهي: ViennaNET.Orm.MSSQL, ViennaNET.Orm.Oracle, ViennaNET.Orm.SQLite, ViennaNET.Orm.PostgreSql.

ساڳئي وقت، ڪيترن ئي مهيا ڪندڙن کي هڪ ئي وقت ۾ هڪ ايپليڪيشن ۾ رجسٽر ٿي سگهي ٿو، جيڪا اجازت ڏئي ٿي، مثال طور، هڪ خدمت جي فريم ورڪ جي اندر، انفراسٹرڪچر کي تبديل ڪرڻ جي ڪنهن به قيمت کان سواء، هڪ قدم قدم لڏپلاڻ ڪرڻ لاء. هڪ DBMS ٻئي ڏانهن. گهربل ڪنيڪشن چونڊڻ لاءِ ميکانيزم ۽، تنهن ڪري، مهيا ڪندڙ هڪ مخصوص اداري جي طبقي لاءِ (جنهن لاءِ ميپنگ کي ڊيٽابيس جي جدولن تي لکيو ويو آهي) تي عمل ڪيو ويندو آهي اداري کي رجسٽر ڪرڻ جي ذريعي 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 فائلن ذريعي ۽ ڪلاس ذريعي. يونٽ ٽيسٽ ۾ اسٽب ريپوزٽريز جي آسان لکڻ لاءِ، اتي هڪ لائبريري آهي ViennaNET.TestUtils.Orm.

ViennaNET.Orm.* استعمال ڪرڻ جا مڪمل مثال ڳولي سگهجن ٿا هتي.

ViennaNET.Messing.*

قطارن سان ڪم ڪرڻ لاءِ لائبريرين جو هڪ سيٽ.

قطارن سان ڪم ڪرڻ لاءِ، ساڳيو طريقو چونڊيو ويو جيئن مختلف DBMSs سان، يعني، لائبريري سان ڪم ڪرڻ جي لحاظ کان وڌ ۾ وڌ ممڪن متحد طريقو، قطع نظر ته قطار مئنيجر استعمال ڪيو ويو هجي. لائبريري 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 جي ڪجهه نموني کي لاڳو ڪري ٿو: اسان هڪ پيغام موڪليندا آهيون ۽ هڪ خاص عارضي قطار مان جواب جو انتظار ڪندا آهيون، جيڪا صرف هڪ جوابي پيغام لاءِ ٺاهي وئي آهي.

هتي بنيادي ڪنيڪشن nuances سان قطار استعمال ڪرڻ جو هڪ مثال.

ViennaNET.CallContext

اسان قطار استعمال ڪندا آهيون نه رڳو مختلف سسٽم جي وچ ۾ انضمام لاء، پر ساڳئي ايپليڪيشن جي مائڪرو سروسز جي وچ ۾ رابطي لاء، مثال طور، ساگا جي اندر. انهي جي نتيجي ۾ پيغام سان گڏ منتقل ڪرڻ جي ضرورت آهي جيئن ته مددگار ڊيٽا صارف لاگ ان، پڇاڙيء کان آخر تائين لاگنگ لاء سڃاڻپ ڪندڙ جي درخواست، ماخذ IP پتو ۽ اختياري ڊيٽا. ھن ڊيٽا جي فارورڊنگ کي لاڳو ڪرڻ لاء، اسان ھڪڙي لائبريري ٺاھيو آھي ViennaNET.CallContext، جيڪو توهان کي خدمت ۾ داخل ٿيڻ واري درخواست کان ڊيٽا محفوظ ڪرڻ جي اجازت ڏئي ٿو. انهي حالت ۾، درخواست جو طريقو ٺاهيو ويو، قطار ذريعي يا Http ذريعي، ڪو به فرق ناهي. ان کان پوء، ٻاهر نڪرڻ واري درخواست يا پيغام موڪلڻ کان اڳ، ڊيٽا کي حوالن مان ورتو وڃي ٿو ۽ هيڊر ۾ رکيل آهي. اهڙيء طرح، ايندڙ خدمت معاون ڊيٽا حاصل ڪري ٿي ۽ ان کي ساڳئي طريقي سان منظم ڪري ٿي.

توهان جي توجه جي مهرباني، اسان توهان جي تبصرن ۽ ڇڪڻ جي درخواستن جو منتظر آهيون!

جو ذريعو: www.habr.com

تبصرو شامل ڪريو