Versengő felhasználók mintája

Azure Functions
Azure Service Bus

Lehetővé teheti több párhuzamos felhasználó számára, hogy feldolgozzák az ugyanazon az üzenetkezelési csatornán fogadott üzeneteket. Több egyidejű felhasználóval a rendszer egyszerre több üzenetet is feldolgozhat az átviteli sebesség optimalizálása, a méretezhetőség és a rendelkezésre állás javítása, valamint a számítási feladatok egyensúlyának javítása érdekében.

Kontextus és probléma

Egy felhőben futó alkalmazásnak várhatóan sok kérelmet kell majd kezelnie. Az egyes kérelmek szinkron módon történő feldolgozása helyett az általános módszer az, hogy az alkalmazás egy üzenetkezelési rendszeren keresztül egy másik szolgáltatásba (feldolgozói szolgáltatásba) küldi őket, ahol a feldolgozásuk aszinkron módon történik. Ez a stratégia segít biztosítani, hogy az alkalmazás üzleti logikája ne legyen blokkolva, miközben a kérések feldolgozása folyamatban van.

Kérelmek száma idővel nagymértékben változhat, és ennek számos oka lehet. A felhasználói aktivitás hirtelen növekedése vagy az egyszerre több bérlőtől érkező összesített kérelmek kiszámíthatatlan mennyiségű számítási feladatot eredményezhetnek. Csúcsidőben előfordulhat, hogy a rendszernek másodpercenként több száz kérést kell feldolgoznia, míg máskor a szám nagyon kicsi lehet. Ezenkívül a kérelmek kezelése terén végzett munka jellege is igen változó lehet. A fogyasztói szolgáltatás egyetlen példányának használatával azt okozhatja, hogy a példányt elárasztják a kérések. Vagy az üzenetkezelő rendszert túlterhelheti az alkalmazásból érkező üzenetek beáramlása. A változó mennyiségű számítási feladatok kezelése érdekében a rendszer a feldolgozói szolgáltatás több példányát is képes futtatni. Ezeket a feldolgozókat azonban össze kell hangolni annak érdekében, hogy egy üzenetet csak egyetlen feldolgozóhoz kézbesítsen a rendszer. A számítási feladatok jelentette terhelést is el kell osztani a feldolgozók között, nehogy egy példány szűk keresztmetszetté váljon.

Megoldás

Az üzenetsor segítségével megteremtheti a kommunikációs csatornát az alkalmazás és a feldolgozói szolgáltatás példányai között. Az alkalmazás üzenetek formájában tesz közzé kérelmeket az üzenetsorban, a feldolgozói szolgáltatáspéldányok pedig fogadják és feldolgozzák ezeket az üzeneteket. Ez a megközelítés lehetővé teszi, hogy ugyanaz a feldolgozói szolgáltatáspéldány-készlet képes legyen kezelni az alkalmazás bármely példányától érkező üzeneteket. Az ábra bemutatja, hogyan lehet az üzenetsor használatával elosztani a munkát a szolgáltatás példányai között.

A munka szétosztása egy szolgáltatás példányai között üzenetsor használatával

Feljegyzés

Bár ezeknek az üzeneteknek több felhasználója is van, ez nem ugyanaz, mint a Feliratkozás közzététele minta (pub/sub). A Versengő fogyasztók megközelítéssel minden üzenetet egyetlen fogyasztónak ad át feldolgozás céljából, míg a Pub/Sub megközelítéssel minden fogyasztó minden üzenetet átad.

Ez a megoldás a következő előnyökkel jár:

  • Kiegyenlített terhelésű rendszert biztosít, amely jelentősen eltérő mennyiségben is képes kezelni az alkalmazáspéldányok által küldött kérelmeket. Az üzenetsor pufferként viselkedik az alkalmazáspéldányok és a feldolgozói szolgáltatás példányai között. Ez a puffer segít minimalizálni a rendelkezésre állásra és a válaszképességre gyakorolt hatást mind az alkalmazás, mind a szolgáltatáspéldányok esetében. További információ: Üzenetsor-alapú terhelésegyensúlyozási minta. A hosszabb ideig tartó feldolgozást igénylő üzenetek nem akadályozzák a feldolgozói szolgáltatás más példányait a többi üzenet párhuzamos kezelésében.

  • Ez növeli a megbízhatóságot. Ha az előállító ennek a mintának a használata helyett közvetlenül kommunikál a feldolgozóval, de nem monitorozza azt, akkor nagy valószínűséggel el fognak veszni üzenetek, vagy a feldolgozásuk sikertelen lesz, ha a feldolgozó meghibásodik. Ebben a mintában a rendszer nem egy adott szolgáltatáspéldányra küldi az üzeneteket. A sikertelen szolgáltatáspéldány nem blokkolja az előállítót, az üzenetek feldolgozását pedig bármely működő szolgáltatáspéldány elvégezheti.

  • Nincs szükség összetett koordinációra a feldolgozók, illetve az előállítói és a feldolgozói példányok között. Az üzenetsor biztosítja, hogy a rendszer minden üzenetet legalább egyszer elküldjön.

  • Skálázható. Automatikus skálázás alkalmazásakor a rendszer dinamikusan növelheti vagy csökkentheti a fogyasztói szolgáltatás példányainak számát, miközben az üzenetek mennyisége ingadozik.

  • Fokozható a rugalmasság, ha az üzenetsor tranzakciós olvasási műveleteket biztosít. Ha a feldolgozói szolgáltatáspéldány egy tranzakciós művelet részeként olvassa be és dolgozza fel az üzenetet, és a feldolgozói szolgáltatáspéldány meghibásodik, ez a minta gondoskodik arról, hogy az üzenet visszajusson az üzenetsorba, ahol a feldolgozói szolgáltatás egy másik példánya kezelheti. Az üzenetek folyamatos sikertelenségének kockázatának csökkentése érdekében javasoljuk, hogy használjon kézbesítetlen üzenetsorokat.

