【问题标题】:c# Grpc Client Not able to connect to Grpc Server hosted in docker(for windows) container on localhostc# Grpc Client 无法连接到本地主机上 docker(for windows) 容器中托管的 Grpc 服务器
【发布时间】:2019-02-26 12:28:12
【问题描述】:

我和一个客户一起做了一个简单的Grpc Greeter Service。当服务托管在 localhost 上时,客户端能够调用 rpc 并接收响应。但是当服务在本地主机上的 docker 容器内运行时,客户端无法连接到服务。

** Grpc 服务服务器 **

namespace GreeterServer
{
    class Program
    {
        private readonly static ManualResetEvent shutdown = new ManualResetEvent(false);
        static void Main(string[] args)
        {
            int port = 5000;
            Console.WriteLine("Hello World!");
            Server server = new Server{
                Services = {GreeterService.BindService(new GreeterController())},
                Ports = {new ServerPort("localhost", port, ServerCredentials.Insecure)}
            };
            server.Start();
            Console.WriteLine("Grpc Server started");
            Console.Read();
            shutdown.WaitOne();
        }
    }
}

** Grpc 服务的 Dockerfile **

FROM microsoft/dotnet:2.1-sdk as base
WORKDIR /app

COPY *.csproj .
RUN dotnet restore

COPY . .
RUN dotnet build -c Release -o out

FROM microsoft/dotnet:2.1-runtime
WORKDIR /app
COPY --from=base /app/out .
ENTRYPOINT ["dotnet", "GreeterServer.dll"]
EXPOSE 5000

** Grpc 客户端 **

namespace GreeterClient
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Hello World!");
                Channel channel = new Channel("127.0.0.1:5000", ChannelCredentials.Insecure);
                GreeterService.GreeterServiceClient client = new GreeterService.GreeterServiceClient(channel);
                HelloRequest request = new HelloRequest
                {
                    Message = "Hi From Client"
                };
                HelloResponse response = client.SayHello(request);
                Console.WriteLine(response.Message);
            }
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
            }

        }
    }
}

** 来自 Grpc 客户端的 Stacktrace **

Grpc.Core.RpcException: Status(StatusCode=Unknown, Detail="Stream removed")
   at Grpc.Core.Internal.AsyncCall`2.UnaryCall(TRequest msg) in T:\src\github\grpc\src\csharp\Grpc.Core\Internal\AsyncCall.cs:line 75
   at Grpc.Core.DefaultCallInvoker.BlockingUnaryCall[TRequest,TResponse](Method`2 method, String host, CallOptions options, TRequest request) in T:\src\github\grpc\src\csharp\Grpc.Core\DefaultCallInvoker.cs:line 46
   at Grpc.Core.Interceptors.InterceptingCallInvoker.<BlockingUnaryCall>b__3_0[TRequest,TResponse](TRequest req, ClientInterceptorContext`2 ctx) in T:\src\github\grpc\src\csharp\Grpc.Core\Interceptors\InterceptingCallInvoker.cs:line 51
   at Grpc.Core.ClientBase.ClientBaseConfiguration.ClientBaseConfigurationInterceptor.BlockingUnaryCall[TRequest,TResponse](TRequest request, ClientInterceptorContext`2 context, BlockingUnaryCallContinuation`2 continuation) in T:\src\github\grpc\src\csharp\Grpc.Core\ClientBase.cs:line 174
   at Grpc.Core.Interceptors.InterceptingCallInvoker.BlockingUnaryCall[TRequest,TResponse](Method`2 method, String host, CallOptions options, TRequest request) in T:\src\github\grpc\src\csharp\Grpc.Core\Interceptors\InterceptingCallInvoker.cs:line 48
   at Greeter.Proto.GreeterService.GreeterServiceClient.SayHello(HelloRequest request, CallOptions options) in F:\c#\GrpcPracticeWithDocker\GreeterClient\GrpcClasses\GreeterGrpc.cs:line 70
   at Greeter.Proto.GreeterService.GreeterServiceClient.SayHello(HelloRequest request, Metadata headers, Nullable`1 deadline, CancellationToken cancellationToken) in F:\c#\GrpcPracticeWithDocker\GreeterClient\GrpcClasses\GreeterGrpc.cs:line 66
   at GreeterClient.Program.Main(String[] args) in F:\c#\GrpcPracticeWithDocker\GreeterClient\Program.cs:line 23

【问题讨论】:

    标签: c# docker microservices grpc


    【解决方案1】:

    我遇到了同样的问题。但最后它与代理配置有关。 GRPC 使用“HTTP_PROXY”和“HTTPS_PROXY”环境配置。不幸的是,我的 grpc 服务器在不需要代理的本地网络上运行。我错过了定义“NO_PROXY”环境变量。

    一旦我将 grpc 服务器 ip 添加到 NO_PROXY 中,它就开始工作了。

    注意:

    1. 我可以让 docker 只使用“localhost”。我没有将我的 grpc 服务器绑定到“0.0.0.0”
    2. 我通过启用 GRPC 跟踪日志来诊断问题。启用跟踪后,您必须使用以下代码将日志显示到控制台中。

    参考:https://github.com/grpc/grpc/blob/master/TROUBLESHOOTING.md

    GrpcEnvironment.SetLogger(new ConsoleLogger());
    

    【讨论】:

    • 添加NO_PROXY环境变量的语法为:Environment.SetEnvironmentVariable("NO_PROXY", "localhost")
    【解决方案2】:

    (1) 不要在 docker 内的 GRPC 服务器中使用 localhost,因为无法从 docker 外部访问环回 localhost,所以它不起作用,你需要监听所有接口,所以使用“0.0.0.0”,例如。

    Ports = {new ServerPort("0.0.0.0", port, ServerCredentials.Insecure)}

    这里是一个引用这个问题的堆栈:Cannot connect to Go GRPC server running in local Docker container

    (2) 我也有同样的问题。我发现问题是我在使用 docker run 或 docker compose 时没有使用交互式 shell。如果您使用的是 docker run,那么您需要使用 -it 命令,而对于 docker compose,您需要使用 stdin_open: true 和 tty:true。

    Docker 运行示例

    docker run --name grpcserver -p 8081:8081 -it -d grpcserver
    

    Docker 组合示例

    version: '3'
    
    services:
      web:
        container_name: mynginx
        build:
          context: ./nginx
          dockerfile: Dockerfile
        ports:
          - 8080:80
      grpcserver:
        image: grpcserver
        container_name: grpcserver
        stdin_open: true
        tty: true
        build:
          context: .
          dockerfile: Dockerfile
    

    这是另一个讨论这个问题的堆栈: Interactive shell using Docker Compose

    祝你好运!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-12
      • 2017-10-10
      • 2020-10-19
      • 2022-01-06
      • 1970-01-01
      • 2021-12-18
      • 2021-07-16
      相关资源
      最近更新 更多