当前位置: 首页 > 知识库问答 >
问题:

gRPC无法连接到所有地址,或服务的DNS解析失败

昌正奇
2023-03-14

我目前正试图获得一个gRPC工作的例子。我使用C # Asp.NET核心WebApi作为服务器,并尝试通过Python客户端连接到它。

我的原始文件:

syntax = "proto3";

service Example {
  rpc Insert (InsertRequest) returns (Empty);
  rpc Update (UpdateRequest) returns (Empty);
  rpc Delete (DeleteRequest) returns (Empty);
}

message InsertRequest {
    int32 Value = 1;
}

message UpdateRequest {
  string Id = 1;
  int32 Value = 2;
}

message DeleteRequest {
  string Id = 1;
}

message Empty { }

Python客户端:

import grpc

import example_pb2
import example_pb2_grpc

with grpc.insecure_channel('localhost:5001') as channel:
    stub = example_pb2_grpc.ExampleStub(channel)
    stub.Insert(example_pb2.InsertRequest(Value = 155))

当我尝试运行我的Python客户端时,我收到以下错误:

Traceback(最近一次调用last):存根中文件“gRPCExampleClient.py”的第10行。插入(example_pb2。InsertRequest(Value = 155))文件“C:\ python 38 \ lib \ site-packages \ grpc _ channel . py”,第923行,在调用return _ end _ unary _ response _ blocking(state,call,False,None)文件“C:\ python 38 \ lib \ site-packages \ grpc _ channel . py”,第826行,in _ end _ unary _ response _ blocking raise _ InactiveRpcError(state)grpc。_频道。_InactiveRpcError:

  • 为我的 Kestrel 服务器显式启用 HTTP/2
  • 已验证服务器是否正在使用C# gRPC客户端
    • C# 客户端使用与 Python 客户端相同的原型文件(C# 客户端按预期工作,并且可以与服务器通信)
        class Program
        {
            static void Main(string[] args)
            {
                var channel = GrpcChannel.ForAddress("https://localhost:5001");
                var client = new Example.ExampleClient(channel);
    
                client.Insert(new InsertRequest() { Value = 155 });
    
                Console.ReadKey(true);
            }
        }
    
    • 尝试在我的Python客户端中使用“https://”方案(与grpc.unsecure_channel('https://localhost:5001')作为频道:)。执行此操作时,我会收到以下错误消息

    Traceback(最近一次调用last):存根中文件“gRPCExampleClient.py”的第10行。插入(example_pb2。InsertRequest(Value = 155))文件“C:\ python 38 \ lib \ site-packages \ grpc _ channel . py”,第923行,在调用return _ end _ unary _ response _ blocking(state,call,False,None)文件“C:\ python 38 \ lib \ site-packages \ grpc _ channel . py”,第826行,in _ end _ unary _ response _ blocking raise _ InactiveRpcError(state)grpc。_频道。_InactiveRpcError:

    • 之后,我尝试将环境变量<code>GRPC_DNS_RESOLVER。遗憾的是,错误仍然存在
    from os import environ
    
    environ["GRPC_DNS_RESOLVER"] = "native"
    
    • 尝试使用 127.0.0.10.0.0.0,带或不带 https:// 方案而不是本地主机
    • 根据 https://html" target="_blank">github.com/grpc/grpc-dotnet/issues/959#issuecomment-647935019 在不指定任何方案时,gRPC 会将 dns:// 作为默认值。我能够通过启用environ[“GRPC_TRACE”] = “api,client_channel_routing,cares_resolver”environ[“GRPC_VERBOSITY”] = “debug”来确认这一点。
      • -

      我希望我只是错过了一些明显的感谢阅读和考虑帮助。

共有2个答案

黎鹤轩
2023-03-14

请参阅 https://github.com/grpc/grpc/blob/master/doc/naming.md

"https"的用法不正确

杨乐意
2023-03-14

我终于想通了。根本问题是我的服务器配置不匹配。由于C#客户端会自动检测dotnet设置 ASP.NET 核心开发证书,因此它将能够安全地连接到服务器。所有其他脚本语言(如python和go)将无法执行此操作并拒绝连接,因为无法验证证书。(这是完全正确的,它仍然只是一个用于调试的自签名证书)

