Aracılığıyla paylaş


Azure Service Bus sorunlarını giderme

Bu makale hata araştırma tekniklerini, eşzamanlılığı, Azure Service Bus Java istemci kitaplığındaki kimlik bilgisi türleri için yaygın hataları ve bu hataları düzeltmeye yönelik azaltma adımlarını kapsar.

Günlüğe kaydetmeyi etkinleştirme ve yapılandırma

Java için Azure SDK, uygulama hatalarını gidermeye ve bunların çözümünü hızlandırmaya yardımcı olmak için tutarlı bir günlük hikayesi sunar. Oluşturulan günlükler, kök sorunun bulunmasına yardımcı olmak için terminal durumuna ulaşmadan önce uygulamanın akışını yakalar. Günlüğe kaydetme hakkında yönergeler için bkz. Java için Azure SDK'da günlüğe kaydetmeyi yapılandırma ve Sorun gidermeye genel bakış.

Loglamayı etkinleştirmeye ek olarak, log seviyesini VERBOSE veya DEBUG olarak ayarlamak kütüphanenin durumu hakkında içgörüler sağlar. Ayrıntılı günlük etkinleştirildiğinde aşırı iletileri azaltmak amacıyla aşağıdaki bölümlerde örnek log4j2 ve logback yapılandırmaları gösterilmektedir.

Log4J 2'yi yapılandırma

Log4J 2'yi yapılandırmak için aşağıdaki adımları kullanın:

  1. "Log4j2 için gerekli bağımlılıklar bölümünde, günlük örneği pom.xml'ten olanları kullanarak pom.xml'ye bağımlılıkları ekleyin."
  2. src/main/resources klasörünüze log4j2.xml ekleyin.

Geri kaydetmeyi yapılandırma

Geri kaydetmeyi yapılandırmak için aşağıdaki adımları kullanın:

  1. günlük kaydı örneği pom.xmliçindeki "logback için gereken bağımlılıklar" bölümünü kullanarak pom.xml içindeki bağımlılıkları ekleyin.
  2. src/main/resources klasörünüze logback.xml ekleyin.

AMQP aktarım günlüğünü etkinleştir

İstemci günlüğünü etkinleştirmek sorunlarınızı tanılamak için yeterli değilse, bu durumda, temel alınan AMQP kitaplığındaki bir dosyada günlüğe kaydetmeyi etkinleştirebilirsiniz Qpid Proton-J. Qpid Proton-J java.util.loggingkullanır. Sonraki bölümde gösterilen içeriklerle bir yapılandırma dosyası oluşturarak günlüğü etkinleştirebilirsiniz. Veya proton.trace.level=ALL ve java.util.logging.Handler uygulaması için istediğiniz yapılandırma seçeneklerini ayarlayın. Uygulama sınıfları ve seçenekleri için Java 8 SDK belgelerindeki java.util.logging paketine bakın.

AMQP aktarım çerçevelerini izlemek için PN_TRACE_FRM=1 ortam değişkenini ayarlayın.

Örnek logging.properties dosyası

Aşağıdaki yapılandırma dosyası, Proton-J'dan proton-trace.logdosyasına TRACE seviyesindeki verileri günlüğe kaydeder.

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

Günlük kaydını azalt

Günlüğe kaydetmeyi azaltmanın bir yolu ayrıntı düzeyini değiştirmektir. Başka bir yol, günlükleri com.azure.messaging.servicebus veya com.azure.core.amqpgibi günlükçü adı paketlerinin dışında tutan filtreler eklemektir. Örnekler için Log4J 2 Yapılandırma ve Logback yapılandırma bölümlerindeki XML dosyalarına bakın.

Bir hata gönderdiğinizde, aşağıdaki paketlerdeki sınıflardan gelen günlük iletileri ilginçtir:

  • com.azure.core.amqp.implementation
  • com.azure.core.amqp.implementation.handler
    • İstisna, onDeliveryiçindeki ReceiveLinkHandler iletisini yoksayabilmenizdir.
  • com.azure.messaging.servicebus.implementation

