Моя установка:
Сервер .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, но не мог понять, что не так.