#scala #kubernetes #grpc #grpc-java #scalapb
#scala #kubernetes #grpc #grpc-java #scalapb
Вопрос:
У меня есть службы (обе написаны в scala), развернутые в кластере kubernetes, давайте назовем их внешней службой и внутренней службой
- Внешняя служба — 5 модулей, предоставляет REST API, использует внутренний сервис grpc API через grpc-клиент
- Модуль внутренней службы 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 в качестве виновника или обнаруживаем, что это так, и увеличиваем масштаб.