Przewodnik rozwiązywania problemów z programem Spring JMS

W tym artykule opisano sposób rozwiązywania znanych problemów i typowych błędów podczas korzystania z programu Spring JMS. Artykuł zawiera również odpowiedzi na kilka często zadawanych pytań dotyczących spring-cloud-azure-starter-servicebus-jms.

Problemy z łącznością

MessageProducer został zamknięty z powodu nieodwracalnego błędu

Opis problemu

W przypadku używania JmsTemplate do wysyłania komunikatów JmsTemplate staje się niedostępna w okresie bezczynności od 10 do 15 minut. Wysyłanie komunikatów w tym przedziale czasu może skutkować wystąpieniem wyjątków pokazanych w poniższym przykładowym wyniku:

2022-11-06 11:12:05.762  INFO 25944 --- [   scheduling-1] c.e.demo.ServiceBusJMSMessageProducer    : Sending message: 2022-11-06T11:12:05.762072 message 1
2022-11-06 11:12:05.772 ERROR 25944 --- [   scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task

org.springframework.jms.IllegalStateException: The MessageProducer was closed due to an unrecoverable error.; nested exception is javax.jms.IllegalStateException: The MessageProducer was closed due to an unrecoverable error.
    at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:274) ~[spring-jms-5.3.23.jar:5.3.23]
  ...
Caused by: org.apache.qpid.jms.provider.ProviderException: The link 'G0:36906660:qpid-jms:sender:azure:5caf3ef4-9602-413c-964d-cf1292d6e1f5:1:1:1:t4' is force detached. Code: publisher(link376). Details: AmqpMessagePublisher.IdleTimerExpired: Idle timeout: 00:10:00. [condition = amqp:link:detach-forced]
    at org.apache.qpid.jms.provider.amqp.AmqpSupport.convertToNonFatalException(AmqpSupport.java:181) ~[qpid-jms-client-0.53.0.jar:na]
  ...

Analiza przyczyny

Wyjątki występują w przypadku usługi Azure Service Bus, gdy połączenie i link protokołu AMQP są aktywne, ale żadne wywołania — na przykład wysyłanie lub odbieranie połączeń — są wykonywane przy użyciu linku przez 10 minut. W takim przypadku link jest zamknięty. A gdy wszystkie linki w połączeniu zostały zamknięte, ponieważ nie było aktywności (bezczynności), a nowe łącze nie zostało utworzone w ciągu 5 minut, połączenie jest zamknięte.

W przypadku modułu startowego JMS usługi Service Bus domyślnie używana jest CachingConnectionFactory, która przechowuje w pamięci podręcznej sesję, producenta i konsumenta. Jeśli element JmsProducer pozostaje bezczynny przez ponad 10 minut, ale krócej niż 15 minut, łącze zajmowane przez buforowanego producenta zostało zamknięte. W tym interwale nie można wysyłać komunikatów. Następnie po upływie kolejnych 5 minut bezczynności całe połączenie zostanie zamknięte. W związku z tym każda operacja wysyłania po 15 minutach bezczynności powoduje utworzenie przez CachingConnectionFactory nowego połączenia w celu wysłania danych. Operacja wysyłania staje się dostępna po 15 minutach.

Rozwiązanie tymczasowe

Obecnie moduł startowy zapewnia obejście problemu z odłączaniem łącza poprzez zastosowanie JmsPoolConnectionFactory, który tworzy pule obiektów Connection, Session i MessageProducer oraz zarządza cyklem życia instancji w puli. To obejście może zapewnić, że producent zostanie usunięty po tym, jak stanie się niedostępny, dzięki czemu wszystkie operacje wysyłania będą wykonywane przez aktywnych producentów.

Aby użyć tego obejścia, dodaj następującą konfigurację:

spring:
  jms:
    servicebus:
      pool:
        enabled: true
        max-connections: ${your-expected-max-connection-value}

Użycie spring.jms.servicebus.idle-timeout

