java - 通过 nginx 反向代理终止 gRPC 连接
问题描述
我正在尝试将 nginx 设置为 gRPC 服务的反向代理。每次 gRPC 调用后,nginx 都会终止与上游 gRPC 服务的连接。我不明白为什么会这样。连接不应该是持久的吗?
我可以使用示例程序重现此行为。
HelloService.proto:-
syntax = "proto3";
option java_multiple_files = true;
package grpctest;
message HelloRequest {
string firstName = 1;
string lastName = 2;
}
message HelloResponse {
string greeting = 1;
}
service HelloService {
rpc hello(HelloRequest) returns (HelloResponse);
rpc helloStream(HelloRequest) returns (stream HelloResponse);
}
HelloServiceImpl.java: -
package grpctest;
import io.grpc.stub.StreamObserver;
public class HelloServiceImpl extends HelloServiceGrpc.HelloServiceImplBase {
@Override
public void hello(
HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
String greeting = new StringBuilder()
.append("Hello, ")
.append(request.getFirstName())
.append(" ")
.append(request.getLastName())
.toString();
HelloResponse response = HelloResponse.newBuilder()
.setGreeting(greeting)
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
@Override
public void helloStream(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
String greeting = new StringBuilder()
.append("Hello, ")
.append(request.getFirstName())
.append(" ")
.append(request.getLastName())
.toString();
HelloResponse response = HelloResponse.newBuilder()
.setGreeting(greeting)
.build();
for(int i = 0; i < 10; i++) {
responseObserver.onNext(response);
}
responseObserver.onCompleted();
}
}
HelloServer.java: -
package grpctest;
import java.io.IOException;
import io.grpc.Attributes;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.ServerTransportFilter;
public class HelloServer {
public static void main(String[] args) throws InterruptedException, IOException {
Server server = ServerBuilder
.forPort(8072)
.addTransportFilter(new ServerTransportFilter() {
@Override
public Attributes transportReady(Attributes transportAttrs) {
System.out.println("Connected ..");
return super.transportReady(transportAttrs);
}
@Override
public void transportTerminated(Attributes transportAttrs) {
System.out.println("Disconnected ..");
super.transportTerminated(transportAttrs);
}
})
.addService(new HelloServiceImpl()).build();
server.start();
server.awaitTermination();
}
}
HelloClient.java: -
package grpctest;
import java.util.Iterator;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
public class HelloClient {
public static void main(String[] args) {
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8072)
.usePlaintext()
.build();
HelloServiceGrpc.HelloServiceBlockingStub stub
= HelloServiceGrpc.newBlockingStub(channel);
HelloResponse helloResponse = stub.hello(HelloRequest.newBuilder()
.setFirstName("jack")
.setLastName("gRPC")
.build());
System.out.println(helloResponse.getGreeting());
System.out.println();
Iterator<HelloResponse> response = stub.helloStream(HelloRequest.newBuilder()
.setFirstName("jack")
.setLastName("gRPC")
.build());
try {
response.forEachRemaining(r -> System.out.println(r.getGreeting()));
} catch(Exception e) {
e.printStackTrace();
}
channel.shutdown();
}
}
当HelloClient
直接连接到HelloServer
服务器上的输出时,如下所示。
Connected ..
Disconnected ..
但是当HelloClient
通过 nginx 连接时,服务器上的输出看起来像这样。
Connected ..
Disconnected ..
Connected ..
Disconnected ..
即 nginx 在每次 RPC 调用后终止物理 TCP 连接。
我的 nginx 配置如下所示。
http {
upstream grpctest {
server 127.0.0.1:8072;
}
server {
#listen 80;
listen 8070 http2;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /grpctest.HelloService {
grpc_pass grpc://grpctest;
grpc_socket_keepalive on;
}
我只展示了已更改的相关位。其余为默认值。
解决方案
推荐阅读
- ruby-on-rails - 搜索踢问题 Faraday::Error::ConnectionFailed
- .net - Chromium-Edge HTML 渲染器是否有 WinForms 控件?
- python - 是否可以始终依赖 ctypes.data_as 来保留对临时对象的引用?
- python - Python 3.6 ~ AttributeError: module 'servicemanager' has no attribute 'Initialize' ~ 创建windows service exe时
- node.js - 如何分别部署 Express Server 和 React App,通过 WebSocket/WebSocketServer 连接
- python - Python如何调用数据框的两列中的任何一列
- python - 尝试 git push 时的 Bitbucket 错误日志
- javascript - DataTables 函数在 Codeigniter 中不起作用
- google-apps-script - GSheet - 确保除了一张之外的所有工作表都被隐藏
- image - 图片压缩后APK无法编译