# #http #go #grpc #http2 #grpc-gateway
Вопрос:
Итак, у меня есть служба grpc в Golang, и я хочу предоставить HTTP API поверх нее, поэтому я добавил grpc-шлюз в службу.
Когда я пытаюсь сделать HTTP-запрос к своей службе, он завершается со странной ошибкой 500 Internal Server Error caused by: stream error: stream ID 19; PROTOCOL_ERROR
Это происходит сразу после того, как балансировщик нагрузки перенаправляет запрос на порт http (порт, на котором работает grpc-шлюз)
Это грубая ошибка, запросы в большинстве случаев терпят неудачу, но иногда запросы проходят без ошибок
глядя на запрос в браузере, я вижу, что когда запрос отправляется с интерфейса, он добавляет этот заголовок TE: trailers
и в соответствии с комментарием к этой теме https://github.com/golang/go/issues/29125#issuecomment-676831990 заголовок TE может вызвать эту проблему. Поэтому я попытался удалить заголовок TE с помощью промежуточного программного обеспечения traefik, но даже это не решило проблему, даже после удаления заголовка до того, как он попадет в порт http, запрос все равно завершится с той же ошибкой.
затем я включил GODEBUG=http2debug=2
и нашел это в журналах
http2: Framer 0xc000272e00: read HEADERS flags=END_HEADERS stream=5 len=29
http2: decoded hpack field header field ":authority" = "dev-env.something.com"
http2: decoded hpack field header field ":method" = "POST"
http2: decoded hpack field header field ":path" = "/v1/someAPI/Create"
http2: decoded hpack field header field ":scheme" = "http"
http2: decoded hpack field header field "x-forwarded-host" = "dev-env.something.com"
http2: decoded hpack field header field "x-forwarded-port" = "443"
http2: decoded hpack field header field "sec-fetch-dest" = "empty"
http2: decoded hpack field header field "x-forwarded-for" = "XX.XXX.XXX.X"
http2: decoded hpack field header field "sec-fetch-mode" = "cors"
http2: decoded hpack field header field "accept" = "application/json, text/plain, */*"
http2: decoded hpack field header field "te" = "trailers"
http2: decoded hpack field header field "x-real-ip" = "XX.XXX.XXX.X"
http2: decoded hpack field header field "user-agent" = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0"
http2: decoded hpack field header field "accept-encoding" = "gzip, deflate, br"
http2: decoded hpack field header field "sec-fetch-site" = "same-origin"
http2: decoded hpack field header field "referer" = "https://dev-env.something.com/"
http2: decoded hpack field header field "x-forwarded-proto" = "https"
http2: decoded hpack field header field "accept-language" = "en-US,en;q=0.5"
http2: decoded hpack field header field "x-forwarded-server" = "traefik-xxxxxxxxxxx"
http2: decoded hpack field header field "origin" = "https://dev-env.something.com"
http2: decoded hpack field header field "content-type" = "application/json"
http2: decoded hpack field header field "content-length" = "12"
http2: Framer 0xc000272e00: read DATA flags=END_STREAM stream=3 len=12 data="{"name":"test"}"
http2: Framer 0xc000272e00: wrote RST_STREAM stream=3 len=4 ErrCode=PROTOCOL_ERROR
http2: Framer 0xc000272e00: wrote WINDOW_UPDATE len=4 (conn) incr=12
http2: Framer 0xc000272e00: wrote PING len=8 ping="x02x04x10x10tx0eaa"
http2: Framer 0xc000272e00: read SETTINGS flags=ACK len=0
http2: Framer 0xc000272e00: read PING flags=ACK len=8 ping="x02x04x10x10tx0eaa"
Теперь даже журналы не очень полезны, либо это, либо я не знаю, как их читать, и мне не хватает чего-то очевидного
Запрос на завиток имеет форму curl -X POST -H "Content-Type: application/json" "https://domain.name.com/v1/someAPI/Create" -d "{"name": "test" }"
Может кто-нибудь сказать мне, что не так, это ошибка в stdlib? Если нет, все равно было бы очень полезно, если бы кто-нибудь мог сказать мне, как читать журналы http2 или где искать источник этих журналов в стандартной библиотеке
Ответ №1:
Так что никакой ошибки в стандартной библиотеке не было, это была человеческая ошибка. Неправильная конфигурация балансировщика нагрузки в половине случаев направляла http-запрос на сервер grpc, а в остальных случаях-на сервер http (сервер grpc и обратный прокси-сервер grpc-шлюза обслуживались на разных портах).
Всякий раз, когда запрос попадает на сервер grpc, он принимает запрос, потому что сервер grpc работает на сервере H2C, но он не смог его перевести, что привело к ошибке.