Właściwości limitu czasu bezczynności konfigurują limit czasu bezczynności połączenia AMQP. Specyfikacja protokołu AMQP zawiera następujący opis:

Połączenia podlegają progowi limitu czasu bezczynności. Limit czasu jest wyzwalany przez lokalny element równorzędny, gdy nie zostaną odebrane żadne ramki po przekroczeniu wartości progowej. Limit czasu bezczynności jest mierzony w milisekundach i jest liczony od chwili odebrania ostatniej ramki. Jeśli próg zostanie przekroczony, węzeł równorzędny POWINIEN spróbować zamknąć połączenie w sposób kontrolowany przy użyciu ramki zamknięcia z komunikatem o błędzie wyjaśniającym przyczynę. Jeśli zdalna strona nie odpowie na to w sposób poprawny w określonym czasie, strona MOŻE zamknąć gniazdo TCP.

W przypadku klienta JMS podczas konfigurowania tej właściwości można kontrolować po stronie serwera, jak długo oczekujesz, że serwer będzie wysyłać pustą ramkę, aby zachować połączenie aktywne, gdy nie są dostarczane żadne komunikaty. Ta właściwość określa zachowanie zdalnego węzła równorzędnego, a każdy węzeł równorzędny może mieć własną, odrębną wartość.

Problemy z platformą JmsTemplate

Zaplanowane komunikaty

Usługa Azure Service Bus obsługuje opóźnione przetwarzanie komunikatów. Aby uzyskać więcej informacji, zobacz sekcję Zaplanowane komunikatysekwencjonowanie komunikatów i znaczniki czasu. W przypadku programu JMS, aby zaplanować komunikat, ustaw właściwość ScheduledEnqueueTimeUtc przy użyciu nagłówka adnotacji komunikatu x-opt-scheduled-enqueue-time.

Problemy z programem JmsListener

Zbyt wiele żądań jest wysyłanych do usługi Service Bus, mimo że na serwerze nie ma żadnych komunikatów

Opis problemu

Podczas korzystania z interfejsu API @JmsListener w niektórych przypadkach w portalu Azure mogą być widoczne utrzymujące się wartości dla żądań przychodzących wysyłanych do kolejek lub tematów, nawet jeśli na serwerze nie ma żadnych komunikatów do odebrania.

Analiza przyczyny

@JmsListener to odbiornik sondowania, który jest zbudowany na potrzeby powtarzających się prób sondowania.

Odbiornik znajduje się w trwającej pętli sondowania. Każda pętla wywołuje metodę MessageConsumer.receive() JMS w celu sondowania odbiorcy lokalnego pod kątem korzystania z komunikatów. Domyślnie dla każdej operacji sondowania odbiorca lokalny wysyła żądania ściągnięcia do brokera komunikatów, aby poprosić o komunikaty, a następnie blokuje go przez określony czas. Dokładny sposób odpytywania jest określany przez kilka właściwości, w tym receiveTimeout, prefetchSize i receiveLocalOnly lub receiveNoWaitLocalOnly. Metoda receiveNoWaitLocalOnly jest używana tylko wtedy, gdy ustawisz receiveTimeout na wartość ujemną.

Jeśli ten problem występuje w aplikacji, sprawdź następujące ustawienia konfiguracji:

  • Sprawdź, czy zasada wstępnego pobierania ma wartość 0, co jest również opcją domyślną. 0-prefetch oznacza konsumenta typu pull, który wysyła żądania pobrania do usługi Service Bus przy każdym odpytywaniu.

  • Jeśli skonfigurowano pobieranie wstępne inne niż zero, określ, czy właściwość receiveLocalOnly czy receiveNoWaitLocalOnly jest ustawiona na wartość false, która jest opcją domyślną. Wartość false w tym miejscu nadal skutkuje wysyłaniem żądań pobrania do serwera, ponieważ nie odpytuje wyłącznie lokalnego konsumenta.

  • Konfiguracja receiveTimeout określa, jak długo blokuje każde żądanie ściągnięcia, dzięki czemu może mieć wpływ na częstotliwość wysyłania żądań ściągnięcia do serwera. Wartość domyślna to 1 sekunda.

