Python GRP C Узкое место в производительности сервера - PullRequest
1 голос
/ 12 февраля 2020

Я написал сервер GRP c, который содержит несколько служб RP c. Некоторые унарные, а некоторые потоковые на стороне сервера.

Он подключается к серверу grp c kubernetes, поэтому я использую клиент python kubernetes для запроса к серверу

В настоящее время у меня некоторые проблемы с производительностью, так как я думаю, что если поступают множественные запросы, они буферизуют каждого работника до sh, прежде чем он сможет обслуживать входящий запрос.

def startServer():
    global server
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    servicer_grpc.add_Servicer_to_server(Servicer(), server)
    server.add_insecure_port('[::]:' + str(port))
    server.start()

Мои вопросы:

  1. Как я могу улучшить свои показатели? Поможет ли добавление еще max_workers в threadpoolexecutor?

  2. Как я могу диагностировать проблему и изолировать причину замедления?

  3. Я думаю если размер ответа имеет значение в этом случае, поскольку я передаю потоковую передачу клиенту. Есть ли способ измерить размер ответа или это имеет значение в python grp c?

Я хотел бы знать, как вы диагностируете вашу python grp c сервер, чтобы вы знали, где улучшить?

1 Ответ

2 голосов
/ 12 февраля 2020

Проблема производительности, которую вы описали, звучит как проблема параллелизма. Сервер gRP C Python использует ThreadExecutor для обработки RPC, и увеличение числа рабочих должно позволять большее число одновременных RP C.

grpc.server(futures.ThreadPoolExecutor(max_workers=1000))

Для вопроса 2 профилировщики cProfile, yep и perf являются мощными инструментами для устранения проблем с производительностью.

Для вопроса 3 размер ответа не имеет большого значения (на уровне КБ).

Вкл С другой стороны, мы работаем над AsyncIO-версией gRP C Python. Он значительно повышает производительность и решает ограниченную параллельную проблему RP C. Пока это экспериментально, но не стесняйтесь попробовать.

from grpc.experimental import aio

class Servicer(...):
    async def ServerStreamingMethodHandler(...):
        for ...:
            yield response

async def startServer():
    global server
    server = aio.server()
    servicer_grpc.add_Servicer_to_server(Servicer(), server)
    server.add_insecure_port('[::]:' + str(port))
    await server.start()
...