Scala gRPC 服务器仅在 GKE 容器上没有响应

问题描述

gRPC服务器托管在GKE容器上,通过端口转发到目标POD后grpcurl调用服务时,不处理onComplete,发生Timeout。 奇怪的是,这个服务器在 Docker 进程和本地主机上运行

## Run from sbt console
> sbt server/run

## or Run from Docker image
> sbt clean docker:stage
> docker build -t test-server:latest ./server/target/docker/stage/
> docker run -d -p 8080:8080 test-server:latest

## Successfully requests.
> grpcurl -plaintext -vv -d '{"organizationId": "f"}' 0.0.0.0:8080 com.test.Server/CreateAccount

Resolved method descriptor:
rpc CreateAccount ( .com.test.Request ) returns ( .com.test.Request );

Request Metadata to send:
(empty)

Response headers received:
content-type: application/grpc
grpc-accept-encoding: gzip

Estimated response size: 3 bytes

Response contents:
{
  "organizationId": "f"
}

Response trailers received:
(empty)
Sent 1 request and received 1 response

这是应用容器的配置。 Envoy 是 sidecarred,但它不会影响应用容器,因为唯一的问题是端口转发给它。

- containers
   - env:
    - name: JAVA_OPTS
      value: -xms1500m -Xmx1500m
    - name: TZ
      value: Asia/Tokyo
    image: asia.gcr.io/my-project/test-server:latest
    imagePullPolicy: Always
    name: admin
    ports:
    - containerPort: 8080
      name: http
      protocol: TCP
    resources:
      limits:
        cpu: "1"
        memory: 2000Mi
      requests:
        cpu: "1"
        memory: 2000Mi
    securityContext: {}
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: default-token-bjhmx
      readOnly: true

因此,似乎没有来自服务器的标头响应。 但是,这可能是 grpcurl 的一个问题。

> kobectl port-forward server-xxxx-xxxx 8080:8080
> grpcurl -plaintext -vv -d '{"organizationId": "f"}' 0.0.0.0:8080 com.test.Server/CreateAccount

Resolved method descriptor:
rpc CreateAccount ( .com.test.Request ) returns ( .com.test.Request );

Request Metadata to send:
(empty)

<-- waiting...
  // service implementation
  override def CreateAccount(request:Request): Future[Request] = {
    println("Received request.")
    Future(request)
  }

==================

object GrpcInterceptor extends ServerInterceptor with Injector {

  override def interceptCall[ReqT,RespT](
      serverCall: ServerCall[ReqT,RespT],headers: Metadata,next: ServerCallHandler[ReqT,RespT]
  ): ServerCall.Listener[ReqT] = {

    val listener = next.startCall(serverCall,headers)
    new ForwardingServerCallListener.SimpleForwardingServerCallListener[ReqT](listener) {
      override def onHalfClose(): Unit = {
        println("On half close")
        super.onHalfClose()
      }
      override def onComplete(): Unit = {
        println("On complete")
        super.onComplete()
      }
      override def onMessage(message: ReqT) {
        println("On message")
        val value = message.asInstanceOf[GeneratedMessage]

        try {
          super.onMessage(message)
        } catch {
          case e: Throwable =>
            closeWithException(e,headers)
        }
      }

      private def closeWithException(t: Throwable,requestHeader: Metadata) = {
        println("Reciever intercept Failed.",t)
        throw new StatusRuntimeException(Status.Code.INTERNAL.toStatus.withDescription(t.getMessage).withCause(t))
      }
    }
  }
}

此实现仍然不会在 GKE 容器上输出“On complete”日志。

On message
On half close
Received request.

然而,似乎只有 GrpcReflectionApi 响应正常。

## On GKE port-forwarding
> grpcurl -plaintext 0.0.0.0:8080 list
com.test.TestServer
grpc.reflection.v1alpha.ServerReflection

我可以确认它适用于相同的 Docker 映像,所以我唯一能想到的是它要么是 GKE 问题,要么需要完成一些特定于 gRPC 的处理。您还可以隔离哪些其他问题?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)