Problémák és megfontolandó szempontok

A minta megvalósítása során az alábbi pontokat vegye figyelembe:

  • Üzenetrendezés. A sorrend, amelyben a fogyasztói szolgáltatáspéldány az üzeneteket fogadja, nem garantált, és nem feltétlenül tükrözi az üzenetek létrehozásának sorrendjét. Érdemes úgy megtervezni rendszert, hogy biztosítsa az üzenetek idempotens feldolgozását, mert ez segít kiküszöbölni minden olyan függőséget, amely az üzenetek kezelési sorrendjéhez kapcsolódik. További információ: Idempotency Patterns on Jonathon Oliver's blog.

    A Microsoft Azure Service Bus-üzenetsorok üzenet-munkamenetek alkalmazásával képesek garantálni az üzenetek elsőnek-be, elsőnek-ki típusú kezelését. További információkért lásd: Üzenetkezelési minták munkamenetek használatával.

  • Rugalmasságot biztosító szolgáltatások tervezése. Ha a rendszert úgy tervezték, hogy észlelje és újraindítsa a sikertelen szolgáltatáspéldányokat, szükség lehet a szolgáltatáspéldányok által végrehajtott feldolgozás idempotens műveletekként történő alkalmazására, hogy egy adott üzenet többszöri lekéréséből és feldolgozásából eredő hatások minimalizálhatók legyenek.

  • Az ártalmas üzenetek észlelése. Ha egy helytelenül formázott üzenet vagy feladat olyan erőforrásokhoz igényel hozzáférést, amelyek nem érhetők el, az a szolgáltatáspéldány sikertelen működéséhez vezethet. A rendszernek meg kell akadályoznia, hogy ezek az üzenetek visszajussanak az üzenetsorba. Ehelyett valahol máshol kell tárolnia ezeknek az üzeneteknek az adatait, hogy szükség esetén elemezni lehessen azokat.

  • Eredmények kezelése. Az üzenetet kezelő szolgáltatáspéldányt a rendszer teljes mértékben leválasztja az üzenetet létrehozó alkalmazáslogikáról, így ezek valószínűleg nem tudnak közvetlenül kommunikálni egymással. Ha a szolgáltatáspéldány olyan eredményeket hoz létre, amelyeket vissza kell küldeni az alkalmazáslogikának, ezeket az információkat mindkét fél számára elérhető helyen kell tárolni. Annak érdekében, hogy az alkalmazáslogika ne hívhasson le hiányos adatokat, a rendszernek jeleznie kell, ha az adatok feldolgozása befejeződött.

    Az Azure használata esetén egy feldolgozófolyamat vissza tudja küldeni az eredményeket az alkalmazáslogikának egy dedikált válaszadási üzenetsor használatával. Az alkalmazáslogikának össze kell kötnie ezeket az eredményeket az eredeti üzenettel. Ennek a forgatókönyvnek a részletes leírása az aszinkron üzenetkezelés ismertetését tartalmazó témakörben található.

  • Az üzenetkezelő rendszer skálázása. Egy nagyméretű megoldás esetében egyetlen üzenetsort túlterhelhetnek az üzenetek, és így szűk keresztmetszetként jelenhet meg a rendszerben. Ebben a helyzetben érdemes megfontolni az üzenetkezelési rendszer particionálását, hogy az adott előállítók a meghatározott üzenetsorra küldjék az üzeneteket. Használhat terheléselosztást is, hogy több üzenetsor között oszthassa szét az üzeneteket.

  • Az üzenetkezelési rendszer megbízhatóságának biztosítása. Egy megbízható üzenetkezelési rendszerre van szükség annak érdekében, hogy az alkalmazás által sorba helyezett üzenet biztosan ne vesszen el. Ez a rendszer elengedhetetlen annak biztosításához, hogy az összes üzenet legalább egyszer legyen kézbesítve.

