1. Анатомия запроса: как Context Path и Ingress определяют маршрут в Kubernetes
Анатомия запроса: как Context Path и Ingress определяют маршрут в Kubernetes
Вы добавили префикс /aeqs-backend-preregistration к URL, и тест для /time_slots внезапно позеленел, вернув заветный статус 200 OK. Но стоило автотесту перейти к следующему шагу и отправить запрос на /reservation с тем же самым префиксом — система снова выбросила 404 Not Found. Почему одна и та же дверь открывается для первого запроса, но наглухо заперта для второго?
Чтобы ответить на этот вопрос и сузить зону поиска ошибки в задаче AEQS-49, нам нужно понять, как именно ваш HTTP-запрос путешествует от скрипта автотеста до конкретного метода в Java-коде.
Два уровня маршрутизации
Когда автотест выполняет команду curl, запрос не попадает в микросервис мгновенно. Он проходит через два независимых контроля пропуска: внешний (сетевой) и внутренний (аппликационный). Ошибка 404 может возникнуть на любом из них, и лечатся они совершенно по-разному.
!Схема маршрутизации запроса в Kubernetes
Уровень 1: Ingress — диспетчер кластера
В современной микросервисной архитектуре приложения живут внутри изолированных контейнеров (подов) в Kubernetes. Снаружи они недоступны. Чтобы ваш автотест мог «достучаться» до пода aeqs-backend-preregistration, на границе кластера стоит Ingress-контроллер.
Ingress работает как диспетчер в большом офисном здании. Он смотрит на доменное имя в вашем запросе (aeqs-backend-preregistration.dev.aeqs.corp.dev.vtb) и принимает решение, в какой именно под направить трафик.
> Ingress — это правило маршрутизации Kubernetes, которое управляет внешним доступом к сервисам в кластере, обычно на основе HTTP/HTTPS хостов и путей.
Если Ingress не знает указанного домена или базового пути, он сам вернет 404 Not Found. В этом случае запрос даже не дойдет до Java-приложения. В логах вашего пода будет абсолютно пусто.
Уровень 2: Context Path — коридор внутри приложения
Допустим, Ingress пропустил запрос и доставил его прямо в под aeqs-backend-preregistration. Здесь в игру вступает сам фреймворк Spring Boot.
По умолчанию Spring Boot ожидает, что пути запросов начинаются от корня (/). То есть контроллер ждет путь /v1/api/time_slots. Однако в конфигурации вашего пода (как вы обнаружили в логах) жестко задана переменная окружения:
CONTEXT_PATH=/aeqs-backend-preregistration
Context Path — это глобальный префикс для всего приложения. Если он задан, Spring Boot «переезжает» в этот виртуальный коридор. Теперь приложение игнорирует любые запросы, которые не начинаются с этого префикса.
Вот почему ваша Фаза 1 увенчалась успехом:
GET /v1/api/time_slots/aeqs-backend-preregistration. Такого пути я не знаю. Держи 404»./aeqs-backend-preregistration/v1/api/time_slots./v1/api/time_slots, нашел нужный метод и вернул 200 OK.Разбор парадокса AEQS-49
Теперь применим эти знания к вашей текущей проблеме с /reservation. У нас есть неоспоримый факт: метод /time_slots с новым URL работает корректно.
Что этот факт говорит нам о состоянии системы?
Running, приложение обрабатывает запросы./aeqs-backend-preregistration — это именно то, что ожидает Spring Boot.Из этого следует важнейший вывод для отладки: ошибка 404 при вызове /reservation генерируется не инфраструктурой (Kubernetes/Ingress), а самим приложением Spring Boot.
Ваш запрос успешно проходит диспетчера, заходит в нужный коридор Context Path, стучится в дверь контроллера, но Spring Boot по какой-то причине не может сопоставить этот конкретный запрос с Java-методом, отвечающим за бронирование.
Проверка гипотез
В вашем описании проблемы были выдвинуты отличные гипотезы. Давайте проверим их через призму того, что мы только что узнали:
| Гипотеза | Вердикт на основе архитектуры |
| :--- | :--- |
| Есть ли скрытая версия/префикс для бронирования? | Крайне маловероятно. Context Path применяется ко всему приложению целиком. Если бы префикс был другим, /time_slots тоже бы перестал работать. |
| Метод переехал в другой сервис (например, aeqs-ticket)? | Вполне возможно. Если логику вынесли в другой микросервис, Ingress всё равно доставит запрос в старый под (так как домен старый), но Spring Boot уже не найдет у себя этого метода и честно вернет 404. |
| Влияет ли отсутствие параметра userSession на маршрутизацию? | Да, это частая причина. В Spring Boot можно настроить маршрутизацию так, что метод контроллера активируется только если в запросе присутствует определенный параметр или заголовок. Если параметра нет — для Spring Boot этого маршрута не существует (снова 404). |
Мы локализовали проблему. Сеть и базовые настройки путей в порядке. Запрос находится внутри контейнера. В следующем шаге мы заглянем внутрь самого Spring Boot, чтобы понять, как он принимает решение отклонить запрос из-за отсутствующих параметров или несовпадения контрактов.