Aby uzyskać pełną analizę, zobacz dyskusję w zgłoszeniu GitHub.

Rozwiązania

W poniższych sekcjach opisano dwa rozwiązania dotyczące tego problemu

Rozwiązanie 1. Zmiana w celu wypychania tylko odbiorcy i sprawdzania lokalnego

Po zmianie trybu na push konsument staje się konsumentem powiadomień asynchronicznych, który nie pobiera komunikatów z brokera, ale utrzymuje docelowy poziom kredytu łącza. Kwota jest ustalana przez właściwość pobierania z góry. Gdy usługa Service Bus (nadawca) wysyła komunikaty, kredyt łącza nadawcy maleje, a gdy spadnie on poniżej określonego progu, klient (odbiorca) wysyła do serwera żądanie zwiększenia kredytu łącza nadawcy z powrotem do żądanej wartości docelowej.

Aby wykonać to rozwiązanie, dodaj następującą konfigurację:

Najpierw ustaw wartość prefetch na różną od zera, co skonfiguruje konsumenta jako nie typu pull. W poniższej tabeli przedstawiono kilka właściwości pobierania wstępnego, z których każda kontroluje różne jednostki usługi Service Bus. Ustaw właściwości, które mają zastosowanie do twojego przypadku.

Własność Opis
spring.jms.servicebus.prefetch.all Domyślna wartość opcji pobierania wstępnego w tej przestrzeni nazw usługi Service Bus
spring.jms.servicebus.prefetch.queue-prefetch Numer pobierania wstępnego dla kolejki.
spring.jms.servicebus.prefetch.queue-browser-prefetch Liczba wiadomości pobieranych z wyprzedzeniem dla przeglądarki kolejki.
spring.jms.servicebus.prefetch.topic-prefetch Liczba prefetch dla tematu.
spring.jms.servicebus.prefetch.durable-topic-prefetch Liczba prefetch dla trwałego tematu.

Po drugie skonfiguruj non-local-check, dodając klasę konfiguracji dla konfiguratora fabryki, jak pokazano w poniższym przykładzie:

@Configuration(proxyBeanMethods = false)
public class CustomJmsConfiguration {

    @Bean
    ServiceBusJmsConnectionFactoryCustomizer customizer() {
        return factory -> {
            factory.setReceiveLocalOnly(true);
            // Configure the below ReceiveNoWaitLocalOnly instead if you have specified the property 
            // spring.jms.listener.receive-timeout with negative value. Otherwise, configure the above `ReceiveLocalOnly`.
            //factory.setReceiveNoWaitLocalOnly(true);
        };
    }
}

Wartość prefetch może wpływać na szybkość dostarczania komunikatów do lokalnego bufora konsumenta. Należy dostosować wartość zgodnie z zużywaną wydajnością i woluminami komunikatów. Odpowiednia wartość może przyspieszyć proces zużywania, a wartość, która jest zbyt duża, może spowodować, że komunikaty buforowane lokalnie staną się nieaktualne i ponownie wysłane. W przypadku małych woluminów komunikatów, w przypadku których przetwarzanie każdego komunikatu zajmuje dużo czasu, ustaw wartość prefetch na 1. Ta wartość gwarantuje, że użytkownik przetwarza tylko jeden komunikat naraz.

Rozwiązanie 2. Zwiększ limit czasu odbierania, aby zmniejszyć częstotliwość ściągania

Właściwość limitu czasu odbioru określa strategię tego, jak długo konsument pozostaje zablokowany, czekając na wynik operacji pull. Dlatego przez wydłużenie limitu czasu można zmniejszyć częstotliwość ściągania, a następnie zmniejszyć liczbę żądań ściągnięcia po wybraniu trybu ściągnięcia. W skrajnych przypadkach można ustawić strategię bezterminowego oczekiwania, aż nadejdzie komunikat, co oznacza, że odbiorca pobiera kolejny komunikat dopiero po przetworzeniu poprzedniego. W takim przypadku, gdy na serwerze nie ma żadnych komunikatów, będzie blokować oczekiwanie.

