Skip to the content.

疑难解答

<- 返回索引

本节描述这个项目的一些常见错误,以及如何解决这些错误。 请注意,这个页面永远不能覆盖所有案件,还请搜索现有的 issures/PRs(打开和关闭状态的)。 如果对应的主题已经存在,请给我们留下评论/信息,以便我们知道你也会受到影响。 如果没有这样的主题,请随时打开本页底部描述创建一个的新主题。

目录

NoClassDefFoundError, ClassNotFoundException, NoSuchMethodError, AbstractMethodError

示例

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'client' defined in file [~/.../MyGrpcClient.class]: Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: io/grpc/TlsChannelCredentials$Feature
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602)
    [...]
Caused by: java.lang.NoClassDefFoundError: io/grpc/TlsChannelCredentials$Feature
    at io.grpc.netty.ProtocolNegotiators.<clinit>(ProtocolNegotiators.java:92)

问题

服务端/客户端未启动,因为缺少某些类或方法。 如果Grpc库使用不同的版本,通常就会出现这样的情况。

解决办法

确保所有 grpc-java 版本使用完全相同的版本。

将以下条目添加到您项目的 dependencyManagement 部分:

<dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-bom</artifactId>
    <version>${grpcVersion}</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

在 gradle 中你也可以使用类似的方法

dependencyManagement {
    imports {
        mavenBom "io.grpc:grpc-bom:${grpcVersion}"

注意: grpc-spring-boot-starter 并不严格绑定到 grpc-java 的特定版本。 这样你也可以使用此 方式来更改项目中使用的 grpc-java 版本。

同时也可以查看 找不到 TLS ALPN 提供商

传输失败

服务端

2019-07-07 10:05:46.217  INFO 6552 --- [-worker-ELG-3-5] i.g.n.s.i.g.n.N.connections              : Transport failed

io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2Exception: HTTP/2 client preface string missing or corrupt. Hex dump for received bytes: 16030100820100007e0303aae6126974cbb4638b325d6bdb
    at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2Exception.connectionError(Http2Exception.java:85) ~[grpc-netty-shaded-1.21.0.jar:1.21.0]
    at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler$PrefaceDecoder.readClientPrefaceString(Http2ConnectionHandler.java:318) ~[grpc-netty-shaded-1.21.0.jar:1.21.0]
    at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler$PrefaceDecoder.decode(Http2ConnectionHandler.java:251) ~[grpc-netty-shaded-1.21.0.jar:1.21.0]
    at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler.decode(Http2ConnectionHandler.java:450) [grpc-netty-shaded-1.21.0.jar:1.21.0]

客户端

io.grpc.StatusRuntimeException: UNAVAILABLE: io exception
    at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:235)
    at io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:216)
    at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:141)
    at net.devh.boot.grpc.examples.lib.SimpleGrpc$SimpleBlockingStub.sayHello(SimpleGrpc.java:178)
    [...]
Caused by: io.grpc.netty.shaded.io.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record: 00001204000000000000037fffffff000400100000000600002000000004080000000000000f0001
    at io.grpc.netty.shaded.io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1204)
    at io.grpc.netty.shaded.io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1272)
    at io.grpc.netty.shaded.io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:502)

问题

服务器运行在PLAINTEXT模式,但客户端试图在TLS(默认)模式中连接它。

简单的解决办法

将客户端配置在PLAINTEXT模式下连接(不推荐生产)。

添加以下条目到您的客户端应用程序配置:

grpc.client.__name__.negotiationType=PLAINTEXT

更好的解决办法

将服务端配置在TLS模式下运行(推荐)。

添加以下条目到您的服务端应用程序配置:

grpc.server.security.enabled=true
grpc.server.security.certificateChain=file:certificates/server.crt
grpc.server.security.privateKey=file:certificates/server.key

网络因未知原因关闭

客户端

io.grpc.StatusRuntimeException: UNAVAILABLE: Network closed for unknown reason

问题

您可能是 (1) 尝试通过 TLS 模式连接到 grpc-server 时,使用 PLAINTE 客户端 或 (2) 目标不是一个 grpc-server (例如 Web 服务)。