简而言之:您不能不安全地连接到gRPC服务器,除非它被明确地设置为通过http/2服务不安全的HTTP请求。

因此,我们现在有两个选择:

  1. 显式为我们的脚本客户端提供证书公钥,以便他们知道他们可以信任我们的服务器
  2. 使用HTTP/2以非SSL模式启动我们的服务器

为了导出我的ASP.NET核心开发证书,我使用了< code>certmgr。使用这个工具,我们可以将dev证书的公钥部分导出为一个. cer文件。此后,我们只需告诉我们的客户端建立一个安全连接,并根据我们刚刚导出的公钥进行验证:

with open('../dev-cert.cer', 'rb') as f: #manually import public key of localhost ASP.NET Core dev certioficate (exported with certmgr)
        credentials = grpc.ssl_channel_credentials(f.read())
with grpc.secure_channel('localhost:5001', credentials) as channel:
    stub = example_pb2_grpc.ExampleStub(channel)
    stub.Insert(example_pb2.InsertRequest(Value = 155))

我还在go中测试了所有这些(以验证这不仅仅是python库问题)

func main() {
    creds, err := credentials.NewClientTLSFromFile("../dev-cert.cer", "")
    if err != nil {
        log.Fatalf("could not process the credentials: %v", err)
    }

    conn, err := grpc.Dial("localhost:5001", grpc.WithTransportCredentials(creds))

    if err != nil {
        log.Fatalf("did not connect: %s", err)
    }
    defer conn.Close()

    request := example_grpc_client.InsertRequest{
        Value: 123,
    }

    client := example_grpc_client.NewExampleClient(conn)

    _, err = client.Insert(context.Background(), &request)
    if err != nil {
        log.Fatalf("error sending message: %s", err)
    }
}

这是我找到的第一个解决方案,但我不建议使用它,因为它只是一种解决方法。通过配置我的服务器应用程序,我能够通过配置kestrel以HTTP/2启动不安全的连接支持来获得不安全的连接:

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.ConfigureKestrel(options => 
                    {
                        options.ListenLocalhost(5001, o => o.Protocols = HttpProtocols.Http2);
                    });

                    webBuilder.UseStartup<Startup>();
                });
 类似资料:
  • 我在. net核心项目中一直在使用GCP SecManager,当访问GCP中的一个秘密时,它会抛出一个错误 Grpc.Core。RPCEException:“状态(StatusCode=”不可用“,Detail=”无法连接到所有地址“,DebugException=”Grpc.Core.Internal.CoreErrorDetailException:“{”已创建“@1621849302.01

  • 我正在使用使用HTTPS和自签名证书托管的GRPC服务。当我使用以下语法连接时: 我得到这样的错误 任何人帮助我如何解决这个问题。 注意:我的操作系统是Windows 10,nodejs--v10.16.0,GRPC

  • 在我的应用程序中,我可以使用IP地址连接到服务器,但当我尝试使用DNS主机名连接时,我无法通过Android emulator连接。在logcat中,我得到以下错误: 07-10 10:22:42.312:我/编导(848):跳过了45帧!应用程序可能在其主线程上做了太多工作。 07-10 10:24:00.181:我/编导(848):跳过了35帧!应用程序可能在其主线程上做了太多工作。 07-1

  • 问题内容: 我有去grpc服务。我正在开发Mac,塞拉利昂。在本地针对服务运行grpc客户端时,一切都很好,但是在Docker容器中针对相同服务运行相同的客户端时,出现此错误: 这是我的docker文件: 我的命令来建立图像: 我的命令启动Docker容器: 其他资讯: 客户端程序可以在Docker容器中正常运行 连接到常规的休息端点可以正常工作(http2,与grpc相关吗?) 在OS X中运行

  • 我有go grpc服务。我在mac电脑上开发,塞拉。当针对本地服务运行grpc客户机时,一切都很好,但当针对docker容器中的相同服务运行相同客户机时,我会出现以下错误: 下面是我的服务器代码片段:

  • $kubectl版本 客户端版本:Version.info{Major:“1”,Minor:“13”,GitVersion:“V1.13.3”,GitCommit:“721BFA751924DA8D1680787490C54B9179B1FED0”,GitTreEstate:“Clean”,BuildDate:“2019-02-01T20:08:12Z”,GoVersion:“Go1.11.5”,