వియన్నానెట్: బ్యాకెండ్ కోసం లైబ్రరీల సమితి. పార్ట్ 2

Raiffeisenbank .NET డెవలపర్ కమ్యూనిటీ ViennaNET యొక్క కంటెంట్‌లను క్లుప్తంగా సమీక్షించడం కొనసాగిస్తోంది. మేము దీనికి ఎలా మరియు ఎందుకు వచ్చాము అనే దాని గురించి, మీరు మొదటి భాగాన్ని చదవగలరు.

ఈ కథనంలో, పంపిణీ చేయబడిన లావాదేవీలు, క్యూలు మరియు డేటాబేస్‌లతో పని చేయడానికి మేము ఇంకా పరిగణించబడని లైబ్రరీల ద్వారా వెళ్తాము, వీటిని మా GitHub రిపోజిటరీలో చూడవచ్చు (మూలాలు ఇక్కడ ఉన్నాయి), మరియు Nuget ప్యాకేజీలు ఇక్కడ ఉన్నాయి.

వియన్నానెట్: బ్యాకెండ్ కోసం లైబ్రరీల సమితి. పార్ట్ 2

వియన్నాNET.సాగస్

ప్రాజెక్ట్ DDD మరియు మైక్రోసర్వీస్ ఆర్కిటెక్చర్‌కి మారినప్పుడు, వ్యాపార తర్కం వివిధ సేవలలో పంపిణీ చేయబడినప్పుడు, పంపిణీ చేయబడిన లావాదేవీ మెకానిజంను అమలు చేయవలసిన అవసరానికి సంబంధించిన సమస్య తలెత్తుతుంది, ఎందుకంటే అనేక దృశ్యాలు తరచుగా అనేక డొమైన్‌లను ఒకేసారి ప్రభావితం చేస్తాయి. మీరు అటువంటి యంత్రాంగాలను మరింత వివరంగా తెలుసుకోవచ్చు, ఉదాహరణకు, "మైక్రోసర్వీసెస్ ప్యాటర్న్స్" పుస్తకంలో, క్రిస్ రిచర్డ్సన్.

మా ప్రాజెక్ట్‌లలో, మేము సరళమైన కానీ ఉపయోగకరమైన మెకానిజమ్‌ను అమలు చేసాము: ఒక సాగా లేదా బదులుగా ఆర్కెస్ట్రేషన్ ఆధారిత సాగా. దీని సారాంశం క్రింది విధంగా ఉంది: వివిధ సేవల్లో వరుసగా కార్యకలాపాలు నిర్వహించాల్సిన ఒక నిర్దిష్ట వ్యాపార దృశ్యం ఉంది మరియు ఏ దశలోనైనా సమస్యలు తలెత్తితే, మునుపటి అన్ని దశల కోసం రోల్‌బ్యాక్ విధానాన్ని కాల్ చేయడం అవసరం. అందించబడింది. ఈ విధంగా, సాగా ముగింపులో, విజయంతో సంబంధం లేకుండా, మేము అన్ని డొమైన్‌లలో స్థిరమైన డేటాను స్వీకరిస్తాము.

మా అమలు ఇప్పటికీ దాని ప్రాథమిక రూపంలో చేయబడుతుంది మరియు ఇతర సేవలతో పరస్పర చర్య చేసే ఏ పద్ధతులను ఉపయోగించడంతో ముడిపడి లేదు. దీన్ని ఉపయోగించడం కష్టం కాదు: బేస్ అబ్‌స్ట్రాక్ట్ క్లాస్ 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-ఫస్ట్ విధానాన్ని ఉపయోగిస్తాము, కాబట్టి రెడీమేడ్ డేటాబేస్‌లో డేటాతో పని చేయడానికి మాత్రమే కార్యాచరణ ఉంటుంది.

ViennaNET.Orm.Seedwork и ViennaNET.Orm - వరుసగా ప్రాథమిక ఇంటర్‌ఫేస్‌లు మరియు వాటి అమలులను కలిగి ఉన్న ప్రధాన సమావేశాలు. వాటి విషయాలను మరింత వివరంగా పరిశీలిద్దాం.

