A Service Bus kézbesítetlen levelek üzenetsorainak áttekintése

Az Azure Service Bus üzenetsorok és témakör-előfizetések egy másodlagos al-sort biztosítanak, amelyet úgynevezett halott betűsor (DLQ) -ként ismernek. A kézbesítetlen levelek üzenetsorát nem kell explicit módon létrehozni, és nem lehet törölni vagy felügyelni a fő entitástól függetlenül.

Ez a cikk a Service Bus halottlevél-üzenetsorait ismerteti. A vita nagy részét a Holt betűs üzenetsorok mintája szemlélteti a GitHubon.

A kézbesítetlen levelek üzenetsora

A kézbesítetlen levelek üzenetsorának célja, hogy olyan üzeneteket tároljon, amelyeket nem lehet kézbesíteni egyetlen fogadónak sem, vagy olyan üzeneteket, amelyeket nem sikerült feldolgozni. Az üzenetek ezután eltávolíthatók a DLQ-ból, és megvizsgálhatók. Előfordulhat, hogy egy alkalmazás lehetővé teszi, hogy a felhasználó kijavítsa a problémákat, és küldje el újra az üzenetet.

API- és protokoll szempontjából a DLQ többnyire hasonló minden más üzenetsorhoz, azzal a kivétellel, hogy az üzeneteket csak a szülő entitás holtbetűs műveletével lehet elküldeni. Emellett az élettartam nem kerül figyelembevételre, és a DLQ-ba nem lehet üzenetet áthelyezni. A kézbesítetlen levelek üzenetsora teljes mértékben támogatja a normál műveleteket, például a peek-lock kézbesítést, a fogadást és a törlést, valamint a tranzakciós műveleteket.

A DLQ-n nincs automatikus tisztítás. Az üzenetek a DLQ-ban maradnak mindaddig, amíg kifejezetten le nem kéri őket a DLQ-ból, és be nem fejezi a holtlevél-üzenetet.

A kézbesítetlen levelek üzenetsorának elérési útja

Minden üzenetsorhoz és minden előfizetéshez tartozik egy saját, kézbesíthetetlen üzeneteket tartalmazó alsor. Közvetlenül a következő szintaxissal (Azure CLI, REST és eszközök, például Service Bus Explorer) kezelheti:

<queue path>/$deadletterqueue
<topic path>/Subscriptions/<subscription path>/$deadletterqueue

Ha a Azure.Messaging.ServiceBus .NET könyvtárat használja, nem saját maga hozza létre ezt az útvonalat. Ehelyett állítsa a(z) ServiceBusReceiverOptions.SubQueue értékét SubQueue.DeadLetter értékre a fogadó létrehozásakor. Például lásd: Üzenetek fogadása kézbesíthetetlen üzenetek várólistájából.

Az átviteli kézbesítetlen levelek üzenetsorának elérési útja

Ha egy üzenet automatikus továbbítási vagy send-via forgatókönyvekben nem továbbítható a célhelyére, akkor az üzenet a továbbítást végző forrás entitás átviteli holtbetűs üzenetsorába (TDLQ) kerül, nem a cél entitásba. Minden olyan üzenetsor vagy előfizetés, amely üzeneteket továbbít, saját átviteli kézbesíthetetlen üzenetek alvárakozási sorával rendelkezik, amelyet közvetlenül a következő szintaxis használatával címezhet:

<queue path>/$Transfer/$DeadLetterQueue
<topic path>/Subscriptions/<subscription path>/$Transfer/$DeadLetterQueue

Amikor a(z) Azure.Messaging.ServiceBus .NET könyvtárat használja, állítsa a(z) ServiceBusReceiverOptions.SubQueue értékét SubQueue.TransferDeadLetter-ra. Például lásd: Üzenetek fogadása az átviteli kézbesítetlen üzenetek üzenetsorából.

DLQ-üzenetek száma

A levél nélküli üzenetsor üzeneteinek számának a témakör szintjén történő lekérése nem alkalmazható, mert az üzenetek nem a témakör szintjén ülnek. Ehelyett, amikor egy feladó üzenetet küld egy témakörnek, az üzenet a témakör előfizetéseihez lesz továbbítva ezredmásodpercen belül, így már nem a témakör szintjén található. Így a témakör előfizetéséhez társított DLQ-ban láthatja az üzeneteket. Az alábbi példában Service Bus Explorer azt mutatja, hogy az előfizetés DLQ-jában jelenleg 62 üzenet található: teszt1.