Aby wykonać to rozwiązanie, skonfiguruj właściwość spring.jms.listener.receive-timeout. Ta właściwość jest typu java.time.Duration i ma domyślną wartość 1 sekundy. Poniższa lista wyjaśnia efekt różnych wartości:

  • Ustawienie limitu czasu odbierania na 0 oznacza, że operacja pobierania blokuje się bezterminowo, aż do czasu dostarczenia wiadomości.
  • Ustawienie limitu czasu odbioru na wartość dodatnią oznacza, że operacja pull blokuje się maksymalnie na czas określony przez ten limit.
  • Ustawienie limitu czasu odbioru na wartość ujemną oznacza, że operacja pull jest odbiorem bez oczekiwania, co oznacza, że natychmiast zwraca wiadomość lub null, jeśli nie ma dostępnych wiadomości.

Uwaga

Wysoka wartość limitu czasu może przynieść pewne skutki uboczne. Na przykład wartość wysokiego limitu czasu wydłuży również czas, przez który główny wątek znajduje się w stanie bloku. Ten stan oznacza, że kontener będzie mniej reagował na wywołania stop() i może zatrzymać się tylko między receive() wywołaniami.

Ponadto kontener może wysyłać żądania tylko po upływie interwału receive-timeout. Jeśli interwał jest dłuższy niż 10 minut, usługa Service Bus zamknie łącze i uniemożliwi odbiornikowi wysyłanie lub odbieranie. Aby uzyskać więcej informacji, zobacz sekcję Link jest zamknięta sekcji błędów protokołu AMQP w usłudze Azure Service Bus. Domyślnie odbiornik używa CachingConnectionFactory.

Jeśli potrzebujesz długiego limitu czasu oczekiwania na odbiór, pamiętaj, by używać JmsPoolConnectionFactory.

Aby uzyskać więcej informacji na temat problemu z zamykaniem łącza i tego, jak używać JmsPoolConnectionFactory, zobacz sekcję MessageProducer został zamknięty z powodu nienaprawialnego błędu.

Problem z prefetchingiem

Opis problemu

Nieodpowiednia polityka pobierania wstępnego może powodować następujące problemy:

  • Te same komunikaty są wielokrotnie odbierane.
  • Komunikaty są umieszczane w kolejce wiadomości niedostarczonych po upływie MaxDeliveryCountExceeded, nawet gdy są przetwarzane bez błędów ani wyjątków.

Analiza przyczyny

Ten problem zwykle występuje, gdy wartość prefetch jest wyższa niż rzeczywista zdolność przetwarzania, w wyniku czego zbyt wiele komunikatów jest pobieranych z wyprzedzeniem do lokalnego bufora i oczekuje na przetworzenie. Jednak wstępnie pobrane komunikaty są traktowane po stronie usługi Service Bus jako wysłane w trybie peek-lock. Każdy wysłany komunikat ma atrybuty max-delivery-count i lock-duration. peek-lock W trybie odbierania komunikaty pobierane do buforu pobierania wstępnego są pobierane do buforu w stanie zablokowanym z zegarem limitu czasu dla tykania blokady. Jeśli bufor pobierania wstępnego jest duży, a przetwarzanie trwa tak długo, że blokady komunikatów wygasają podczas pozostawania w buforze pobierania wstępnego, komunikat jest traktowany jako porzucony i ponownie udostępniany do pobierania z kolejki.

