c#Grpc客户端无法连接到本地主机上docker(for windows)容器中托管的Grpc服务器

c#Grpc客户端无法连接到本地主机上docker(for windows)容器中托管的Grpc服务器,c#,docker,microservices,grpc,C#,Docker,Microservices,Grpc,我和一位客户一起做了一个简单的Grpc迎宾服务。当服务托管在localhost上时,客户端能够调用rpc并接收响应。但是,当服务在localhost上的docker容器内运行时,客户端无法连接到该服务 **Grpc服务服务器** namespace GreeterServer { class Program { private readonly static ManualResetEvent shutdown = new ManualResetEvent(fals

我和一位客户一起做了一个简单的
Grpc迎宾服务
。当服务托管在localhost上时,客户端能够调用rpc并接收响应。但是,当服务在localhost上的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.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
**来自Grpc客户端的Stacktrace**

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.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
Grpc.Core.RpcException:Status(StatusCode=Unknown,Detail=“流已删除”)
在T:\src\github\Grpc\src\csharp\Grpc.Core\Internal\AsyncCall.cs中的Grpc.Core.Internal.AsyncCall`2.UnaryCall(TRequest msg):第75行
在T:\src\github\Grpc\src\csharp\Grpc.Core\DefaultCallInvoker.BlockingUnaryCall[TRequest,treresponse](方法'2,字符串主机,调用选项,TRequest请求)中的Grpc.Core.DefaultCallInvoker.BlockingUnaryCall中:第46行
在T:\src\github\Grpc\src\csharp\Grpc.Core\Interceptors\Interceptors\interceptorcontext`2 ctx中的Grpc.Core.Interceptors.InterceptingCallInvoker.b_uu3_0[TRequest,treresponse](TRequest-req,ClientInterceptorContext`2 ctx)处
在T:\src\github\Grpc\src\csharp\Grpc.Core\ClientBase.cs中的Grpc.Core.ClientBase.ClientBaseConfigurationInterceptor.BlockingUnaryCall[TRequest,treresponse](TRequest请求,ClientInterceptorContext`2 context,BlockingUnaryCallContinuation`2 continuation)处
在T:\src\github\Grpc\src\csharp\Grpc.Core\Interceptors\csharp\Grpc.Core\Interceptors\InterceptingCallInvoker.cs第48行的Grpc.Core.InterceptingCallInvoker.BlockingUnaryCall[TRequest,treresponse](方法'2,字符串主机,CallOptions选项,TRequest请求)
在F:\c#\GrpcPracticeWithDocker\GreeterClient\GRPClasses\GreeterGrpc.cs第70行的Greeter.Proto.GreeterService.GreeterServiceClient.SayHello(HelloreRequest请求,CallOptions选项)中
在F:\c#\GRPCPractice with Docker\GreeterClient\GRPClasses\GreeterGrpc.cs第66行中的Greeter.Proto.GreeterService.GreeterServiceClient.SayHello(HelloRequest请求,元数据头,可为空的'1截止日期,CancellationToken CancellationToken)
在F:\c#\GrpcPracticeWithDocker\GreeterClient\Program.cs中的GreeterClient.Program.Main(字符串[]args)处:第23行
(1)不要在docker内部的GRPC服务器中使用localhost,它不会工作,因为无法从docker外部访问环回localhost,您需要监听所有接口,因此请使用“0.0.0.0”,例如

端口={new ServerPort(“0.0.0.0”,端口,ServerCredentials.unsecure)}

以下是一个涉及此问题的堆栈:

(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
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
Docker编写示例

docker run --name grpcserver -p 8081:8081 -it -d grpcserver
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
下面是另一个讨论这一点的堆栈:


祝你好运

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

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

注:

  • 我可以让docker只使用“localhost”。我尚未将grpc服务器绑定到“0.0.0.0”
  • 我通过启用GRPC跟踪日志来诊断问题。启用跟踪后,必须使用以下代码将日志显示到控制台中
  • 参考:


    添加NO_PROXY Environment变量的语法是:Environment.SetEnvironmentVariable(“NO_PROXY”、“localhost”)