是否有人使用 ubuntu 18.04 在 docker 中使用 gRPC 服务器在微服务中部署了 .NET Core

Dev*_*ngh 4 docker .net-core grpc kestrel-http-server asp.net-core

我有两个带有普通 Web API 和 gRPC 服务的 .net 核心微服务(PatientService 和 AppointmentService)。我使用 gRPC 进行服务间通信,而不是使用 HTTP 调用。

预约服务依赖于患者服务的数据,这意味着当我点击预约服务的端点以获取预约时,我需要来自患者服务的患者信息,因此我使用 gRPC 进行此调用。

现在我的应用程序运行良好,我能够在两者之间进行通信,而无需在本地环境中使用 kestrel 做任何额外的事情。但是当我在 Docker 中运行相同的应用程序时,该应用程序没有运行,我无法访问 HTTP1 和 HTTp2 端口。我正在运行 Linux 容器。

我的问题是如何在 .net 核心应用程序中运行 HTTP1 和 HTTP2?如何使用grpc在.net微服务中进行服务间通信?

如何使用 Linux 容器(Ubuntu 18.04)在 docker 中运行 .net core web API + gRPC 服务?如何在没有 TLS 的情况下运行 gRPC?

请帮助我已经尝试了一切,但我被卡住了。我有这个重要的版本要发布。

Docker 文件。

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
RUN sed -i 's/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/g' /etc/ssl/openssl.cnf
RUN sed -i 's/MinProtocol = TLSv1.2/MinProtocol = TLSv1/g' /etc/ssl/openssl.cnf
RUN sed -i 's/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/g' /usr/lib/ssl/openssl.cnf
RUN sed -i 's/MinProtocol = TLSv1.2/MinProtocol = TLSv1/g' /usr/lib/ssl/openssl.cnf
WORKDIR /app
EXPOSE 80
EXPOSE 6002
EXPOSE 443
EXPOSE 5001
EXPOSE 6001
#our sql server was use this port for connect
EXPOSE 7007

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

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

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

Run Code Online (Sandbox Code Playgroud)

Ale*_* Cr 6

我找到了一个对我有用的解决方案,我只用了 3 周就搞定了。

有3个主要问题:

  1. Docker 暴露端口
  2. 红隼配置
  3. 客户端通道配置

应该在 appsetting.json 或程序 cs 中使用以下参数设置 Kestrel:

  "Kestrel": {
    "EndPoints": {
      "Grpc": {
        "Url": "http://*:8080",
        "Protocols": "Http2"
      },
      "webApi": {
        "Protocols": "Http1",
        "Url": "http://*:80"
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

或者

ConfigureKestrel(options =>
                {
                    options.ListenAnyIP(80, listenOptions => listenOptions.Protocols = HttpProtocols.Http1); //webapi
                    options.ListenAnyIP(8080, listenOptions => listenOptions.Protocols = HttpProtocols.Http2); //grpc
                })
Run Code Online (Sandbox Code Playgroud)

完成此设置后,您可以使用以下命令启动 docker(端口和 ip 可能会有所不同,请确保没有其他东西在监听这些端口 ips):

docker run -p 127.0.0.40:8080:80 -p 127.0.0.40:8081:8080 --env ASPNETCORE_ENVIRONMENT=Development -it my_project -e ASPNETCORE_ENVIRONMENT=Development -e ASPNETCORE_URLS=http://+
Run Code Online (Sandbox Code Playgroud)

在此之后,您必须配置您的频道(不要使用 Grpc.AspNetCore 中的“.AddGrpcClient”扩展名):

services.AddSingleton(x =>
                        {
                            AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
                            return GrpcChannel.ForAddress("127.0.0.40:8081",
                                //TODO:GRPC Root SSL Creds
                                channelOptions: new GrpcChannelOptions()
                                {
                                    Credentials = ChannelCredentials.Insecure
                                });
                        });
Run Code Online (Sandbox Code Playgroud)

在此之后,您可以根据自己的意愿使用您创建的频道创建您的客户,无论您想做什么都应该没问题。没有其他方法对我有用。

更新: 我找到了一种方法让它与 Grpc.AspNetCore 的“AddGrpcClient”一起工作。

services.AddGrpcClient<ControllerGuide.GuideClient>(
(x, opt) =>
{
    AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
    opt.Address = new Uri("UriGRPC:5001");
    opt.ChannelOptionsActions.Add(act =>
    {
        act.Credentials = ChannelCredentials.Insecure;
    });
});
Run Code Online (Sandbox Code Playgroud)