Mikor érdemes ezt a mintát használni?

Használja ezt a mintát, ha:

  • Az alkalmazás számítási feladatai aszinkron módon futtatható feladatokra vannak osztva.
  • A feladatok egymástól függetlenek, és párhuzamosan futtathatók.
  • A munka mennyisége nagymértékben változó, ami skálázható megoldást kíván.
  • A megoldásnak magas rendelkezésre állást kell biztosítania, továbbá rugalmasan kell kezelnie egy feladat feldolgozásának meghiúsulását.

Nem érdemes ezt a mintát használni, ha:

  • Az alkalmazás számítási feladatait nem könnyű különálló feladatokká szétválasztani, vagy a feladatok között nagyfokú függőség áll fenn.
  • A feladatokat szinkron módon kell végrehajtani, és az alkalmazáslogikának meg kell várnia a feladat befejeződését a továbblépés előtt.
  • A feladatok meghatározott sorrendben kell végrehajtani.

Néhány üzenetküldő rendszer olyan munkameneteket támogat, amelyek lehetővé teszik az előállító számára az üzenetek csoportosítását, illetve annak biztosítását, hogy mindet ugyanaz a feldolgozó kezelje. Ez a mechanizmus rangsorolt üzenetek esetében alkalmazható (ha azok támogatottak) egy olyan üzenetrendezés megvalósításához, amely sorrendben továbbítja az üzeneteket az előállítótól egyetlen fogyasztónak.

Számítási feladatok tervezése

Az építészeknek értékelniük kell, hogy a konkurens fogyasztók mintája hogyan használható a számítási feladat kialakításában az Azure Well-Architected Framework pilléreiben foglalt célok és alapelvek kezelésére. Példa:

Pillér Hogyan támogatja ez a minta a pillércélokat?
A megbízhatósági tervezési döntések segítenek a számítási feladatnak ellenállóvá válni a hibás működéssel szemben, és biztosítani, hogy a hiba bekövetkezése után teljesen működőképes állapotba kerüljön. Ez a minta redundanciát épít ki az üzenetsor-feldolgozásban úgy, hogy replikaként kezeli a fogyasztókat, így a példányhiba nem akadályozza meg, hogy más felhasználók feldolgozhassák az üzenetsor-üzeneteket.

- RE:05 Redundancia
- RE:07 Háttérfeladatok
A költségoptimalizálás a számítási feladatok megtérülésének fenntartására és javítására összpontosít. Ez a minta segíthet a költségek optimalizálásában azáltal, hogy lehetővé teszi az üzenetsor mélységén alapuló skálázást nullára, ha az üzenetsor üres. Emellett optimalizálhatja a költségeket azáltal, hogy lehetővé teszi az egyidejű fogyasztói példányok maximális számának korlátozását.

- CO:05 Díjoptimalizálás
- CO:07 Összetevő költségei
A teljesítményhatékonyság a skálázás, az adatok és a kód optimalizálásával segíti a számítási feladatok hatékony kielégítését . A terhelés elosztása az összes fogyasztói csomóponton növeli a kihasználtságot és a dinamikus skálázást az üzenetsor mélysége alapján, minimalizálva a túlterheltségeket.

- PE:05 Skálázás és particionálás
- PE:07 Kód és infrastruktúra

Mint minden tervezési döntésnél, fontolja meg az ezzel a mintával bevezethető többi pillér céljaival szembeni kompromisszumokat.

Példa

Az Azure Service Bus-üzenetsorokat és Azure-függvénysor-eseményindítókat biztosít, amelyek kombinálva a felhőtervezési minta közvetlen megvalósítását jelentik. Az Azure Functions eseményindítókon és kötéseken keresztül integrálható az Azure Service Bus szolgáltatással. A Service Bus használatával olyan függvényeket hozhat létre, amelyek a közzétevők által küldött üzenetsor-üzeneteket használnak fel. A közzétételi alkalmazás(ok) üzeneteket tesznek közzé egy üzenetsorba, és az Azure Functions-ként implementált felhasználók lekérhetik az üzeneteket az üzenetsorból, és kezelhetik őket.

A rugalmasság érdekében a Service Bus-üzenetsor lehetővé teszi a fogyasztó számára, hogy módot használjon PeekLock , amikor üzenetet kér le az üzenetsorból; ez a mód valójában nem távolítja el az üzenetet, hanem egyszerűen elrejti azt más felhasználók elől. Az Azure Functions-futtatókörnyezet PeekLock módban kap egy üzenetet, ha a függvény sikeresen befejeződött, meghívja a Complete (Befejező) elemet az üzenetre, vagy ha a függvény meghiúsul, az üzenet ismét láthatóvá válik, így egy másik felhasználó kérheti le. Ha a függvény a PeekLock időkorlátnál hosszabb ideig fut, a zárolás automatikusan megújul, amíg a függvény fut.