62 üzenet a teszt1-előfizetés kézbesítetlen levelek üzenetsorában.

A DLQ-üzenetek számát a Azure CLI paranccsal az servicebus topic subscription showis lekérheti.

Üzenetek áthelyezése a DLQ-ba

A Service Busban számos olyan tevékenység van, amely miatt az üzenetek az üzenetkezelő motoron belülről kerülnek leküldésre a DLQ-ba. Az alkalmazások explicit módon is áthelyezhetik az üzeneteket a DLQ-ba. A következő két tulajdonság (a holtbetű oka és a holtbetű leírása) lesz hozzáadva a holtbetűs üzenetekhez. Az alkalmazások saját kódokat határozhatnak meg a holtbetűs ok tulajdonsághoz, de a rendszer a következő értékeket állítja be.

Holtbetű oka Holt betűs hiba leírása
HeaderSizeExceeded A stream méretkvótája túllépte a korlátot.
TTLExpiredException Az üzenet lejárt, és a kézbesíthetetlen üzenetek közé került. A részletekért tekintse meg a Time to Live szakaszt.
Session ID is null A munkamenet engedélyezett entitása nem engedélyezi az olyan üzeneteket, amelyek munkamenet-azonosítója null értékű.
MaxTransferHopCountExceeded Az üzenetsorok közötti továbbításkor engedélyezett ugrások maximális száma túllépte a korlátot. Ez az érték 4 értékre van állítva.
MaxDeliveryCountExceeded Az üzenet nem feldolgozható a maximális kézbesítési kísérletek után. A részletekért tekintse meg a Kézbesítések maximális száma szakaszt.

Élettartam

Ha engedélyezi a kézbesítetlen levelek használatát az üzenetsorokon vagy előfizetéseken, a rendszer az összes lejáró üzenetet a DLQ-ba helyezi át. A holt betű okkódja a következőre TTLExpiredExceptionvan állítva: . A késleltetett üzenetek nem törlődnek, és nem kerülnek át a kézbesítetlen levelek üzenetsorába a lejáratuk után. Ez szándékosan van.

Szállítási mennyiség maximális száma

A Service Bus-üzenetsorok és -előfizetések esetében korlátozva van az üzenetek kézbesítésére tett kísérletek száma. Az alapértelmezett érték 10. Ha egy üzenet betekintő zárolás alatt érkezik, de vagy explicit módon el lett hagyva, vagy a zárolás lejárt, a rendszer növeli az üzenet kézbesítési számát. Ha a kézbesítések száma meghaladja a korlátot, a rendszer áthelyezi az üzenetet a DLQ-ba. A DLQ-ban az üzenet holtbetűs oka a következőre MaxDeliveryCountExceededvan állítva: . Ez a viselkedés nem tiltható le, de a maximális kézbesítési számot nagy számra állíthatja be.

Rendezd le az üzeneteket, mielőtt bezárnád a vevőt vagy a kapcsolatot

Peek-lock módban a befogadott üzenet zárolása a vevőhöz és annak csatlakozásához van kötve. Ha bezárja a fogadót vagy annak kapcsolatát, mielőtt rendezné az üzenetet (befejezés, elvetés, elhalasztás vagy holtbetűssé tétel), a rendezési művelet nem jut el a szolgáltatáshoz, ezért az üzenet zárolva marad, amíg le nem jár a zárolás. Ezután a szolgáltatás újra kézbesíti az üzenetet, ami növeli a kézbesítési számot. Az a többször kézbesített, de soha nem véglegesített üzenet végül a holtbetyűs üzenetsorba kerül a(z) MaxDeliveryCountExceeded indokkal.