ServiceBusProcessorClient'da Eşzamanlılık

ServiceBusProcessorClient, uygulamanın ileti işleyicisine kaç çağrının eşzamanlı olarak gerçekleşmesi gerektiğini yapılandırmasına olanak tanır. Bu yapılandırma, birden çok iletiyi paralel olarak işlemeyi mümkün kılar. ServiceBusProcessorClient oturum olmayan bir varlıktan ileti tüketen bir uygulama, maxConcurrentCalls API'sini kullanarak istenen eşzamanlılığı yapılandırabilir. Oturumu etkinleştirilmiş bir varlık için istenen eşzamanlılık, maxConcurrentSessions ile maxConcurrentCalls'in çarpımı kadardır.

Uygulama, ileti işleyicisine yapılandırılmış eşzamanlılıktan daha az eşzamanlı çağrı gözlemlerse, bunun nedeni iş parçacığı havuzunun uygun şekilde boyutlandırılmaması olabilir.

ServiceBusProcessorClient, mesaj işleyicisini çağırmak için Reactor'un global boundedElastic iş parçacığı havuzundan daemon iş parçacıklarını kullanır. Bu havuzdaki eş zamanlı iş parçacığı sayısı bazı üst limitlerce sınırlıdır. Varsayılan olarak, bu üst sınır kullanılabilir CPU çekirdeği sayısının on katıdır. ServiceBusProcessorClient uygulamanın istenen eşzamanlılığını (maxConcurrentCalls veya maxConcurrentSessions kez maxConcurrentCalls) etkili bir şekilde desteklemesi için, istenen eşzamanlılık değerinden daha yüksek bir boundedElastic havuz üst sınırı değerine sahip olmanız gerekir. sistem özelliğini reactor.schedulers.defaultBoundedElasticSizeayarlayarak varsayılan üst sınırı geçersiz kılabilirsiniz.

İş parçacığı havuzunu ve CPU tahsisini duruma göre ayarlamanız gerekir. Ancak, başlangıç noktası olarak havuz sınırını geçersiz kıldığınızda, eşzamanlı iş parçacıklarını CPU çekirdeği başına yaklaşık 20-30 ile sınırlayın. ServiceBusProcessorClient örneği başına istenen eşzamanlılığı yaklaşık 20-30 olarak ayarlamanızı öneririz. Belirli kullanım örneğinizin profilini alın ve ölçün ve eşzamanlılık yönlerini buna göre ayarlayın. Yüksek yük senaryoları için, her örneğin yeni bir ServiceBusProcessorClient örneğinden oluşturulduğu birden çok ServiceBusClientBuilder örneği çalıştırmayı göz önünde bulundurun. Ayrıca, her ServiceBusProcessorClient'ı bir kapsayıcı veya VM gibi ayrılmış bir ana bilgisayarda çalıştırarak, bir ana bilgisayardaki hizmet kesintisinin ileti işlemenin genelini etkilememesi için bunu da dikkate alın.

Az sayıda CPU çekirdeğine sahip bir sunucuda havuz sınırı için yüksek bir değer belirlemenin olumsuz etkileri olacağını unutmayın. Cpu kaynaklarının düşük olduğuna veya daha az CPU'da çok fazla iş parçacığına sahip bir havuza ilişkin bazı işaretler şunlardır: sık sık zaman aşımları, kilit kaybı, kilitlenme veya daha düşük aktarım hızı. Java uygulamasını bir kapsayıcıda çalıştırıyorsanız iki veya daha fazla vCPU çekirdeği kullanmanızı öneririz. Kapsayıcılı ortamlarda Java uygulaması çalıştırılırken 1 vCPU çekirdeğinden daha az bir değer seçmeniz önerilmez. Kaynak oluşturma hakkında ayrıntılı öneriler için bkz. Java uygulamalarınızı konteynerleştirin.

Bağlantı paylaşımı darboğazı

Paylaşılan bir ServiceBusClientBuilder örneğinden oluşturulan tüm istemciler Service Bus ad alanıyla aynı bağlantıyı paylaşır.