Ten problem może spowodować pobranie komunikatu do buforu wstępnego pobierania i umieszczenie go na końcu. Jeśli bufor prefetch nie zostanie przetworzony przed wygaśnięciem wiadomości, wiadomości są wielokrotnie wstępnie pobierane, ale nigdy nie są faktycznie dostarczane w stanie umożliwiającym ich użycie (z prawidłowo założoną blokadą). Następnie po usunięciu tych nieaktualnych kopii aplikacja wielokrotnie używa tego samego komunikatu i nie jest w stanie ich ukończyć. W innym przypadku wszystkie powtarzające się komunikaty wygasają w buforze, zanim zostaną przetworzone. W takim przypadku komunikat w usłudze Service Bus zostanie ostatecznie przeniesiony do kolejki wiadomości niedostarczonych po przekroczeniu maksymalnej liczby prób dostarczenia.

Aby uzyskać więcej informacji, zobacz sekcję Dlaczego pobieranie wstępne nie jest opcją domyślną? w artykule Pobieranie wstępne komunikatów usługi Azure Service Bus.

Rozwiązanie

Należy zachować ostrożność przy konfiguracji parametru prefetch, aby był on dostosowany do możliwości przetwarzania po stronie konsumenta. Musisz zrównoważyć maksymalną liczbę wiadomości pobieranych z wyprzedzeniem oraz czas trwania blokady skonfigurowany dla kolejki lub subskrypcji tak, aby czas wygaśnięcia blokady był co najmniej dłuższy niż skumulowany oczekiwany czas przetwarzania wiadomości dla maksymalnego rozmiaru buforu wstępnego pobierania, powiększonego o jeszcze jedną wiadomość. Jednocześnie limit czasu blokady nie powinien być tak długi, że komunikaty mogą przekraczać maksymalny czas wygaśnięcia, gdy zostaną przypadkowo usunięte, co wymaga wygaśnięcia blokady przed ponownym wysłaniem.

Aby skonfigurować atrybut pobierania wstępnego, który ma wartość domyślną zero, użyj jednej z następujących właściwości:

Własność Opis
spring.jms.servicebus.prefetch.all Wartość rezerwowa opcji pobierania wstępnego w tej przestrzeni nazw usługi Service Bus.
spring.jms.servicebus.prefetch.queue-prefetch Numer pobierania wstępnego dla kolejki.
spring.jms.servicebus.prefetch.queue-browser-prefetch Liczba wiadomości pobieranych z wyprzedzeniem dla przeglądarki kolejki.
spring.jms.servicebus.prefetch.topic-prefetch Liczba prefetch dla tematu.
spring.jms.servicebus.prefetch.durable-topic-prefetch Liczba prefetch dla trwałego tematu.

Jak wykonać dyspozycję protokołu AMQP w usłudze Service Bus?

Program JMS obsługuje pięć typów dyspozycji protokołu AMQP podczas potwierdzania komunikatów brokerowi obsługi komunikatów. Obsługiwane wartości to ACCEPTED, REJECTED, RELEASED, MODIFIED_FAILEDi MODIFIED_FAILED_UNDELIVERABLE. Aby uzyskać więcej informacji, zobacz sekcję Mapowanie dyspozycji AMQP i operacji Service Bus w dokumencie Korzystanie z usługi Java Message Service 1.1 ze standardową usługą Azure Service Bus i protokołem AMQP 1.0.