Ennek a mintának a elkerülése érdekében:

  • Rendezz minden üzenetet, mielőtt bezárod a fogadót vagy a ServiceBusClient.
  • Ne tartsd meg a fogadott üzenetet későbbi feldolgozásra, mert addigra a fogadó fél vagy a kapcsolat már lezárulhat. A szolgáltatás 10 perc után lezárja az inaktív kapcsolatot, ami a zárolást is feloldja.
  • Ha a véglegesítés azért hiúsul meg, mert a zárolás elveszett, fogadja újra az üzenetet, és dolgozza fel ahelyett, hogy megpróbálná újra elvégezni a véglegesítést az eredeti üzeneten.

Az alábbi példa befejezi az egyes üzenetek feldolgozását, mielőtt a await using blokk lezárja a fogadót:

await using (ServiceBusReceiver receiver = client.CreateReceiver(queueName))
{
    ServiceBusReceivedMessage message = await receiver.ReceiveMessageAsync();

    // Process the message, then settle it while the receiver is still open.
    await receiver.CompleteMessageAsync(message);
}

Ha a fogadó bezárása után próbál meg rendezni egy üzenetet, az kivételt eredményez, és az üzenet nem kerül rendezésre.

Important

Az elveszett zár nem mindig a kódod miatt alakul ki. Átmeneti hálózati hiba, hálózati kimaradások vagy a szolgáltatás által előírt 10 perces üres időkivonás is leszakíthatja a kapcsolatot, mielőtt egy üzenetet rendeznél. Ilyen esetekben lásd a hibaelhárítási útmutatóban a következőt: Az üzenet- vagy munkamenetzárolás a zárolat lejárati ideje előtt megszűnik.

Az előfizetési szabályok feldolgozása során felmerülő hibák

Ha engedélyezi a holtbetűsítést a szűrőértékelési kivételek esetében, az előfizetés SQL-szűrőszabályának végrehajtása során előforduló hibák a DLQ-ban lesznek rögzítve a jogsértő üzenettel együtt. Ne használja ezt a beállítást olyan éles környezetben, ahol olyan üzenettípusok vannak, amelyeket a rendszer a témakörbe küld, és amelyek nem rendelkeznek előfizetőkkel, mivel az nagy mennyiségű DLQ-üzenetet eredményezhet. Ezért győződjön meg arról, hogy a témakörnek küldött összes üzenet rendelkezik legalább egy egyező előfizetéssel.

Alkalmazásszintű holtbetűsítés

A rendszer által biztosított levélfelirat-kezelő funkciók mellett az alkalmazások a DLQ használatával explicit módon elutasíthatják az elfogadhatatlan üzeneteket. Az elfogadhatatlan üzenetek tartalmazhatnak olyan üzeneteket, amelyek valamilyen rendszerhiba, helytelenül formázott hasznos adatokat tartalmazó üzenetek vagy üzenetszintű biztonsági séma használata esetén sikertelen hitelesítést tartalmazó üzenetek miatt nem dolgozhatók fel megfelelően.

A .NET hívja meg a ServiceBusReceiver.DeadLetterMessageAsync metódust.

Javasoljuk, hogy adja meg a kivétel típusát a DeadLetterReason-ban és a kivétel veremkivonatát a DeadLetterDescription-ben, mivel így könnyebb elhárítani annak okát, amely miatt az üzenetek halott levélbe kerültek. Előfordulhat, hogy egyes üzenetek túllépik a standard szintű Azure Service Bus 256 KB-os kvótakorlátját. A Service Bus-névteret a standard szintről a prémium szintre frissítheti, hogy magasabb kvóták és korlátok rendelkezzenek.

Üzenetek fogadása kézbesíthetetlen üzeneteket tartalmazó üzenetsorból

Ha a Azure.Messaging.ServiceBus használatával kézbesíthetetlen üzenetet szeretne fogadni a .NET-kódtárral, állítsa a(z) ServiceBusReceiverOptions.SubQueue értékét SubQueue.DeadLetter értékre, amikor létrehozza a fogadót. A kódtár elvégzi Ön helyett a kézbesítetlen üzenetek alvárólistájának címzését.

using Azure.Identity;
using Azure.Messaging.ServiceBus;

string fullyQualifiedNamespace = "<NAMESPACE-NAME>.servicebus.windows.net";
string queueName = "<QUEUE-NAME>";