Paylaşılan bağlantı kullanmak, tek bir bağlantıdaki istemciler arasında çoğullama işlemlerine olanak tanır, ancak çok sayıda istemci varsa veya istemciler birlikte yüksek yük oluşturursa paylaşım da bir performans sorununa neden olabilir. Her bağlantının kendisiyle ilişkilendirilmiş bir G/Ç iş parçacığı vardır. Bağlantı paylaşırken, istemciler çalışmalarını bu paylaşılan G/Ç iş parçacığının iş kuyruğuna koyar ve her istemcinin ilerleme durumu, kuyruktaki çalışmasının zamanında tamamlanmasına bağlıdır. G/Ç iş parçacığı, sıralanan işi seri olarak işler. Eğer paylaşılan bir bağlantının I/O iş parçacığı iş kuyruğunda ilgilenilmesi gereken çok sayıda bekleyen iş varsa, belirtiler düşük CPU belirtilerine benzer. Bu durum, önceki eşzamanlılık hakkında bölümde açıklanmıştır - örneğin, istemciler beklemeye alındığında, zaman aşımına uğradığında, kilit kaybı yaşandığında veya kurtarma sürecinde yavaşlama meydana geldiğinde.

Service Bus SDK'sı, bağlantı G/Ç iş parçacığı için reactor-executor-* adlandırma desenini kullanır. Uygulama paylaşılan bağlantı darboğazını yaşadığında, bu durum G/Ç iş parçacığının CPU kullanımına yansıyabilir. Ayrıca, yığın dökümü veya canlı bellekteki nesne ReactorDispatcher$workQueue, G/Ç iş parçacığının iş sırasıdır. Performans sorunu döneminde bellek anlık görüntüsündeki uzun bir iş kuyruğu, paylaşılan G/Ç iş parçacığının bekleyen çalışmalarla aşırı yüklendiğini gösterebilir.

