Высокая задержка службы grpc с использованием grpc-клиента в kubernetes

#scala #kubernetes #grpc #grpc-java #scalapb

#scala #kubernetes #grpc #grpc-java #scalapb

Вопрос:

У меня есть службы (обе написаны в scala), развернутые в кластере kubernetes, давайте назовем их внешней службой и внутренней службой

  1. Внешняя служба — 5 модулей, предоставляет REST API, использует внутренний сервис grpc API через grpc-клиент
  2. Модуль внутренней службы 1, предоставляет API grpc

Проблема — Когда я вызываю внутреннюю службу grpc API путем переадресации портов с использованием некоторого grpc-клиента, например, BloomRPC, задержка очень хорошая в течение 1 секунды (в среднем 300 мс), но когда я использую тот же grpc API с использованием grpc-клиента (написанного на scala), это всегда занимает в среднем> 2 секунды. Я понимаю, что первый вызов займет некоторое время из-за обработки соединения TPC, но это всегда занимает 2-4 секунды даже после прогрева JVM. Я создаю канал grpc только один раз при запуске службы (в основном методе, асинхронная заглушка) и повторно использую его, балансировка нагрузки grpc на стороне клиента не включена. Как улучшить задержку?

 class MyServiceGrpcClient(val channel: ManagedChannel) {
  val myServiceStub = MyServiceGrpc.stub(channel)

  def this(host: String, port: Int) {
    this(ManagedChannelBuilder.forAddress(host, port).usePlaintext().build())
  }

  @throws[InterruptedException]
  def shutdown(): Unit = {
    channel.shutdown.awaitTermination(5, TimeUnit.SECONDS)
  }
}


object ExternalServiceApp extends App {
  val host = sys.env.getOrElse("HOST_NAME", "internal-service-name") //Its k8s ClusterIP service name
  val port = sys.env.getOrElse("PORT", "1234")
  val internalGrpcClient = new MyServiceGrpcClient(wesHost, wesPort).myServiceStub

  val routes = new ExternalRoutes(internalGrpcClient)

  //Akka http routes logic, route API calls grpc API
}

class ExternalRoutes(grpcClient: MyServiceGrpcClient){

  override def getResponse(request: Request): Future[Response] = {

    grpcClient.internalGrpcApi(request).map { resp =>
      resp
    }

  }
}
 

Комментарии:

1. Можете ли вы опубликовать весь код клиента?

2. @thesamet обновил код с основным классом приложения, где внешний Http API создает клиентский объект grpc, и он передается в другой класс, где происходит внутренний вызов grpc. Таким образом, объект-заглушка (с каналом) создается только один раз при запуске внешней службы

3. Я предлагаю попытаться выполнить разделяй и властвуй, чтобы определить, какая часть системы вызывает проблему. Можете ли вы попробовать grpc-java напрямую, без ScalaPB? Можете ли вы попробовать подключиться к локально работающему серверу, чтобы мы знали, что это не сеть или Kubernetes? Продолжайте в том же духе, пока не узнаете, какая часть добавляет задержку.

4. Я попытался выполнить следующие действия: 1. Перенаправить внутреннюю службу grpc и запустить grpc API с помощью клиента bloomrpc grpc. Это дает очень хорошую задержку в течение (1 секунды) 2. Запустите внешнюю службу http локально и перенаправьте внутреннюю службу grpc и нажмите внешний http API (в коде он вызывает grpc api с использованием написанного выше клиентского кода grpc), тогда эта строка занимает> 2 сек grpcClient.internalGrpcApi(request).map { соотв=> соответственно } Вы хотите, чтобы я сгенерировал клиентские классы на java с помощью компилятора протокола и попытался вызвать grpc API? Как вы думаете, классы scalapb занимают больше времени?

5. ScalaPB имеет производительность, аналогичную grpc-java. Стоит проверить, что это верно и для вашего варианта использования, поэтому мы исключаем ScalaPB в качестве виновника или обнаруживаем, что это так, и увеличиваем масштаб.