Az Azure Functions a várólista mélysége alapján skálázható fel és skálázható fel, amelyek mind az üzenetsor konkurens felhasználóiként működnek. Ha a függvények több példánya is létrejön, az üzenetek egymástól függetlenül történő lekérésével és feldolgozásával versenyeznek.

Az Azure Service Bus-üzenetsorok használatával kapcsolatos részletes információkért lásd: Service Bus-üzenetsorok, témakörök és előfizetések.

Az Üzenetsor által aktivált Azure Functionsről további információt az Azure Functions Azure Service Bus-eseményindítóján talál.

Az alábbi kód bemutatja, hogyan hozhat létre új üzenetet, és hogyan küldheti el egy Service Bus-üzenetsorba egy ServiceBusClient példány használatával.

private string serviceBusConnectionString = ...;
...

  public async Task SendMessagesAsync(CancellationToken  ct)
  {
   try
   {
    var msgNumber = 0;

    var serviceBusClient = new ServiceBusClient(serviceBusConnectionString);

    // create the sender
    ServiceBusSender sender = serviceBusClient.CreateSender("myqueue");

    while (!ct.IsCancellationRequested)
    {
     // Create a new message to send to the queue
     string messageBody = $"Message {msgNumber}";
     var message = new ServiceBusMessage(messageBody);

     // Write the body of the message to the console
     this._logger.LogInformation($"Sending message: {messageBody}");

     // Send the message to the queue
     await sender.SendMessageAsync(message);

     this._logger.LogInformation("Message successfully sent.");
     msgNumber++;
    }
   }
   catch (Exception exception)
   {
    this._logger.LogException(exception.Message);
   }
  }

Az alábbi példakód egy C# Azure-függvényként írt fogyasztót mutat be, aki felolvassa az üzenet metaadatait, és naplóz egy Service Bus-üzenetsort. Figyelje meg, hogy az ServiceBusTrigger attribútum hogyan köti azt egy Service Bus-üzenetsorhoz.

[FunctionName("ProcessQueueMessage")]
public static void Run(
    [ServiceBusTrigger("myqueue", Connection = "ServiceBusConnectionString")]
    string myQueueItem,
    Int32 deliveryCount,
    DateTime enqueuedTimeUtc,
    string messageId,
    ILogger log)
{
    log.LogInformation($"C# ServiceBus queue trigger function consumed message: {myQueueItem}");
    log.LogInformation($"EnqueuedTimeUtc={enqueuedTimeUtc}");
    log.LogInformation($"DeliveryCount={deliveryCount}");
    log.LogInformation($"MessageId={messageId}");
}

Következő lépések

  • Az aszinkron üzenetkezelés ismertetése. Az üzenetsorok aszinkron típusú kommunikációs mechanizmusok. Ha a feldolgozói szolgáltatásnak választ kell küldenie egy alkalmazásnak, szükség lehet valamilyen válaszüzenet-küldés alkalmazására. Az aszinkron üzenetkezelés ismertetése információkat nyújt a kérelem/válasz típusú üzenetküldés üzenetsorok használatával történő megvalósításával kapcsolatban.

  • Útmutató az automatikus skálázáshoz. Egy feldolgozói szolgáltatás példányait el lehet indítani és le lehet állítani, mivel azon üzenetsorok hossza, amelyekre az alkalmazások üzeneteket küldenek, változó. Az automatikus skálázás segítségével az átviteli sebesség szinten tartható a feldolgozási csúcsidőszakban.

Az alábbi minták és útmutatók hasznosak lehetnek a minta megvalósításakor:

  • Számításierőforrás-konszolidálási minta. Egy feldolgozói szolgáltatás több példánya egyetlen folyamatba vonhatók össze a költségek és a felügyeleti terhek csökkentése érdekében. A számításierőforrás-konszolidálási minta ismerteti ennek a módszernek az előnyeit és a hátrányait.

  • Üzenetsor-alapú terheléskiegyenlítési minta. Az üzenetsor bevezetése rugalmassá teheti a rendszert, lehetővé téve, hogy a szolgáltatáspéldányok kezelni tudják alkalmazáspéldányoktól érkező, váltakozó mennyiségű kérelmeket. Az üzenetsor pufferként viselkedik, ami kiegyenlíti a terhelést. Az üzenetsor-alapú terheléskiegyenlítési minta részletesebben is ismerteti ezt a forgatókönyvet.