Почему незаконченные сообщения не попадают в мою тему мертвых писем?

Вопрос или проблема

Итак, сценарий простой: я хочу настроить эмулятор pubsub от Google так, чтобы у него была тема для очереди мертвых писем, и если сообщение вызывает исключение в обработчике, это сообщение должно быть перенаправлено в тему очереди мертвых писем. Затем я хочу иметь возможность подписаться на эту тему и извлекать мертвые письма из нее. Я использую spring-cloud-gcp-starter-pubsub в моих продюсерах и потребителях, затем использую следующие команды оболочки, чтобы запустить и настроить эмулятор:

gcloud beta emulators pubsub start --project=local-test --host-port=0.0.0.0:8080

затем после того, как он полностью запустится,

curl -X PUT -v http://localhost:8080/v1/projects/local-test/topics/fam-task
curl -X PUT -v http://localhost:8080/v1/projects/local-test/topics/dead-letter
curl -X PUT 'http://localhost:8080/v1/projects/local-test/subscriptions/subscription-task-reactor-fam-task' \
--header 'Content-Type: application/json' --data '{"topic": "projects/local-test/topics/fam-task", "enableMessageOrdering": true, "enableExactlyOnceDelivery": true, "deadLetterPolicy": {"deadLetterTopic": "projects/local-test/topics/dead-letter", "maxDeliveryAttempts": 5}}'

echo "Создать подписки для мертвых писем"
curl -X PUT 'http://localhost:8080/v1/projects/local-test/subscriptions/subscription-dead-letter' \
--header 'Content-Type: application/json' --data '{"topic": "projects/local-test/topics/dead-letter", "enableMessageOrdering": true, "enableExactlyOnceDelivery": true}'

Мне удается проверить, что продюсеры и потребители правильно связаны между собой и отправляют/получают сообщения, как ожидалось. Для целей проверки концепции я заставляю метод получения просто выбрасывать новое RuntimeException() при получении сообщения. Когда это происходит, в логах моего приложения отображается

PubSubInboundChannelAdapter – Отправка сообщения Spring [4] не удалась; сообщение автоматически отклонено.

5 раз, что соответствует ожидаемому поведению, определенному при создании subscription-task-reactor-fam-task, но опрос очереди мертвых писем с помощью

POST http://localhost:8080/v1/projects/local-test/subscriptions/subscription-dead-letter:pull

приводит к тайм-ауту без возвращаемых сообщений. Подписка и тема существуют, тема мертвых писем существует и, кажется, задана при создании подписки. Подписка на тему мертвых писем существует, действительна и может быть опрошена, просто даже когда сообщения отклоняются, они не отображаются, когда я опрашиваю тему мертвых писем. Я вижу другие вопросы с ответами о том, чтобы убедиться, что у учетной записи службы есть доступные роли подписчика и издателя, но я не уверен, как (если вообще) это относится к эмулятору. Есть идеи, что я делаю не так?

Ответ или решение

Вопрос, с которым вы столкнулись, касается настройки "dead letter queue" (DLQ) в эмуляторе Pub/Sub от Google. Правильная конфигурация DLQ имеет решающее значение для управления отсечёнными сообщениями, которые не могут быть обработаны после нескольких попыток. Давайте проанализируем вашу ситуацию и выясним, почему сообщения, которые не были успешно обработаны, не поступают в заданный вами "dead letter topic".

1. Объяснение конфигурации

Вы уже создали два топика: fam-task и dead-letter, а также настройки подписки subscription-task-reactor-fam-task. Это правильные шаги, однако давайте остановимся на важности правильной конфигурации политики мёртвых письем. В вашем случае:

"deadLetterPolicy": {
  "deadLetterTopic": "projects/local-test/topics/dead-letter",
  "maxDeliveryAttempts": 5
}

Эта конфигурация предполагает, что если сообщение не может быть обработано после пяти попыток, оно будет перенаправлено в указанный вами мёртвый топик. Однако есть несколько моментов, которые стоит проверить внимательнее.

2. Обработка исключений

Вы указали, что ваша обработка сообщения завершается с выбросом RuntimeException. Важно убедиться, что ваш обработчик корректно ловит исключения и передаёт обратную связь о неудачных обработках в сервис Pub/Sub. Просто выбрасывание исключения не всегда приводит к "nack"-у сообщения. Убедитесь, что вы используете корректные механизмы для этой обработки. Например, в Spring нужно правильно настраивать уровень обработки ошибок и возможности обработки сообщений.

3. Качество сообщений и атрибуты

Проверьте, что все сообщения, которые вы отправляете в fam-task, соответствуют требованиям Pub/Sub. Иногда дополнительные атрибуты, требуемые в сообщении, могут влиять на его доставку в DLQ. Убедитесь, что формат и содержимое сообщений корректны.

4. Особенности эмулятора

Локальный эмулятор Google Pub/Sub может вести себя несколько иначе, чем реальный сервис. Например, он может не полностью поддерживать все функции, доступные в облачном варианте. Убедитесь, что ваша версия эмулятора актуальна и поддерживает функции, которые вы хотите использовать, включая мёртвые темы и подписки.

5. Аутентификация и роли

Вы затронули аспекты аутентификации и ролей. В эмуляторе вам не потребуется настраивать роли для сервисных учётных записей, как это требуется в облаке. Все тесты можно проводить в рамках локальной среды, но убедитесь, что приложение правильно настроено для работы с эмулятором, и что у него есть необходимые разрешения для отправки запросов.

6. Временные задержки

Иногда сообщения могут не сразу появляться в DLQ. Возможны временные задержки или проблемы с сетью вызова, что может привести к тому, что результат /pull не показывает ожидаемое поведение. Попробуйте добавить небольшую паузу между попытками получения сообщений из мёртвого топика.

Заключение

Для того чтобы решить проблему с не поступающими мёртвыми сообщениями в вашем случае, вам нужно тщательно проверить порядок обработки исключений, алиасы и форматы сообщений, а также провести дополнительные тесты с учётом особенностей эмулятора. Если после выполнения всех этих шагов проблема сохраняется, рекомендуется обратиться к официальной документации Google Pub/Sub и, возможно, в сообщество разработчиков для получения более целенаправленной помощи.

Оцените материал
Добавить комментарий

Капча загружается...