Dlatego w celu ręcznego ukończenia, porzucenia, utraconych komunikatów, odroczenia lub wydania wiadomości przy użyciu JmsListenerwykonaj następujące czynności:

  1. Wyłącz tryb sesji transakcyjnej i użyj trybu potwierdzeń CLIENT.

    Aby wykonać to zadanie, albo zadeklaruj własny bean JmsListenerContainerFactory, a następnie ustaw jego właściwości, albo wykonaj przetwarzanie końcowe elementu JmsListenerContainerFactory zdefiniowanego w starter. W poniższym przykładzie użyto podejścia polegającego na deklarowaniu kolejnego beana:

    @Configuration(proxyBeanMethods = false)
    public class CustomJmsConfiguration {
    
        @Bean
        public JmsListenerContainerFactory<?> customQueueJmsListenerContainerFactory(
                DefaultJmsListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory) {
            DefaultJmsListenerContainerFactory jmsListenerContainerFactory = new DefaultJmsListenerContainerFactory();
            configurer.configure(jmsListenerContainerFactory, connectionFactory);
            jmsListenerContainerFactory.setPubSubDomain(Boolean.FALSE);
            jmsListenerContainerFactory.setSessionTransacted(Boolean.FALSE);
            jmsListenerContainerFactory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
            return jmsListenerContainerFactory;
        }
    }
    
  2. W procedurze obsługi komunikatów jawnie ukończ lub porzucaj komunikaty.

    @JmsListener(destination = "QUEUE_NAME", containerFactory = "customQueueJmsListenerContainerFactory")
    public void receiveMessage(JmsTextMessage message) throws Exception {
        String event = message.getBody(String.class);
        try {
            logger.info("Received event: {}", event);
            logger.info("Received message: {}", message);
            // by default complete the message
            message.acknowledge();
        } catch (Exception e) {
            logger.error("Exception while processing re-source event: " + event, e);
            JmsAcknowledgeCallback acknowledgeCallback = message.getAcknowledgeCallback();
            // explicitly abandon the message
            acknowledgeCallback.setAckType(MODIFIED_FAILED);
            message.setAcknowledgeCallback(acknowledgeCallback);
            message.acknowledge();
            throw e;
        }
    }
    

Problemy z konfiguracją

Wyłączanie automatycznej konfiguracji usługi Service Bus JMS

Opis problemu

Niektórzy użytkownicy importują niektóre startery Spring Cloud Azure do automatycznej konfiguracji usługi platformy Azure innej niż Service Bus JMS. Korzystają one również z platformy Spring JMS bez konieczności korzystania z usługi Service Bus JMS. Następnie podczas próby uruchomienia aplikacji są zgłaszane następujące wyjątki:

Caused by: java.lang.IllegalArgumentException: 'spring.jms.servicebus.connection-string' should be provided
    at com.azure.spring.cloud.autoconfigure.jms.properties.AzureServiceBusJmsProperties.afterPropertiesSet(AzureServiceBusJmsProperties.java:210)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800)
    ... 98 more

Analiza przyczyny

Ten problem występuje, ponieważ wszystkie klasy autokonfiguracji platformy Azure Spring Cloud są umieszczane w tym samym module, więc każdy szablon startowy Spring Cloud Azure faktycznie importuje całą tę automatyczną konfigurację, która obejmuje również usługę Service Bus JMS. Następnie, gdy aplikacja korzysta z interfejsu API Spring JMS, spełnia warunki autokonfiguracji JMS usługi Service Bus i uruchamia ją. Wówczas w przypadku użytkowników, którzy nie zamierzają używać spring-cloud-azure-starter-servicebus-jms, warunki dotyczące właściwości nie zostają spełnione, ponieważ nie ma potrzeby konfigurowania usługi Service Bus na potrzeby JMS. Taka sytuacja powoduje zgłaszanie wyjątków.

Rozwiązanie

Rozwiązanie Spring Cloud Azure for Service Bus JMS udostępnia właściwość włączania lub wyłączania jej automatycznej konfiguracji. Możesz wyłączyć tę funkcję zgodnie z potrzebami, używając następującego ustawienia właściwości:

spring.jms.servicebus.enabled=false

Konfigurowanie atrybutów komunikatów

Jak ustawić typ zawartości komunikatów wychodzących?

Aby skonfigurować typ zawartości, dostosuj konwerter komunikatów, aby zmodyfikować atrybut typu zawartości podczas konwertowania komunikatów. Poniższy kod przyjmuje komunikaty bajtowe jako przykład.

Najpierw dostosuj konwerter komunikatów do użycia w JmsTemplate, jak pokazano w poniższym przykładzie:

public class CustomMappingJackson2MessageConverter extends MappingJackson2MessageConverter {

    public static final String CONTENT_TYPE = "application/json";

