Рекомендации для однопоточных вызовов с высокой пропускной способностью и низкой задержкой в ​​gRPC - PullRequest
0 голосов
/ 17 октября 2019

Я ищу рекомендации по максимизации пропускной способности и минимизации задержки для унарных вызовов gRPC. Мне нужно достичь около 20000 QPS, <50 мс каждый. На умеренном оборудовании (4-ядерный процессор) я мог достичь только 15K QPS со средней задержкой 200 мс. Я использую Java-клиент и сервер. Сервер ничего не делает, кроме как возвращает ответ. Клиент отправляет несколько одновременных запросов, используя асинхронную заглушку. Количество одновременных запросов ограничено. ЦПУ остается в диапазоне ~ 80%. Для сравнения, используя Apache Kafka, я могу достичь гораздо более высокой пропускной способности (100 тысяч QPS), а также задержки в диапазоне 10 мс. </p>

1 Ответ

1 голос
/ 24 октября 2019

Если вы используете grpc-java 1.21 или более поздней версии и grpc-netty-shaded, вы уже должны использовать транспорт Netty Epoll. Если вы используете grpc-netty, добавьте зависимость времени выполнения на io.netty:netty-transport-native-epoll (правильную версию можно найти, посмотрев файл pom.xml grpc-netty или таблицу версий в SECURITY.md ).

Исполнителем по умолчанию для обратных вызовов является «пул кэшированных потоков». Если вы не блокируете (или знаете пределы блокирования), указание пула потоков фиксированного размера может повысить производительность. Вы можете попробовать как Executors.newFixedThreadPool, так и ForkJoinPool;мы видели, как «оптимальный» выбор варьируется в зависимости от рабочей нагрузки. Вы указываете своего собственного исполнителя через ServerBuilder.executor() и ManagedChannelBuilder.executor().

Если у вас высокая пропускная способность (~ Gbps + на клиента с TLS; выше, если открытый текст) с использованием нескольких каналов, можно повысить производительность с помощью нескольких соединений TCP. Каждое TCP-соединение прикрепляется к потоку, поэтому наличие большего количества TCP-соединений позволяет использовать больше потоков. Вы можете создать несколько каналов и затем циклически перебирать их;выбор другого для каждого RPC. Обратите внимание, что вы можете легко реализовать интерфейс Channel, чтобы «скрыть» эту сложность от остальной части вашего приложения. Похоже, это обеспечит вам большой выигрыш, но я поставил его последним, потому что это обычно не нужно.

...