Bu nedenle, bir Service Bus uç noktasına uygulama yükü gönderilen iletilerin veya yük boyutunun genel sayısı açısından makul düzeyde yüksekse, oluşturduğunuz her istemci için ayrı bir oluşturucu örneği kullanmanız gerekir. Örneğin, her varlık (kuyruk veya konu) için yeni bir ServiceBusClientBuilder oluşturabilir ve ondan bir istemci oluşturabilirsiniz. Belirli bir varlığa son derece yüksek yük olması durumunda, yük dengeleme için bu varlık için birden çok istemci örneği oluşturmak veya istemcileri birden çok konakta (örneğin kapsayıcılar veya VM'ler) çalıştırmak isteyebilirsiniz.

Application Gateway özel uç noktası kullanılırken istemciler duruyor

Özel uç nokta adresi, Service Bus tarafından çözümlenebilen veya trafiği Service Bus'a yönlendirmek için yapılandırılmış, uygulama tarafından sağlanan https uç nokta adresini ifade eder. Azure Application Gateway, trafiği Service Bus'a ileden bir HTTPS ön ucu oluşturmayı kolaylaştırır. Bir uygulama için Service Bus SDK'sını, Service Bus'a bağlanmak üzere özel uç nokta olarak Application Gateway ön uç IP adresi kullanacak şekilde yapılandırabilirsiniz.

Application Gateway, farklı TLS protokol sürümlerini destekleyen çeşitli güvenlik ilkeleri sunar. TlSv1.2'yi en düşük sürüm olarak zorunlu kılmaya yönelik önceden tanımlanmış ilkeler vardır ve en düşük sürüm olarak TLSv1.0 olan eski ilkeler de vardır. HTTPS ön ucuna bir TLS ilkesi uygulanır.

Şu anda Service Bus SDK, en düşük sürüm olarak TLSv1.0 kullanan Application Gateway ön ucu tarafından gerçekleştirilen belirli uzak TCP sonlandırmalarını tanımlayamıyor. Örneğin ön uç, özellikleri güncelleştirildiğinde bağlantıyı kapatmak için TCP FIN, ACK paketleri gönderirse SDK bağlantıyı algılayamaz, bu nedenle yeniden bağlanmaz ve istemciler artık ileti gönderip alamaz. Böyle bir durdurma yalnızca en düşük sürüm olarak TLSv1.0 kullanıldığında gerçekleşir. Azaltmak için, Application Gateway ön ucu için en düşük sürüm olarak TLSv1.2 veya üzeri bir güvenlik ilkesi kullanın.

Tüm Azure Hizmetlerinde TLSv1.0 ve 1.1 desteği zaten 31 Ekim 2024'e kadar sona erecek şekilde duyuruldu, bu nedenle TLSv1.2'ye geçiş kesinlikle önerilir.

İleti veya oturum kilidi kayboldu

Service Bus kuyruğu veya konu aboneliğinin kaynak düzeyinde ayarlanmış bir kilit süresi vardır. Alıcı istemcisi kaynaktan bir ileti çektiğinde, Service Bus aracısı iletiye bir ön kilit uygular. İlk kilit, kaynak düzeyinde ayarlanan kilit süresi için sürer. İleti kilidi süresi dolmadan önce yenilenmediyse Service Bus aracısı iletiyi serbest bırakarak diğer alıcıların kullanımına açar. Uygulama, kilit süresi dolduktan sonra bir iletiyi tamamlamaya veya bırakmaya çalışırsa, API çağrısı com.azure.messaging.servicebus.ServiceBusException: The lock supplied is invalid. Either the lock expired, or the message has already been removed from the queuehatasıyla başarısız olur.

Service Bus istemcisi, süresi dolmadan önce ileti kilidini sürekli olarak yenileyen bir arka plan kilidi yenileme görevi çalıştırmayı destekler. Varsayılan olarak, kilit yenileme görevi 5 dakika boyunca çalışır. ServiceBusReceiverClientBuilder.maxAutoLockRenewDuration(Duration)kullanarak kilit yenileme süresini ayarlayabilirsiniz. Duration.ZERO değerini geçerseniz, kilit yenileme görevi devre dışı bırakılır.

Aşağıdaki liste, kilit kaybı hatasına neden olabilecek bazı kullanım desenlerini veya konak ortamlarını açıklıyor.

  • Kilit yenileme görevi devre dışı bırakılır ve uygulamanın ileti işleme süresi kaynak düzeyinde ayarlanan kilit süresini aşıyor.

  • Uygulamanın ileti işleme süresi, yapılandırılan kilit yenileme görev süresini aşıyor. Kilit yenileme süresi açıkça ayarlanmazsa varsayılan olarak 5 dakika olduğunu unutmayın.

  • Uygulama, ServiceBusReceiverClientBuilder.prefetchCount(prefetch)kullanarak prefetch değerini pozitif bir tamsayıya ayarlayarak Prefetch özelliğini açtı. Prefetch özelliği etkinleştirildiğinde, istemci Service Bus varlığından (kuyruk veya konu) ön işleme eşit ileti sayısını alır ve bunları bellek içi ön yükleme arabelleğinde depolar. İletiler, uygulama tarafından alınana kadar ön bellek arabelleğinde kalır. İstemci, ön getirme arabelleğindeyken iletilerin kilidini uzun süre aktif tutmaz. Uygulama işleme o kadar uzun sürerse ve bu sırada ileti kilitleri prefetch arabelleğinde süresi dolacak şekilde kalırsa, uygulama süresi dolmuş kilitlere sahip iletileri alabilir. Daha fazla bilgi için bkz. Prefetch neden varsayılan seçenek değil?

  • Konak ortamında, kilit yenileme görevinin kilidi zamanında yenilemesini engelleyen geçici ağ hatası veya kesinti gibi ağ sorunları ara sıra meydana gelebilir.

  • Konak ortamında yeterli CPU yok veya zaman zaman kilit yenileme görevinin zamanında çalışmasını geciktiren CPU döngüleri sıkıntısı yaşanıyor.

  • Ana sistemin saati doğru değil - örneğin, saat hatalıdır - kilit yenileme görevini geciktiriyor ve zamanında çalışmasını önlüyor.

  • Bağlantı G/Ç iş parçacığı aşırı yüklenmiş olup, bu durum kilit yenileme ağ çağrılarının zamanında yürütülme yeteneğini olumsuz etkilemektedir. Aşağıdaki iki senaryo bu soruna neden olabilir:

    • Uygulama aynı bağlantıyı paylaşan çok fazla alıcı istemci çalıştırıyor. Daha fazla bilgi için Bağlantı paylaşımı darboğazı bölümüne bakın.
    • Uygulama, ServiceBusReceiverClient.receiveMessages veya ServiceBusProcessorClient büyük bir maxMessages veya maxConcurrentCalls değerlerine sahip olacak şekilde yapılandırdı. Daha fazla bilgi için ServiceBusProcessorClient Eşzamanlılık bölümüne bakın.
  • Kilit kaybı hatası olasılığını artıran yaygın bir uygulama düzeni, uzun süre çalışan kilit yenileme görevlerini (örneğin, birkaç saat süren görevler) zamanlamayı içerir. Daha önce belirtildiği gibi, Service Bus istemcisinin denetimi dışındaki çeşitli faktörler kilit yenilemenin başarılı olmasına engel olabileceğinden, uygulama tasarımları uzun süreler boyunca garantili yenilemeyi kabul etmekten kaçınmalıdır. Uzun süre çalışan işlemleri yeniden işlemek zorunda kalmamak için, işi daha küçük parçalara ayırmayı veya aynı anda etkili denetim noktası oluşturma mantığını uygulamayı göz önünde bulundurun.

İstemcideki kilit yenileme görevlerinin sayısı, maxMessages veya maxConcurrentCallsiçin ayarlanan ServiceBusProcessorClient veya ServiceBusReceiverClient.receiveMessages parametre değerlerine eşittir. Birden çok ağ çağrısı yapan fazla sayıda kilit yenileme görevi, Service Bus ad alanı daraltma üzerinde de olumsuz bir etki yaratabilir.

Ana bilgisayar yeterince kaynaklandırılmamışsa, yalnızca birkaç kilit yenileme görevi çalışıyor olsa bile kilit yine de kaybolabilir. Java uygulamasını bir kapsayıcıda çalıştırıyorsanız iki veya daha fazla vCPU çekirdeği kullanmanızı öneririz. Kapsayıcılı ortamlarda Java uygulamaları çalıştırırken 1'den az vCPU çekirdeği seçmenizi önermiyoruz. Kaynak oluşturma hakkında ayrıntılı öneriler için bkz. Java uygulamalarınızı konteynerleştirin.

Kilitlerle ilgili aynı açıklamalar, Service Bus kuyruğu veya oturumu etkinleştirilmiş bir konu aboneliği için de geçerlidir. Alıcı istemcisi kaynaktaki bir oturuma bağlandığında, aracı oturuma bir başlangıç kilidi uygular. Oturumun kilidini korumak için istemcideki kilit yenileme görevinin süresi dolmadan önce oturum kilidini yenilemeye devam etmesi gerekir. Oturum etkinleştirilmiş bir kaynakta, Service Bus düğümleri arasında yük dengelemesini sağlamak amacıyla temel bölümler bazen taşınır; örneğin, yükü paylaşmak için yeni düğümler eklendiğinde. Bu durumda oturum kilitleri kaybolabilir. Uygulama, oturum kilidi kaybolduktan sonra bir iletiyi tamamlamaya veya bırakmaya çalışırsa API çağrısı com.azure.messaging.servicebus.ServiceBusException: The session lock was lost. Request a new session receiverhatasıyla başarısız olur.

Sonraki adımlar

Bu makaledeki sorun giderme kılavuzu Java istemci kitaplıkları için Azure SDK'sını kullanırken karşılaşılan sorunları çözmeye yardımcı olmazsa, Java GitHub deposuiçin Azure SDK'da bir sorun öneririz.