解决办法

  1. 配置您的客户端使用TLS模式。

    grpc.client.__name__.negotiationType=TLS
    

    或删除negotiationType配置,因为默认情况下TLS

  2. 使用 grpcurl 或类似工具,验证已配置的服务端正在运行的是 grpc 服务

找不到 TLS ALPN 提供商

服务端

org.springframework.context.ApplicationContextException: Failed to start bean 'nettyGrpcServerLifecycle'; nested exception is java.lang.IllegalStateException: Could not find TLS ALPN provider; no working netty-tcnative, Conscrypt, or Jetty NPN/ALPN available
    at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:185) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    [...]
Caused by: java.lang.IllegalStateException: Could not find TLS ALPN provider; no working netty-tcnative, Conscrypt, or Jetty NPN/ALPN available
    at io.grpc.netty.GrpcSslContexts.defaultSslProvider(GrpcSslContexts.java:258) ~[grpc-netty-1.21.0.jar:1.21.0]
    at io.grpc.netty.GrpcSslContexts.configure(GrpcSslContexts.java:171) ~[grpc-netty-1.21.0.jar:1.21.0]
    at io.grpc.netty.GrpcSslContexts.forServer(GrpcSslContexts.java:130) ~[grpc-netty-1.21.0.jar:1.21.0]
    [...]

客户端

[...]
Caused by: java.lang.IllegalStateException: Failed to create channel: <name>
    at net.devh.boot.grpc.client.inject.GrpcClientBeanPostProcessor.processInjectionPoint(GrpcClientBeanPostProcessor.java:118) ~[grpc-client-spring-boot-starter-2.4.0.RELEASE.jar:2.4.0.RELEASE]
    at net.devh.boot.grpc.client.inject.GrpcClientBeanPostProcessor.postProcessBeforeInitialization(GrpcClientBeanPostProcessor.java:77)
    [...]
Caused by: java.lang.IllegalStateException: Could not find TLS ALPN provider; no working netty-tcnative, Conscrypt, or Jetty NPN/ALPN available
    at io.grpc.netty.GrpcSslContexts.defaultSslProvider(GrpcSslContexts.java:258) ~[grpc-netty-1.21.0.jar:1.21.0]
    at io.grpc.netty.GrpcSslContexts.configure(GrpcSslContexts.java:171) ~[grpc-netty-1.21.0.jar:1.21.0]
    at io.grpc.netty.GrpcSslContexts.forClient(GrpcSslContexts.java:120) ~[grpc-netty-1.21.0.jar:1.21.0]
    [...]

两端

AbstractMethodError: io.netty.internal.tcnative.SSL.readFromSSL()

问题

classpath 上没有 (兼容) netty TLS 实现。

解决办法

grpc-netty切换到grpc-netty-shaded 或添加依赖于nety-tcnative-boringssl-static (请使用与grpc-java 的netty 安全性部分完全相同(兼容的版本))。

注意: 你需要一个 64 位的 Java 虚拟机。

证书不匹配

客户端

io.grpc.StatusRuntimeException: UNAVAILABLE: io exception
[...]
Caused by: javax.net.ssl.SSLHandshakeException: General OpenSslEngine problem
[...]
Caused by: java.security.cert.CertificateException: No subject alternative names present

io.grpc.StatusRuntimeException: UNAVAILABLE: io exception
[...]
Caused by: javax.net.ssl.SSLHandshakeException: General OpenSslEngine problem
[...]
Caused by: java.security.cert.CertificateException: No name matching <name> found

问题

证书与目标地址/名称不匹配。

解决办法

通过在客户端配置中添加以下内容:

grpc.client.__name__.security.authorityOverride=<authority>

不受信任的证书

客户端

io.grpc.StatusRuntimeException: UNAVAILABLE: io exception
[...]
Caused by: javax.net.ssl.SSLHandshakeException: General OpenSslEngine problem
[...]
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
[...]
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

问题

服务器使用的证书不在客户端的信任库中。

解决办法

通过使用 java keytool 将证书添加到java的信任商店,或配置客户端使用自定义信任的证书文件:

