首页 > 解决方案 > 无法连接到 Docker 中托管的网络核心 gRPC 服务

问题描述

我对 gRPC 服务比较陌生。

我正在尝试将Net core gRPC 服务部署到 Linux docker 容器中,并从VS 控制台应用程序本地访问它。

我想让事情尽可能简单,因此 docker 文件与 VS 中 docker compose 指向的 Net core gRPC docker 文件相同。当直接在 VS 中运行 gRPC 服务时,控制台应用程序可以访问该服务,只是不能在 docker 容器中访问。

gRPC 启动设置

{
  "profiles": {
    "TrafficGrpc": {
      "commandName": "Project",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "https://localhost:5001"
    },
    "Docker": {
      "commandName": "Docker",
      "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
      "publishAllPorts": true,
      "useSSL": true
    }
  }
}

gRPC 应用设置

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http2"
    }
  }
}

码头工人文件

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["gRPC/TrafficGrpc/TrafficGrpc.csproj", "TrafficGrpc/"]
RUN dotnet restore "TrafficGrpc/TrafficGrpc.csproj"
COPY . .
WORKDIR "/src/gRPC/TrafficGrpc"
RUN dotnet build "TrafficGrpc.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "TrafficGrpc.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "TrafficGrpc.dll"]

码头工人撰写文件

version: "3.7"
services:

  # Traffic service
  traffic:
    container_name: traffic
    build:
      context: .
      dockerfile: Dockerfile-traffic
    networks:
      grpc_network:
    environment:
      - SERVICE_NAME=1
    expose:
      - "80"
      - "443"
    ports:
      - "0.0.0.0:32773:80"
      - "0.0.0.0:32774:443"
      
networks:
  grpc_network:

控制台应用程序,VS

string trafficUrl = "http://localhost:32773";
//string trafficUrl = "https://localhost:32774";

Traffic traffic = new Traffic
{
    Date = DateTime.Now.AddDays(1),
    Area = Areas[rng.Next(Areas.Length)],
    Condition = Conditions[rng.Next(Conditions.Length)]
};

GrpcChannel tChannel = GrpcChannel.ForAddress(trafficUrl);
TrafficCheckerClient tClient = new TrafficCheckerClient(tChannel);
TrafficConditionResponse tReply = await tClient.CheckTrafficConditionAsync(
    new TrafficConditionRequest { Condition = traffic.Condition }); // <-- ERROR here

运行 docker-compose 文件后,控制台应用程序无法连接到 gRPC。

使用http,我得到这个错误:

Grpc.Core.RpcException
  HResult=0x80131500
  Message=Status(StatusCode=Internal, Detail="Error starting gRPC call. HttpRequestException: An error occurred while sending the request. IOException: The response ended prematurely.")
  Source=System.Private.CoreLib
  StackTrace:
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at ConsoleTestgRPC.Program.<Main>d__5.MoveNext() in D:\Workspace-GW-EV\CL\ConsoleTestgRPC\Program.cs:line 61

使用 https,我收到此错误:

Grpc.Core.RpcException
  HResult=0x80131500
  Message=Status(StatusCode=Internal, Detail="Error starting gRPC call. HttpRequestException: The SSL connection could not be established, see inner exception. IOException: Authentication failed because the remote party has closed the transport stream.")
  Source=System.Private.CoreLib
  StackTrace:
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at ConsoleTestgRPC.Program.<Main>d__5.MoveNext() in D:\Workspace-GW-EV\CL\ConsoleTestgRPC\Program.cs:line 61

此时,我不知道是docker网络还是gRPC配置问题。

我需要帮助来指引我正确的方向。

谢谢你

标签: c#docker.net-coregrpc

解决方案


我今天遇到了熟悉的问题。

您在 dockerfile 中设置了 EXPOSE 80,因此您需要让 grpc 监听绑定到它的端口。

所以在我的例子中,grpc 监听 8099,并将其暴露给主机端口:32812,然后客户端创建通道给它。它工作。

在 dockerfile 中:

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 8099
EXPOSE 443

在服务器监听端口:

public static IWebHostBuilder CreateHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .ConfigureKestrel(options =>
                {
                    options.ListenAnyIP(
                        8099,
                        listenOptions => { listenOptions.Protocols = HttpProtocols.Http2; }
                    );
                })
                .UseStartup<Startup>();

在客户端创建通道:

GrpcClientFactory.AllowUnencryptedHttp2 = true;

using var http = GrpcChannel.ForAddress("http://localhost:32812");

绑定端口

希望对你有帮助,祝你好运~


推荐阅读