gRPC вернул HTTP 200, но вызов завершился ошибкой: что проверить

HTTP 200 не гарантирует успех gRPC-вызова. Порядок проверки итогового статуса, клиента и прокси с критериями исправления.

HTTP 200 в журнале прокси не гарантирует успешный gRPC-вызов. Проверьте итоговый статус у gRPC-клиента: код OK (0) означает успешное завершение RPC, остальные коды требуют разбора.

Сначала сопоставьте один проблемный вызов в клиенте, прокси и приложении, затем повторите безопасный запрос тем же методом. Так можно отличить отказ приложения от потери завершающих метаданных или тайм-аута по пути.

Почему 200 и ошибка не противоречат друг другу

В обычном gRPC поверх HTTP/2 есть два результата: HTTP-статус и статус самого RPC. Согласно описанию протокола gRPC, итоговый grpc-status передаётся в trailers — метаданных, завершающих поток; при немедленной ошибке возможен ответ только с метаданными, без сообщения.

Поэтому строка 200 в access log описывает лишь часть обмена. Для потокового метода даже несколько полученных сообщений ещё не означают, что весь вызов завершился успешно. Если клиент не получил корректного завершения, отсутствие grpc-status нельзя считать нулевым кодом.

Это руководство относится к обычному gRPC поверх HTTP/2. У gRPC-Web и JSON-шлюза способ передачи результата другой: сначала уточните, какой протокол использует клиент.

1. Соберите результат одного вызова

Выберите конкретный случай и запишите:

  • время с часовым поясом, имя сервиса и метода;
  • адрес назначения, версию клиента и приложения;
  • HTTP-статус, если он доступен, итоговый gRPC-код и текст ошибки;
  • установленный deadline — срок ожидания вызова — и фактическую длительность;
  • идентификатор трассировки и число попыток, если они фиксируются.

Не объединяйте HTTP 200 одной попытки и ошибку другой. Повтор внутри клиентской библиотеки может скрыть первый отказ, а одинаковый метод — попасть на разные узлы.

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

2. Повторите безопасный RPC полноценным клиентом

Открытие адреса в браузере или curl -I не воспроизводит gRPC-вызов. Используйте штатный клиент либо grpcurl: инструмент вызывает RPC и показывает ответ и ошибку.

Пример для тестового сервиса с включённой server reflection, которая позволяет получить описание методов:

grpcurl -v -d '{}' api.example.com:443 example.v1.Diagnostics/Check

Адрес, метод и пустое сообщение здесь условные. Замените их на разрешённый метод чтения или диагностики с известным ожидаемым результатом; команда сама по себе не делает произвольный метод безопасным.

Если reflection отключена, используйте согласованный .proto или protoset, как описано в документации grpcurl. Отказ reflection ещё не доказывает отказ нужного RPC. Не отключайте проверку TLS ради успешного теста и не переносите рабочие секреты в команду или отчёт.

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

3. Выберите ветку по итоговому коду

Справочник gRPC задаёт смысл кодов. Практический порядок проверки такой:

| Результат | Что проверить сначала | | --- | --- | | UNAUTHENTICATED (16), PERMISSION_DENIED (7) | Личность клиента, передачу авторизационных метаданных, права на метод | | INVALID_ARGUMENT (3), FAILED_PRECONDITION (9) | Соответствие сообщения контракту и состояние объекта | | DEADLINE_EXCEEDED (4) | Бюджет времени клиента, очередь и длительность работы сервера | | UNAVAILABLE (14) | Доступность нужного узла, события релиза и сбои соединения | | INTERNAL (13), UNKNOWN (2) | Журнал приложения и клиента по тому же идентификатору |

Код задаёт направление, но не называет виновный компонент. Например, недоступность сервиса не доказывает, что весь хостинг упал.

После тайм-аута операции записи сначала выясните, выполнена ли она. Не включайте безусловные повторы платежа или создания заказа: безопасный повтор требует предусмотренной защиты от дублей.

4. Если итоговых метаданных нет, сравните участки пути

Нарисуйте цепочку клиент → балансировщик → прокси → gRPC-сервер. Для каждого узла проверьте поддержку gRPC, протокол до следующего узла, ограничения времени и запись завершения вызова.

В разрешённом тестовом контуре сравните один безопасный RPC через внешний адрес и напрямую к сервису. Сохраните сопоставимые TLS-настройки, имя назначения, метод и параметры; иначе тест будет проверять другую конфигурацию.

Если напрямую вызов завершается, а через прокси обрывается, изучайте этот участок: тайм-аут, сброс потока, передачу trailers. При связи с выкладкой пригодится отдельная проверка завершения HTTP/2-запросов при релизе.

Как подтвердить исправление и продолжить контроль

Повторите исходный безопасный сценарий: клиент должен получить ожидаемые данные и корректное завершение RPC. Отдельно проверьте контролируемую ошибку: она должна оставаться видимой как ошибка, даже если HTTP-журнал показывает 200.

Для регулярного контроля разделите доступность публичной HTTP-точки и результат конкретного RPC. Web-Puls можно использовать для HTTP-проверки выбранного URL; чтение gRPC trailers и выполнение RPC такая проверка не подтверждает. Общие критерии выбора точки разобраны в руководстве по мониторингу API.

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

Проверьте свой сайт прямо сейчас

Введите адрес сайта: Web-Puls покажет HTTP-код, время ответа и базовую диагностику. Для постоянного контроля можно подключить мониторинг.

Нужна помощь с диагностикой ошибки?

Опишите симптомы в короткой заявке: URL, код ответа, время появления и что менялось перед сбоем. Специалист поддержки оценит задачу и предложит формат работ.