    public CustomMappingJackson2MessageConverter() {
        this.setTargetType(MessageType.BYTES);
    }

    @Override
    protected BytesMessage mapToBytesMessage(Object object, Session session, ObjectWriter objectWriter)
            throws JMSException, IOException {
        final BytesMessage message = super.mapToBytesMessage(object, session, objectWriter);
        JmsBytesMessage msg = (JmsBytesMessage) message;
        AmqpJmsMessageFacade facade = (AmqpJmsMessageFacade) msg.getFacade();
        facade.setContentType(Symbol.valueOf(CONTENT_TYPE));
        return msg;
    }
}

Następnie zadeklaruj własny bean konwertera komunikatów, jak pokazano w tym przykładzie:

@Configuration(proxyBeanMethods = false)
public class CustomJmsConfiguration {

    @Bean
    public MessageConverter messageConverter() {
        return new CustomMappingJackson2MessageConverter();
    }
}

Jak ustawić nazwę właściwości identyfikatora typu dla MapJackson2MessageConverter?

Atrybut type-id-property-name umożliwia MappingJackson2MessageConverter określenie klasy używanej do deserializacji ładunku komunikatu. Podczas serializacji każdego obiektu Java do ładunku komunikatu Spring konwerter przechowuje typ ładunku we właściwości komunikatu, której nazwa jest rejestrowana przez type-id-property-name. Następnie, podczas deserializacji komunikatu, konwerter odczytuje z komunikatu identyfikator typu i przeprowadza deserializację.

Aby ustawić type-id-property-name, zadeklaruj własny komponent MappingJackson2MessageConverter bean i skonfiguruj tę właściwość, jak pokazano w poniższym przykładzie:

@Configuration(proxyBeanMethods = false)
public class CustomJmsConfiguration {

    @Bean
    public MessageConverter jacksonJmsMessageConverter()
    {
        MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
        converter.setTypeIdPropertyName("your-custom-type-id-property-name");
        return converter;
    }
}

Wykrywanie duplikatów

Usługa Azure Service Bus obsługuje wykrywania duplikatów, która stosuje właściwość MessageId w celu unikatowego identyfikowania komunikatów i odrzucania duplikatów wysyłanych do usługi Service Bus.

Jednak w przypadku interfejsu API JMS nie należy ustawiać identyfikatora komunikatu JMS, który jest uważany za niedozwolone w specyfikacji JMS. Dlatego ta funkcja nie jest obecnie obsługiwana w rozwiązaniu Spring Cloud Azure Service Bus JMS Starter.

Aby uzyskać dalsze aktualizacje dotyczące tej funkcji, zobacz zgłoszenie w serwisie GitHub .

Włącz rejestrowanie transportu AMQP

Aby uzyskać więcej informacji, zobacz sekcję włączanie rejestrowania transportu AMQP w dokumencie Rozwiązywanie problemów z usługą Service Bus.

Uzyskaj dodatkową pomoc

Aby uzyskać więcej informacji na temat sposobów dotarcia do pomocy technicznej, zobacz Support w katalogu głównym repozytorium.

Zasoby dla szablonu startowego JMS usługi Azure Service Bus platformy Spring Cloud

Zgłaszanie problemów z usługą GitHub

Podczas zgłaszania problemów z usługą GitHub wymagane są następujące szczegóły:

  • Konfiguracja usługi Service Bus / środowisko obszaru nazw
    • Jaka warstwa to przestrzeń nazw (Standardowa lub Premium)?
    • Jakiego typu jednostka obsługi komunikatów jest używana (kolejka lub temat)? i jego konfiguracja.
    • Jaki jest średni rozmiar każdego komunikatu?
  • Jak wygląda wzorzec ruchu? (czyli liczba komunikatów na minutę i to, czy klient jest zawsze zajęty, czy ma wolne okresy ruchu).
  • Kod i kroki odtwarzania
    • Jest to ważne, ponieważ często nie możemy odtworzyć problemu w naszym środowisku.
  • Dzienniki