grpc.client.__name__.security.trustCertCollection=file:certificates/trusted-servers-collection.crt.list

注意: 两边的存储库目前在创建时都是只读的,更新不会被应用。

服务端端口被占用

服务端

Caused by: java.lang.IllegalStateException: Failed to start the grpc server
    at net.devh.boot.grpc.server.serverfactory.GrpcServerLifecycle.start(GrpcServerLifecycle.java:51) ~[grpc-server-spring-boot-starter-2.4.0.RELEASE.jar:2.4.0.RELEASE]
    [...]
Caused by: java.io.IOException: Failed to bind
    at io.grpc.netty.shaded.io.grpc.netty.NettyServer.start(NettyServer.java:246) ~[grpc-netty-shaded-1.21.0.jar:1.21.0]
    at io.grpc.internal.ServerImpl.start(ServerImpl.java:177) ~[grpc-core-1.21.0.jar:1.21.0]
    at io.grpc.internal.ServerImpl.start(ServerImpl.java:85) ~[grpc-core-1.21.0.jar:1.21.0]
    at net.devh.boot.grpc.server.serverfactory.GrpcServerLifecycle.createAndStartGrpcServer(GrpcServerLifecycle.java:90) ~[grpc-server-spring-boot-starter-2.4.0.RELEASE.jar:2.4.0.RELEASE]
    at net.devh.boot.grpc.server.serverfactory.GrpcServerLifecycle.start(GrpcServerLifecycle.java:49) ~[grpc-server-spring-boot-starter-2.4.0.RELEASE.jar:2.4.0.RELEASE]
    ... 13 common frames omitted
Caused by: java.net.BindException: Address already in use: bind

问题

grpc 服务端尝试使用的端口被占用。

有四种常见情况可能发生这种错误。

  1. 应用程序已在运行
  2. 另一个应用程序正在使用该端口
  3. grpc 服务器使用了一个已经用于其他用途的端口(例如spring-web)
  4. 你正在运行测试,每次测试后你都没有关闭 grpc-server

解决办法

  1. 尝试使用任务管理器或jps搜索应用程序
  2. 尝试使用 netstat 搜索端口
  3. 检查/更改您的配置。 此库默认使用端口 9090
  4. 添加@DirtiesContext到您的测试类和方法中,请注意,这个错误只会从第二次测试开始发生,因此你必须在你的第一个测试类上也加上这个注解!

客户端解析域名失败

客户端

WARN  io.grpc.internal.ManagedChannelImpl - [Failed to resolve name. status=Status{code=UNAVAILABLE, description=No servers found for `discovery-server:443`}
ERROR n.d.b.g.c.n.DiscoveryClientNameResolver - No servers found for `discovery-server:443`

问题

服务发现失败或者配置中未指定scheme,从而无法解析 discovery-server:443 。 如果没有服务发现,那么默认值是 dns, 但如果您使用了服务发现,那么它将是默认的,因而无法解决该地址。

这同样适用于其他库,例如 tracing 或 上报,它们通过 grpc 向 外部服务器报告其结果。

解决办法

可以查看 客户端目标配置

创建 issue

在 GitHub 上创建问题/提问并不难,但你可以稍微努力帮助我们更快地解决您的 个问题。

如果您的问题/疑问一般都是关于 grpc 的问题,请考虑在 grpc-java 上提问。

使用提供的模板来创建新问题,其中包含我们需要的必需/有用信息的部分。

通常来说,你应该在你的问题上包括以下信息:

  1. 您有什么类型的诉求?
    • 问题
    • Bug 反馈
    • 功能​​​​​​​​​​​请求
  2. 你希望的结果是什么?
  3. 你遇到了什么问题? 什么不起作用? 缺少什么东西,为什么需要?
  4. 任何相关堆栈/日志(非常重要)
  5. 您使用的是哪个版本?
    • Spring (boot)
    • grpc-java
    • grpc-spring-boot-starter
    • 其他相关库
  6. 其他背景
    • 它以前是否正常运行过?
    • 我们如何重现?
    • 有 demo 演示吗?

<- 返回索引