首页 > 解决方案 > 通过 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;
        }

我只展示了已更改的相关位。其余为默认值。

标签: javanginxgrpc

解决方案


推荐阅读