ఇంటర్ఫేస్ IEntityFactoryService మరియు దాని అమలు EntityFactoryService యూనిట్ ఆఫ్ వర్క్, నిర్దిష్ట ఎంటిటీలతో పని చేయడానికి రిపోజిటరీలు, అలాగే కమాండ్‌ల ఎగ్జిక్యూటర్‌లు మరియు డైరెక్ట్ SQL క్వెరీలు ఇక్కడ సృష్టించబడినందున, డేటాబేస్‌తో పనిచేయడానికి ప్రధాన ప్రారంభ స్థానం. కొన్నిసార్లు డేటాబేస్తో పని చేయడానికి తరగతి సామర్థ్యాలను పరిమితం చేయడం సౌకర్యంగా ఉంటుంది, ఉదాహరణకు, డేటాను మాత్రమే చదివే సామర్థ్యాన్ని అందించడం. అటువంటి సందర్భాలలో IEntityFactoryService ఒక పూర్వీకుడు - ఇంటర్ఫేస్ ఉంది IEntityRepositoryFactory, ఇది రిపోజిటరీలను సృష్టించే పద్ధతిని మాత్రమే ప్రకటిస్తుంది.

డేటాబేస్ను నేరుగా యాక్సెస్ చేయడానికి, ప్రొవైడర్ మెకానిజం ఉపయోగించబడుతుంది. మేము మా బృందాలలో ఉపయోగించే ప్రతి DBMS దాని స్వంత అమలును కలిగి ఉంటుంది: ViennaNET.Orm.MSSQL, ViennaNET.Orm.Oracle, ViennaNET.Orm.SQLite, ViennaNET.Orm.PostgreSql.

అదే సమయంలో, అనేక ప్రొవైడర్లు ఒకే సమయంలో ఒక అప్లికేషన్‌లో నమోదు చేసుకోవచ్చు, ఉదాహరణకు, ఒక సేవ యొక్క ఫ్రేమ్‌వర్క్‌లో, మౌలిక సదుపాయాలను సవరించడానికి ఎటువంటి ఖర్చులు లేకుండా, నుండి దశల వారీ వలసలను నిర్వహించడానికి ఇది అనుమతిస్తుంది. ఒక DBMS మరొకదానికి. అవసరమైన కనెక్షన్‌ని ఎంచుకోవడానికి మెకానిజం మరియు అందువల్ల, నిర్దిష్ట ఎంటిటీ క్లాస్ (డేటాబేస్ టేబుల్‌లకు మ్యాపింగ్ వ్రాయబడింది) కోసం ప్రొవైడర్ ఎంటిటీని బౌండెడ్ కాంటెక్స్ట్ క్లాస్‌లో నమోదు చేయడం ద్వారా అమలు చేయబడుతుంది (డొమైన్ ఎంటిటీలను నమోదు చేసే పద్ధతిని కలిగి ఉంటుంది) లేదా దాని వారసుడు ApplicationContext (అప్లికేషన్ ఎంటిటీలు , డైరెక్ట్ రిక్వెస్ట్‌లు మరియు ఆదేశాలను నమోదు చేసే పద్ధతులను కలిగి ఉంటుంది), ఇక్కడ కాన్ఫిగరేషన్ నుండి కనెక్షన్ ఐడెంటిఫైయర్ వాదనగా అంగీకరించబడుతుంది:

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

ఉదాహరణ అప్లికేషన్ సందర్భం:

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

కనెక్షన్ ID పేర్కొనబడకపోతే, "డిఫాల్ట్" అనే కనెక్షన్ ఉపయోగించబడుతుంది.

డేటాబేస్ పట్టికలకు ఎంటిటీల ప్రత్యక్ష మ్యాపింగ్ ప్రామాణిక NHibernate సాధనాలను ఉపయోగించి అమలు చేయబడుతుంది. మీరు xml ఫైల్‌ల ద్వారా మరియు తరగతుల ద్వారా వివరణను ఉపయోగించవచ్చు. యూనిట్ పరీక్షలలో స్టబ్ రిపోజిటరీలను సౌకర్యవంతంగా రాయడానికి, లైబ్రరీ ఉంది ViennaNET.TestUtils.Orm.

ViennaNET.Orm.* ఉపయోగించి పూర్తి ఉదాహరణలు కనుగొనవచ్చు ఇక్కడ.

ViennaNET.మెసేజింగ్.*

క్యూలతో పని చేయడానికి లైబ్రరీల సమితి.

క్యూలతో పని చేయడానికి, వివిధ DBMSల మాదిరిగానే అదే విధానం ఎంపిక చేయబడింది, అవి లైబ్రరీతో పని చేసే పరంగా గరిష్టంగా సాధ్యమయ్యే ఏకీకృత విధానం, ఉపయోగించిన క్యూ మేనేజర్‌తో సంబంధం లేకుండా. గ్రంధాలయం 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

ఒక వ్యాఖ్యను జోడించండి