Рейтинг:0

gRPC через CloudFlare приводит к внутренней ошибке HTTP/2 с кодом 2

флаг ar

Моя установка:

Сервер .Net gRPC <-> Nginx <-> CloudFlare <-> клиент gRPC (C#/Python)

Мой сервер .Net gRPC настроен на поддержку незащищенного http2, прослушивание порта 50052:

webBuilder.UseStartup<StartupGrpc>().UseUrls($"http://*:50052");
webBuilder.ConfigureKestrel(serverOptions => { serverOptions.ConfigureEndpointDefaults(listenOptions => { listenOptions.Protocols = HttpProtocols.Http2; }); });

Nginx настроен на grpc_pass следующим образом:

сервер {
    имя_сервера grpc.mydomain.com;
    слушать 443 ssl http2;
    ssl_certificate /etc/nginx/cf_origin_ssl/mydomain.pem;
    ssl_certificate_key /etc/nginx/cf_origin_ssl/mydomain.key;

    прокси_кэш выключен;
 
    место расположения / {
        grpc_pass grpc://localhost:50052;   
    }
}

сервер {
    имя_сервера mydomain.com;
    слушать 443 ssl http2;
    ssl_certificate /etc/nginx/cf_origin_ssl/mydomain.pem;
    ssl_certificate_key /etc/nginx/cf_origin_ssl/mydomain.key;

    прокси_кэш выключен;
 
    место расположения / {
        proxy_pass локальный: 50051;   
    }
}

CloudFlare: Сеть/gRPC -> На, SSL/TLS -> Полный (строгий) (с сертификатами происхождения, созданными CloudFlare). Я протестировал, и мой веб-сервер в мой домен.com работал нормально. Однако вызовы gRPC из клиента gRPC .Net/C# возвращают:

Необработанное исключение. Grpc.Core.RpcException: Status(StatusCode="Unavailable", Detail="Ошибка при запуске вызова gRPC. IOException: запрос был прерван. Http2StreamException: сервер HTTP/2 сбросил поток. Код ошибки HTTP/2 "INTERNAL_ERROR" (0x2 ).", DebugException="System.IO.IOException: запрос был прерван.
 ---> System.Net.Http.Http2StreamException: сервер HTTP/2 сбросил поток. Код ошибки HTTP/2 «INTERNAL_ERROR» (0x2).
    --- Конец внутренней трассировки стека исключений ---
    в System.Net.Http.Http2Connection.ThrowRequestAborted (внутреннее исключение исключения)
    в System.Net.Http.Http2Connection.Http2Stream.CheckResponseBodyState()
    в System.Net.Http.Http2Connection.Http2Stream.TryReadFromBuffer (буфер Span`1, логическая частьOfSyncRead)
    в System.Net.Http.Http2Connection.Http2Stream.ReadDataAsync (буфер памяти 1, HttpResponseMessage responseMessage, CancellationToken CancellationToken)
    at Grpc.Net.Client.StreamExtensions.ReadMessageAsync[TResponse](Stream responseStream, вызов GrpcCall, десериализатор Func`2, String grpcEncoding, Boolean singleMessage, CancellationToken CancellationToken)
    at Grpc.Net.Client.Internal.GrpcCall`2.RunCall (запрос HttpRequestMessage, тайм-аут Nullable`1)")

Я также пытался сделать вызовы gRPC из Python и получил аналогичную ошибку:

Traceback (последний последний вызов):
    ...
    Файл "/home/user/miniconda/lib/python3.9/site-packages/grpc/_channel.py", строка 946, в __call__
    вернуть _end_unary_response_blocking (состояние, вызов, ложь, нет)
    Файл "/home/user/miniconda/lib/python3.9/site-packages/grpc/_channel.py", строка 849, в _end_unary_response_blocking
    поднять _InactiveRpcError (состояние)
    grpc._channel._InactiveRpcError: <_InactiveRpcError RPC, который завершился с:
    статус = Код Статуса. НЕДОСТУПЕН
    details = "не удалось подключиться ко всем адресам"
    debug_error_string = "{"created":"@1634609018.116476058","description":"Не удалось выбрать подканал","file":"src/core/ext/filters/client_channel/client_channel.cc","file_line":3158, "referenced_errors":[{"created":"@1634609018.116472621","description":"не удалось подключиться ко всем адресам","file":"src/core/lib/transport/error_utils.cc","file_line": 147,"grpc_status":14}]}"
    >

Во время обработки вышеупомянутого исключения произошло другое исключение:

Traceback (последний последний вызов):
    ...
    Файл "/home/user/miniconda/lib/python3.9/site-packages/grpc/_channel.py", строка 946, в __call__
    вернуть _end_unary_response_blocking (состояние, вызов, ложь, нет)
    Файл "/home/user/miniconda/lib/python3.9/site-packages/grpc/_channel.py", строка 849, в _end_unary_response_blocking
    поднять _InactiveRpcError (состояние)
    grpc._channel._InactiveRpcError: <_InactiveRpcError RPC, который завершился с:
    статус = Код Статуса. ВНУТРЕННИЙ
    details = "Получен RST_STREAM с кодом ошибки 2"
    debug_error_string = "{"created":"@1634609018.553728473","description":"Ошибка получена от однорангового узла ipv4:172.67.179.119:443","file":"src/core/lib/surface/call.cc"," file_line": 1069, "grpc_message": "Получен RST_STREAM с кодом ошибки 2", "grpc_status": 13}"
    >

В обоих случаях запросы gRPC прошли через CloudFlare, Nginx и достигли моего сервера gRPC (удаленные процедуры были выполнены). В журналах Nginx также сообщается с 200 код успеха:

116.110.42.123 - - [19/окт/2021:01:25:22 +0000] "POST /greet.Greeter/CsharpSayHello HTTP/2.0" 200 64 "-" "grpc-dotnet/2.40.0.0" "116.110.42.123 " "grpc.mydomain.com" sn="grpc.mydomain.com" rt=0,002 ua="127.0.0.1:50052" us="200" ut="0,000" ul="71" cs=-
116.110.42.123 - - [19/окт/2021:01:27:57 +0000] "POST /greet.Greeter/CsharpSayHello HTTP/2.0" 200 68 "-" "grpc-python/1.41.0 grpc-c/19.0 .0 (linux; chttp2)" "116.110.42.123" "grpc.mydomain.com" sn="grpc.mydomain.com" rt=0,001 ua="127.0.0.1:50052" us="200" ut="0,000 "ул="75" кс=-

Я много гуглил о CloudFlare gGRPC и Nginx, но не мог понять, что не так.

Ответить или комментировать

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