将基于 Java 的 Grpc 服务器与基于 C# 的客户端一起使用时出现传输失败错误
Transport failed error when using a Java based Grpc server with a C# based client
我正在使用 spring boot (2.2.2) 和 grpc-server-spring-boot-starter java 库开发一个基于 java 的 Grpc 服务器.
我的客户端应用程序是 C# 应用程序 (netcoreapp3.1)。我的笔记本电脑上的两个应用程序 运行 都用于此测试。
这是我的原型文件
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.honeywell.EOM.SystemAPI.webapi.web.grpc.service";
//option java_outer_classname = "TestProto";
service Simple {
rpc GetData (Empty) returns (Data) {
}
}
message Empty {
}
message Data {
string name = 1;
}
这是服务代码
@GrpcService
public class TestService extends SimpleGrpc.SimpleImplBase {
@Override
public void getData(Empty request, StreamObserver<Data> responseObserver) {
Data data = Data.newBuilder().setName("Somename").build();
responseObserver.onNext(data);
responseObserver.onCompleted();
}
}
我首先使用这个工具测试了服务器tool
该服务与此客户端工具配合良好。
然而,当我使用 C# 客户端进行测试时,出现此错误
io.grpc.netty.shaded.io.grpc.netty.NettyServerTransport notifyTerminated
INFO: 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: 16030100b6010000b203035e95b0402c6320969d3d5fba04
at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2Exception.connectionError(Http2Exception.java:103)
at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler$PrefaceDecoder.readClientPrefaceString(Http2ConnectionHandler.java:306)
at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler$PrefaceDecoder.decode(Http2ConnectionHandler.java:239)
at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler.decode(Http2ConnectionHandler.java:438)
at io.grpc.netty.shaded.io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:505)
at io.grpc.netty.shaded.io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:444)
at io.grpc.netty.shaded.io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:283)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
at io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1422)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
at io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:931)
at io.grpc.netty.shaded.io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
at io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:700)
at io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:635)
at io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:552)
at io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:514)
at io.grpc.netty.shaded.io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:1044)
at io.grpc.netty.shaded.io.netty.util.internal.ThreadExecutorMap.run(ThreadExecutorMap.java:74)
at io.grpc.netty.shaded.io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:834)
C#客户端代码在这里
using var channel = GrpcChannel.ForAddress("https://localhost:9090");
var client = new Simple.SimpleClient(channel);
var reply = client.GetData(new Empty { });
我做错了什么?这是一个开放缺陷吗?
错误消息报告接收到的字节(十六进制):
16030100b6010000b203035e95b0402c6320969d3d5fba04
三个起始字节 160301
看起来像 TLS 握手。服务器可能处于纯文本模式,客户端正在使用 TLS。
要在客户端使用纯文本,请使用 "http":
using var channel = GrpcChannel.ForAddress("http://localhost:9090");
编辑:此答案的代码示例已损坏;它没有正确启用纯文本
如 Eric Anderson 的回答所述,客户端确实在使用 TLS。
gRPC 的 .NET Core 客户端在与不安全(非 TLS)服务器通信时需要额外的配置(从 .NET Core 3.1 开始)。
// This switch must be set before creating the GrpcChannel/HttpClient.
AppContext.SetSwitch(
"System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
using var channel = GrpcChannel.ForAddress("http://localhost:9090");
var client = new Simple.SimpleClient(channel);
var reply = client.GetData(new Empty { });
我正在使用 spring boot (2.2.2) 和 grpc-server-spring-boot-starter java 库开发一个基于 java 的 Grpc 服务器. 我的客户端应用程序是 C# 应用程序 (netcoreapp3.1)。我的笔记本电脑上的两个应用程序 运行 都用于此测试。
这是我的原型文件
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.honeywell.EOM.SystemAPI.webapi.web.grpc.service";
//option java_outer_classname = "TestProto";
service Simple {
rpc GetData (Empty) returns (Data) {
}
}
message Empty {
}
message Data {
string name = 1;
}
这是服务代码
@GrpcService
public class TestService extends SimpleGrpc.SimpleImplBase {
@Override
public void getData(Empty request, StreamObserver<Data> responseObserver) {
Data data = Data.newBuilder().setName("Somename").build();
responseObserver.onNext(data);
responseObserver.onCompleted();
}
}
我首先使用这个工具测试了服务器tool
该服务与此客户端工具配合良好。
然而,当我使用 C# 客户端进行测试时,出现此错误
io.grpc.netty.shaded.io.grpc.netty.NettyServerTransport notifyTerminated
INFO: 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: 16030100b6010000b203035e95b0402c6320969d3d5fba04
at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2Exception.connectionError(Http2Exception.java:103)
at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler$PrefaceDecoder.readClientPrefaceString(Http2ConnectionHandler.java:306)
at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler$PrefaceDecoder.decode(Http2ConnectionHandler.java:239)
at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler.decode(Http2ConnectionHandler.java:438)
at io.grpc.netty.shaded.io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:505)
at io.grpc.netty.shaded.io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:444)
at io.grpc.netty.shaded.io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:283)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
at io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1422)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
at io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:931)
at io.grpc.netty.shaded.io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
at io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:700)
at io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:635)
at io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:552)
at io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:514)
at io.grpc.netty.shaded.io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:1044)
at io.grpc.netty.shaded.io.netty.util.internal.ThreadExecutorMap.run(ThreadExecutorMap.java:74)
at io.grpc.netty.shaded.io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:834)
C#客户端代码在这里
using var channel = GrpcChannel.ForAddress("https://localhost:9090");
var client = new Simple.SimpleClient(channel);
var reply = client.GetData(new Empty { });
我做错了什么?这是一个开放缺陷吗?
错误消息报告接收到的字节(十六进制):
16030100b6010000b203035e95b0402c6320969d3d5fba04
三个起始字节 160301
看起来像 TLS 握手。服务器可能处于纯文本模式,客户端正在使用 TLS。
要在客户端使用纯文本,请使用 "http":
using var channel = GrpcChannel.ForAddress("http://localhost:9090");
编辑:此答案的代码示例已损坏;它没有正确启用纯文本
如 Eric Anderson 的回答所述,客户端确实在使用 TLS。
gRPC 的 .NET Core 客户端在与不安全(非 TLS)服务器通信时需要额外的配置(从 .NET Core 3.1 开始)。
// This switch must be set before creating the GrpcChannel/HttpClient.
AppContext.SetSwitch(
"System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
using var channel = GrpcChannel.ForAddress("http://localhost:9090");
var client = new Simple.SimpleClient(channel);
var reply = client.GetData(new Empty { });