Řešení potíží se službou Azure Service Bus
Tento článek se zabývá technikami šetření selhání, souběžností, běžnými chybami typů přihlašovacích údajů v klientské knihovně Azure Service Bus v Javě a kroky pro zmírnění těchto chyb.
Povolení a konfigurace protokolování
Sada Azure SDK pro Javu nabízí konzistentní scénář protokolování, který pomáhá řešit chyby aplikací a urychlit jejich řešení. Protokoly vytvořené zachytí tok aplikace před dosažením stavu terminálu, aby pomohly najít kořenový problém. Pokyny k protokolování najdete v tématu Konfigurace protokolování v sadě Azure SDK pro Javu a přehled řešení potíží.
Kromě povolení protokolování nastavujte úroveň VERBOSE
protokolu nebo DEBUG
poskytuje přehled o stavu knihovny. Následující části ukazují ukázkové konfigurace log4j2 a logback, které snižují nadměrné množství zpráv, když je povolené podrobné protokolování.
Konfigurace Log4J 2
Ke konfiguraci Log4J 2 použijte následující kroky:
- Do pom.xml přidejte závislosti z ukázky protokolování pom.xml v části Závislosti vyžadované pro Log4j2.
- Přidejte log4j2.xml do složky src/main/resources .
Konfigurace zpětného protokolování
Ke konfiguraci zpětného přihlašování použijte následující postup:
- Přidejte do pom.xml závislosti pomocí závislostí z ukázky protokolování pom.xml v části Závislosti vyžadované pro zpětný protokol.
- Přidejte logback.xml do složky src/main/resources .
Povolení protokolování přenosu AMQP
Pokud povolení protokolování klienta nestačí k diagnostice vašich problémů, můžete povolit protokolování do souboru v podkladové knihovně AMQP Qpid Proton-J. Qpid Proton-J používá java.util.logging
. Protokolování můžete povolit vytvořením konfiguračního souboru s obsahem zobrazeným v další části. Nebo nastavte proton.trace.level=ALL
a podle toho, jaké možnosti konfigurace chcete pro implementaci java.util.logging.Handler
použít. Třídy implementace a jejich možnosti naleznete v tématu Package java.util.logging v dokumentaci k sadě Java 8 SDK.
Pokud chcete trasovat přenosové rámce AMQP, nastavte proměnnou PN_TRACE_FRM=1
prostředí.
Ukázkový soubor logging.properties
Následující konfigurační soubor protokoluje výstup na úrovni TRACE z Proton-J do souboru proton-trace.log:
handlers=java.util.logging.FileHandler
.level=OFF
proton.trace.level=ALL
java.util.logging.FileHandler.level=ALL
java.util.logging.FileHandler.pattern=proton-trace.log
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=[%1$tF %1$tr] %3$s %4$s: %5$s %n
Omezení protokolování
Jedním ze způsobů, jak snížit protokolování, je změnit úroveň podrobností. Dalším způsobem je přidat filtry, které vyloučí protokoly z balíčků názvů protokolovacího nástroje jako com.azure.messaging.servicebus
nebo com.azure.core.amqp
. Příklady najdete v souborech XML v částech Konfigurace protokolu 4J 2 a Konfigurace zpětného protokolu .
Při odeslání chyby jsou zprávy protokolu z tříd v následujících balíčcích zajímavé:
com.azure.core.amqp.implementation
com.azure.core.amqp.implementation.handler
- Výjimkou je, že zprávu můžete ignorovat
onDelivery
vReceiveLinkHandler
souboru .
- Výjimkou je, že zprávu můžete ignorovat
com.azure.messaging.servicebus.implementation
Souběžnost v ServiceBusProcessorClient
ServiceBusProcessorClient
umožňuje aplikaci nakonfigurovat, kolik volání obslužné rutiny zpráv by mělo probíhat souběžně. Tato konfigurace umožňuje paralelně zpracovávat více zpráv. ServiceBusProcessorClient
Pro využívání zpráv z entity mimo relaci může aplikace nakonfigurovat požadovanou souběžnost pomocí maxConcurrentCalls
rozhraní API. U entity s povolenou relací je maxConcurrentSessions
požadovaná souběžnost časy maxConcurrentCalls
.
Pokud aplikace sleduje méně souběžných volání obslužné rutiny zprávy než nakonfigurovaná souběžnost, může to být proto, že fond vláken nemá správnou velikost.
ServiceBusProcessorClient
používá vlákna démona z globálního vázaného fondu vláken Reactor k vyvolání obslužné rutiny zprávy. Maximální počet souběžných vláken v tomto fondu je omezen limitem. Ve výchozím nastavení je toto omezení desetkrát větší než počet dostupných jader procesoru. ServiceBusProcessorClient
Abyste mohli efektivně podporovat požadovanou souběžnost aplikace (maxConcurrentCalls
nebo maxConcurrentSessions
časymaxConcurrentCalls
), musíte mít boundedElastic
hodnotu limitu fondu, která je vyšší než požadovaná souběžnost. Výchozí limit můžete přepsat nastavením systémové vlastnosti reactor.schedulers.defaultBoundedElasticSize
.
Fond vláken a přidělení procesoru byste měli vyladit podle jednotlivých případů. Pokud však přepíšete limit fondu jako výchozí bod, omezte souběžná vlákna na přibližně 20 až 30 na jádro procesoru. Doporučujeme použít limit požadované souběžnosti na ServiceBusProcessorClient
instanci na přibližně 20–30. Profilujte a změřte konkrétní případ použití a odpovídajícím způsobem vylaďte aspekty souběžnosti. V případě scénářů s vysokým zatížením zvažte spuštění více ServiceBusProcessorClient
instancí, ve kterých je každá instance sestavena z nové ServiceBusClientBuilder
instance. Zvažte také spuštění každého ServiceBusProcessorClient
na vyhrazeném hostiteli , jako je kontejner nebo virtuální počítač, aby výpadek v jednom hostiteli neměl vliv na celkové zpracování zpráv.
Mějte na paměti, že nastavení vysoké hodnoty pro limit fondu na hostiteli s několika jádry procesoru by mohlo mít nepříznivý vliv. Mezi příznaky nízkých prostředků procesoru nebo fondu s příliš mnoha vlákny na menším počtu procesorů patří: časté vypršení časového limitu, ztráta zámku, zablokování nebo nižší propustnost. Pokud používáte aplikaci Java v kontejneru, doporučujeme použít dvě nebo více jader vCPU. Při spouštění aplikace Java v kontejnerizovaných prostředích nedoporučujeme vybírat nic menšího než 1 jádro vCPU. Podrobná doporučení týkající se obnovení najdete v tématu Kontejnerizace aplikací v Javě.
Kritické body sdílení připojení
Všichni klienti vytvořená ze sdílené ServiceBusClientBuilder
instance sdílejí stejné připojení k oboru názvů služby Service Bus.
Použití sdíleného připojení umožňuje operace multiplexingu mezi klienty na jednom připojení, ale sdílení se může stát kritickým bodem také v případě, že existuje mnoho klientů nebo klienti společně generují vysoké zatížení. Každé připojení má přidružené vstupně-výstupní vlákno. Při sdílení připojení klienti umístí svou práci do pracovní fronty tohoto sdíleného vstupně-výstupního vlákna a průběh každého klienta závisí na včasném dokončení jeho práce ve frontě. Vstupně-výstupní vlákno zpracovává zařazuje zařaděnou práci sériově. To znamená, že pokud pracovní fronta vstupně-výstupních vláken sdíleného připojení skončí s velkým množstvím čekajících prací na řešení, pak jsou příznaky podobné těm, které mají nízký procesor. Tato podmínka je popsaná v předchozí části o souběžnosti – například klienti stáhnou, vypršení časového limitu, ztracené uzamčení nebo zpomalení v cestě obnovení.
Sada Service Bus SDK používá reactor-executor-*
vzor pojmenování pro vstupně-výstupní vlákno připojení. Když aplikace zaznamená kritický bod sdíleného připojení, může se to projevit v využití procesoru ve vlákně vstupně-výstupních operací. Také v výpisu haldy nebo v živé paměti je objekt ReactorDispatcher$workQueue
pracovní frontou vstupně-výstupního vlákna. Dlouhá pracovní fronta v snímku paměti během období kritického bodu může znamenat, že sdílené vstupně-výstupní vlákno je přetížené čekajícími operacemi.
Proto pokud je zatížení aplikace do koncového bodu služby Service Bus přiměřeně vysoké z hlediska celkového počtu odeslaných zpráv nebo velikosti datové části, měli byste pro každého klienta, kterého sestavíte, použít samostatnou instanci tvůrce. Například pro každou entitu – frontu nebo téma – můžete vytvořit nový ServiceBusClientBuilder
a vytvořit z ní klienta. V případě extrémně vysokého zatížení pro konkrétní entitu můžete chtít vytvořit pro danou entitu více instancí klienta nebo spustit klienty v několika hostitelích , například kontejnery nebo virtuální počítače, aby bylo možné vyrovnávat zatížení.
Klienti se zastaví při používání vlastního koncového bodu služby Application Gateway.
Adresa vlastního koncového bodu odkazuje na adresu koncového bodu HTTPS poskytovanou aplikací, která se dá přeložit na Service Bus nebo nakonfigurovanou tak, aby směrovala provoz do služby Service Bus. Aplikace Azure lication Gateway usnadňuje vytvoření front-endu HTTPS, který přesměruje provoz do služby Service Bus. Sadu Service Bus SDK pro aplikaci můžete nakonfigurovat tak, aby jako vlastní koncový bod pro připojení ke službě Service Bus používala front-endovou IP adresu služby Application Gateway.
Application Gateway nabízí několik zásad zabezpečení podporujících různé verze protokolu TLS. Existují předdefinované zásady, které vynucují TLSv1.2 jako minimální verzi, existují také staré zásady s TLSv1.0 jako minimální verzí. Front-end HTTPS bude mít použitou zásadu TLS.
V současné chvíli sada SDK služby Service Bus nerozpozná určité vzdálené ukončení protokolu TCP front-endem služby Application Gateway, která jako minimální verzi používá TLSv1.0. Pokud například front-end odešle TCP FIN, pakety ACK zavřou připojení při aktualizaci jeho vlastností, sada SDK ho nedokáže rozpoznat, takže se znovu nepřipojí a klienti už nebudou moct odesílat ani přijímat zprávy. K takovému zastavení dochází pouze při použití TLSv1.0 jako minimální verze. Pokud chcete zmírnit omezení, použijte zásadu zabezpečení s TLSv1.2 nebo vyšší jako minimální verzi front-endu služby Application Gateway.
Podpora TLSv1.0 a 1.1 ve všech službách Azure již oznámila ukončení do 31. října 2024, takže přechod na TLSv1.2 se důrazně doporučuje.
Zpráva nebo zámek relace se ztratí.
Fronta nebo odběr tématu služby Service Bus má nastavenou dobu uzamčení na úrovni prostředku. Když příjemce klient natáhne zprávu z prostředku, zprostředkuje službě Service Bus počáteční zámek zprávy. Počáteční zámek trvá po dobu trvání zámku nastavenou na úrovni prostředku. Pokud se zámek zprávy ještě před vypršením platnosti neprodlouží, zprostředkovatel Service Bus zprávu uvolní, aby ji zpřístupnily ostatním příjemcům. Pokud se aplikace pokusí dokončit nebo opustit zprávu po vypršení platnosti zámku, volání rozhraní API selže s chybou com.azure.messaging.servicebus.ServiceBusException: The lock supplied is invalid. Either the lock expired, or the message has already been removed from the queue
.
Klient služby Service Bus podporuje spuštění úlohy obnovení zámku na pozadí, která obnovuje zámek zprávy nepřetržitě pokaždé, než vyprší jeho platnost. Ve výchozím nastavení se úloha prodlužování zámku spustí po dobu 5 minut. Dobu trvání prodloužení platnosti zámku můžete upravit pomocí .ServiceBusReceiverClientBuilder.maxAutoLockRenewDuration(Duration)
Pokud předáte Duration.ZERO
hodnotu, úloha prodlužování zámku je zakázaná.
Následující seznamy popisují některé vzory použití nebo hostitelské prostředí, které můžou vést ke ztrátě zámku:
Úloha prodloužení zámku je zakázaná a doba zpracování zpráv aplikace překračuje dobu trvání zámku nastavenou na úrovni prostředku.
Doba zpracování zpráv aplikace překračuje nakonfigurovanou dobu trvání úlohy obnovení zámku. Mějte na paměti, že pokud není doba trvání prodloužení zámku explicitně nastavená, výchozí hodnota je 5 minut.
Aplikace zapnula funkci Prefetch nastavením hodnoty prefetch na kladné celé číslo pomocí
ServiceBusReceiverClientBuilder.prefetchCount(prefetch)
. Pokud je povolená funkce Prefetch, klient načte počet zpráv, které se rovnají předběžnému načtení z entity služby Service Bus – fronta nebo téma – a uloží je do vyrovnávací paměti před načtením. Zprávy zůstanou ve vyrovnávací paměti předběžného načtení, dokud nebudou přijaty do aplikace. Klient nepředstavuje zámek zpráv, když jsou v předfetovací vyrovnávací paměti. Pokud zpracování aplikace trvá tak dlouho, že vyprší platnost uzamčení zpráv při zachování vyrovnávací paměti předběžného načtení, může aplikace získat zprávy se zámkem, jehož platnost vypršela. Další informace najdete v tématu Proč není výchozí možnost Předběžné načtení?Hostitelské prostředí má občasné problémy se sítí – například přechodné selhání sítě nebo výpadek – které brání prodloužení úlohy uzamčení v obnovení zámku včas.
Hostitelské prostředí nemá dostatek procesorů nebo má nedostatek cyklů procesoru, které přerušovaně zpožďují úlohu obnovení zámku z časového běhu.
Čas hostitelského systému není přesný – například hodiny se zkosí – zpozdí úlohu obnovení zámku a nechá ji běžet včas.
Vstupně-výstupní vlákno připojení je přetížené a má vliv na její schopnost spouštět zamykání obnovování síťových volání včas. Tento problém může způsobovat následující dva scénáře:
- Aplikace spouští příliš mnoho příjemců, kteří sdílejí stejné připojení. Další informace najdete v části Kritické body sdílení připojení.
- Aplikace nakonfigurovala
ServiceBusReceiverClient.receiveMessages
nebo měla velkémaxMessages
hodnoty nebomaxConcurrentCalls
ServiceBusProcessorClient
hodnoty. Další informace najdete v části Concurrency v ServiceBusProcessorClient .
Počet úloh obnovení zámku v klientovi se rovná maxMessages
hodnotám nebo maxConcurrentCalls
parametrům nastaveným pro ServiceBusProcessorClient
nebo ServiceBusReceiverClient.receiveMessages
. Velký počet úloh obnovení zámku, které provádí více síťových volání, může mít také nepříznivý vliv na omezování oboru názvů služby Service Bus.
Pokud hostitel není dostatečně prostředků, zámek může být stále ztracen, i když je spuštěných pouze několik úloh obnovení zámku. Pokud používáte aplikaci Java v kontejneru, doporučujeme použít dvě nebo více jader vCPU. Při spouštění aplikací Java v kontejnerizovaných prostředích nedoporučujeme vybírat nic menšího než 1 jádro vCPU. Podrobná doporučení týkající se obnovení najdete v tématu Kontejnerizace aplikací v Javě.
Stejné poznámky týkající se zámků jsou relevantní také pro frontu služby Service Bus nebo odběr tématu, které má povolenou relaci. Když se klient příjemce připojí k relaci v prostředku, zprostředkuje počáteční zámek relace. Aby bylo možné zachovat zámek v relaci, musí úloha obnovení zámku v klientovi zachovat zámek relace před vypršením jeho platnosti. U prostředku s povolenou relací se podkladové oddíly někdy přesunou, aby se dosáhlo vyrovnávání zatížení mezi uzly Service Bus , například když se přidají nové uzly pro sdílení zatížení. V takovém případě může dojít ke ztrátě zámků relace. Pokud se aplikace pokusí dokončit nebo opustit zprávu po ztrátě zámku relace, volání rozhraní API selže s chybou com.azure.messaging.servicebus.ServiceBusException: The session lock was lost. Request a new session receiver
.
Upgrade na verzi 7.15.x nebo nejnovější
Pokud narazíte na nějaké problémy, měli byste se nejprve pokusit je vyřešit upgradem na nejnovější verzi sady Service Bus SDK. Verze 7.15.x je zásadním návrhem, který řeší dlouhotrvající problémy týkající se výkonu a spolehlivosti.
Verze 7.15.x a novější snižuje přeskakování vláken, odebere zámky, optimalizuje kód v horkých cestách a snižuje přidělení paměti. Výsledkem těchto změn je až 45 až 50krát vyšší propustnost .ServiceBusProcessorClient
Verze 7.15.x a novější přináší také různá vylepšení spolehlivosti. Řeší několik podmínek časování (například předběžné načtení a výpočty kreditů) a vylepšené zpracování chyb. Tyto změny vedou k lepší spolehlivosti v přítomnosti přechodných problémů v různých typech klientů.
Používání nejnovějších klientů
Nová základní architektura s těmito vylepšeními – ve verzi 7.15.x a novější – se nazývá V2-Stack. Tento řádek verze zahrnuje jak předchozí generaci základního zásobníku, zásobník, který používá verze 7.14.x, tak novou sadu V2-Stack.
Ve výchozím nastavení některé typy klientů používají sadu V2-Stack, zatímco jiné vyžadují výslovný souhlas se službou V2-Stack. Výslovný souhlas nebo odhlášení z konkrétního zásobníku (V2 nebo předchozí generace) pro typ klienta můžete dosáhnout zadáním com.azure.core.util.Configuration
hodnot při sestavování klienta.
Příjem relací založených na zásobníku V2 například vyžaduje ServiceBusSessionReceiverClient
výslovný souhlas, jak je znázorněno v následujícím příkladu:
ServiceBusSessionReceiverClient sessionReceiver = new ServiceBusClientBuilder()
.connectionString(Config.CONNECTION_STRING)
.configuration(new com.azure.core.util.ConfigurationBuilder()
.putProperty("com.azure.messaging.servicebus.session.syncReceive.v2", "true") // 'false' by default, opt-in for V2-Stack.
.build())
.sessionReceiver()
.queueName(Config.QUEUE_NAME)
.buildClient();
Následující tabulka uvádí typy klientů a odpovídající názvy konfigurace a uvádí, jestli je klient ve výchozím nastavení povolený, aby používal sadu V2-Stack v nejnovější verzi 7.17.0. U klienta, který není ve výchozím nastavení ve V2-Stacku, můžete k vyjádření souhlasu použít právě zobrazený příklad.
Typ klienta | Název konfigurace | Je ve výchozím nastavení ve službě V2-Stack? |
---|---|---|
Odesílatel a klient pro správu | com.azure.messaging.servicebus.sendAndManageRules.v2 |
ano |
Klient bez relace procesoru a příjemce reaktoru | com.azure.messaging.servicebus.nonSession.asyncReceive.v2 |
ano |
Klient příjemce procesoru relace | com.azure.messaging.servicebus.session.processor.asyncReceive.v2 |
ano |
Klient přijímače relačních reaktorů | com.azure.messaging.servicebus.session.reactor.asyncReceive.v2 |
ano |
Synchronní klient příjemce, který není relace | com.azure.messaging.servicebus.nonSession.syncReceive.v2 |
ne |
Klient synchronního příjemce relace | com.azure.messaging.servicebus.session.syncReceive.v2 |
ne |
Jako alternativu k používání com.azure.core.util.Configuration
můžete vyjádřit výslovný souhlas nebo vyjádřit výslovný nesouhlas nastavením stejných názvů konfigurací pomocí proměnných prostředí nebo systémových vlastností.
Další kroky
Pokud pokyny k řešení potíží v tomto článku nepomáhají vyřešit problémy při použití sady Azure SDK pro klientské knihovny Java, doporučujeme vám založit problém v úložišti Azure SDK pro Javu na GitHubu.