// 1. Create the top-level client. Passwordless authentication is recommended.
await using var client = new ServiceBusClient(fullyQualifiedNamespace, new DefaultAzureCredential());

// 2. Configure options to target the dead-letter sub-queue.
var options = new ServiceBusReceiverOptions
{
    SubQueue = SubQueue.DeadLetter
};

// 3. Create a receiver scoped to the dead-letter queue. For a subscription's
//    dead-letter queue, use: client.CreateReceiver(topicName, subscriptionName, options).
ServiceBusReceiver dlqReceiver = client.CreateReceiver(queueName, options);

// 4. Receive a dead-lettered message.
ServiceBusReceivedMessage dlqMessage = await dlqReceiver.ReceiveMessageAsync();

// 5. Inspect why the message was dead-lettered.
string reason = dlqMessage.DeadLetterReason;
string description = dlqMessage.DeadLetterErrorDescription;

// 6. Complete the message to remove it from the dead-letter queue.
await dlqReceiver.CompleteMessageAsync(dlqMessage);

Ugyanez a minta az átviteli kézbesítetlen üzenetek üzenetsorához is használható a(z) SubQueue.TransferDeadLetter használatával. A teljes példáért lásd: Üzenetek fogadása az átviteli kézbesítetlen levelek üzenetsorából.

Holt betűzés automatikus továbbítási forgatókönyvekben

Az üzenetek a következő feltételek mellett lesznek elküldve a kézbesítetlen levelek üzenetsorába:

  • Egy üzenet négynél több üzenetsoron vagy egymáshoz láncolt témakörön halad át.
  • A célsor vagy témakör le van tiltva vagy törölve.
  • A cél üzenetsor vagy témakör meghaladja a maximális entitásméretet.

Holtbetűs küldés forgatókönyveken keresztül

  • Ha a célüzenetsor vagy téma le van tiltva, az üzenet a forrásüzenetsor átviteli kézbesítetlenüzenet-sorába (TDLQ) kerül.
  • Ha a célsor vagy entitás meghaladja az entitás méretét, a rendszer elküldi az üzenetet a forrássor TDLQ-jának.

A forrásentitás TransferDeadLetterMessageCount futásidejű tulajdonságának kiolvasásával ellenőrizheti, hogy hány üzenet várakozik az átviteli holtbetűs üzenetsorban. További információ: Üzenetszám részletei.

Üzenetek fogadása az átviteli kézbesítetlen üzenetek üzenetsorából

Az átviteli hibalevélüzenetsor a forrásentitás egyik alüzenetsora, ezért ugyanúgy fogadhat belőle, mint egy normál hibalevélüzenetsorból: állítsa a fogadó hatókörét a forrásüzenetsorra (vagy a forrás témakör-előfizetésre), és válassza ki az átviteli hibalevél-alüzenetsort.

Ha a Azure.Messaging.ServiceBus .NET-kódtárat használja, állítsa a(z) ServiceBusReceiverOptions.SubQueue értékét SubQueue.TransferDeadLetter értékre a vevő létrehozásakor. A könyvtár Ön helyett kezeli az átvitel kézbesíthetetlen üzeneteinek alvárólistáját.

using Azure.Identity;
using Azure.Messaging.ServiceBus;

string fullyQualifiedNamespace = "<NAMESPACE-NAME>.servicebus.windows.net";

// The source queue that forwards messages. The transfer dead-letter queue
// lives on this entity, not on the destination.
string sourceQueueName = "<SOURCE-QUEUE-NAME>";

// 1. Create the top-level client. Passwordless authentication is recommended.
await using var client = new ServiceBusClient(fullyQualifiedNamespace, new DefaultAzureCredential());

// 2. Configure options to target the transfer dead-letter sub-queue.
var options = new ServiceBusReceiverOptions
{
    SubQueue = SubQueue.TransferDeadLetter
};

// 3. Create a receiver scoped to the source entity's transfer dead-letter queue.
//    For a subscription that forwards, use:
//    client.CreateReceiver(topicName, subscriptionName, options).
ServiceBusReceiver tdlqReceiver = client.CreateReceiver(sourceQueueName, options);

// 4. Receive a message that failed to transfer to its destination.
ServiceBusReceivedMessage tdlqMessage = await tdlqReceiver.ReceiveMessageAsync();

// 5. Inspect why the message couldn't be transferred.
string reason = tdlqMessage.DeadLetterReason;
string description = tdlqMessage.DeadLetterErrorDescription;

// 6. Complete the message to remove it from the transfer dead-letter queue.
await tdlqReceiver.CompleteMessageAsync(tdlqMessage);

Miért került az üzenetem a halott levél sorba?

Ha váratlan üzeneteket találsz a halott betű sorban, használd az egyes üzeneteken található halott betű indokát és leírását az okok azonosítására. A kézbesíthetetlenség oka a DeadLetterReason tulajdonságban van beállítva, a rendszer által megadott okok pedig a Üzenetek áthelyezése a DLQ-ba című részben vannak felsorolva. Az alábbi táblázat a leggyakoribb okokat térképezi fel arra, hogyan azonosítod és előzed meg őket.

A probléma oka Hogyan lehet azonosítani Hogyan lehet ezt megelőzni
A kézbesítések száma túllépte a megengedett értéket Az ok: MaxDeliveryCountExceeded. Győződj meg róla, hogy a kezelő minden üzenetet rendez, és vizsgáld meg a feldolgozási kivételeket, valamint azokat az üzeneteket, amelyeket megérkeznek, de soha nem fejeznek be. Lásd : Maximális szállítási szám.
Egyezség a vevő lezárása után Ennek oka, MaxDeliveryCountExceededhogy a naplóid lock-lost vagy receiver-closed hibákat mutatnak, amikor befejezed az üzeneteket. Minden üzenetet nyugtázzon, mielőtt bezárja a fogadót vagy a kapcsolatot. Lásd: az üzenetek véglegesítését, mielőtt bezárná a vevőt vagy a kapcsolatot.
Az üzenet lejárt Az ok: TTLExpiredException. Növeld az élet idejét, vagy dolgozd fel gyorsabban az üzeneteket. Lásd: Idő az életre.
Az üzenet túl nagy Az ok: HeaderSizeExceeded. Csökkentsd az üzenet méretét, vagy frissíts a Premium szintre a magasabb limitekért.
Hiányzó munkamenet-azonosító Az ok: Session ID is null. Állítsd be a munkamenet-azonosítót minden olyan üzenetben, amelyet egy munkamenet-kompatibilis entitásnak küldesz.
Túl sok automatikus előreugrás Az ok: MaxTransferHopCountExceeded. Csökkentse az automatikus továbbítási lánc hosszát legfeljebb négy ugrásra. Lásd: Dead-lettering az automatikus előrehaladási helyzetekben.
Előfizetési szűrőhiba A szűrőértékelési kivételeknél a holtbetűs írás engedélyezett, és egy szűrőszabály hibát dobott. Javítsd ki a szűrőszabályt, és győződj meg róla, hogy a témához küldött üzeneteknek megfelelő előfizetése van. Lásd : Hiba előfizetési szabályok feldolgozása közben.

Az olyan tünetekkel kapcsolatban, amelyekhez nem rendelhető kézbesítetlen üzenet ok, például időszakos zárolásvesztés esetén, lásd a Service Bus hibaelhárítási útmutatót.

Halott levélként kezelt üzenetek újrafeldolgozásra küldése

Miután megoldotta azt a problémát, amely miatt egy üzenet elhalt betűsre váltott, újból elküldheti azt az újra feldolgozandó üzenetsorba vagy témakörbe. A legegyszerűbb módszer az Service Bus Explorer használata a Azure portálon, amellyel üzeneteket lehet betekinteni a kézbesítetlen levelek üzenetsorába, szükség esetén szerkeszteni a tartalmukat vagy tulajdonságaikat, és egyenként vagy kötegekben újraküldni őket. Az operátorok gyakran azért részesítik előnyben ezt a felhasználói felületet, mert felfedi, hogy mely üzenettípusok sikertelenek, mely forrásentitások és miért, miközben továbbra is engedélyezi a kötegek újraküldését.

Az üzenetsorok vagy előfizetések holtbetűsítésének engedélyezése című cikkből megtudhatja, hogyan konfigurálhatók a holtbetűk az üzenet lejárati beállításakor.