Почему мой Node.js gRP C клиент отправляет запрос на мой Python gRP C сервер в течение 3 секунд? - PullRequest
0 голосов
/ 02 мая 2020

Давайте начнем с признания того, что я новичок группы C. Если я задал глупый вопрос, go вперед и дайте мне знать, но только после объяснения , почему это глупо. Спасибо! :)

Обзор

Я занимаюсь разработкой приложения для обработки изображений. Переменные, которые влияют на результат обработки, должны быть изменены пользователем. Я хотел обеспечить привлекательный GUI при сохранении кроссплатформенной совместимости. Таким образом, я решил реализовать обработку изображений в Python и использовать Node.js и Electron для моего GUI.

Необходим способ отправки и получения данных в мой Python бэкэнд, Я решил использовать gRP C. Таким образом, у меня есть Node.js gRP C Client в паре с Python gRP C Server .

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

Настройка

Приложение Node.js Electron принимает данные от пользователя и отправляет запрос в Python бэкэнд. Размер запроса - небольшой объект:

// From My Protocol Buffer
message DetectionSettings {
    float lowerThreshold = 1;
    float upperThreshold = 2;
    float smallestObject = 3;
    float largestObject  = 4;
    float blurAmount     = 5;

    int64 frameNumber    = 6;
    string streamSource  = 7;
}

После получения этого запроса приложение Python считывает кадр из указанного streamSource и обрабатывает его. Затем этот обработанный кадр преобразуется в формат JPEG и возвращается через gRP C в приложение Node.js в виде Image:

// From My Protocol Buffer
message Image {
    bytes image_data = 1;
    int32 height = 2;
    int32 width = 3;
    int64 frame = 4;    
}

Проблема

Я заметил, что между временем выполнения запроса и получением изображения существует переменная задержка. Это время варьируется от нескольких мс до почти 3 секунд! После профилирования кода Python я определил, что время обработки незначительно. Кроме того, время, необходимое для возврата Image через gRP C, также незначительно.

Таким образом, существует интригующая задержка между выполнением RP C и приложением Python, принимающим вызов. Вот некоторые журналы со временем, чтобы лучше объяснить, что происходит (число в скобках в секундах):

/* Node.js */
[160408.072] "Sending Request..."
[160408.072] "Executing RPC"
[160408.072] "RPC Executed"

/* Python */
[160411.032] [ py-backend ] Getting frame

/* Node.js */
[160411.617] "Got Data"

Вы можете видеть, что в этом случае время от выполнения Node.js RP C до вызываемый метод Python составлял около 3 секунд, в то время как время от выполнения метода Python до приложения Node.js, получающего Image, составляет менее 1 секунды 0.o

. Код

Python gRP C Сервер

# Create the server
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))

# Add our service to the server
processor_pb2_grpc.add_ProcessorServicer_to_server(
    ProcessorServicer(), server
)

server.add_insecure_port('[::1]:50053')
server.start()
server.wait_for_termination()

Node.js Клиент:

const grpc = require('grpc')
const PROTO_PATH = '../processor.proto'

const serviceConfig = {
    "loadBalancingConfig": [ {"round_robin": {} } ]
}
const options = {
    'grpc.service_config': JSON.stringify(serviceConfig)
}

const ProcessorService = grpc.load(PROTO_PATH).Processor
const client = new ProcessorService ('[::1]:50053',
    grpc.credentials.createInsecure(), options);

module.exports = client

Буфер протокола:

syntax = "proto3";

message Number {
    float value = 1;
}

message Image {
    bytes image_data = 1;
    int32 height = 2;
    int32 width = 3;
    int64 frame = 4;    
}

message DetectionSettings {
    float lowerThreshold = 1;
    float upperThreshold = 2;
    float smallestObject = 3;
    float largestObject  = 4;
    float blurAmount     = 5;

    int64 frameNumber    = 6;
    string streamSource  = 7;
}

service Processor{
    rpc GetFrame(DetectionSettings) returns (Image) {};
}

Node.js gRP C Звоните:

function GetFrameBytes(detectionSettings, streamSource, frameNumber, callback)
{
    detectionSettings["streamSource"] = streamSource;
    detectionSettings["frameNumber"] = frameNumber;

    client.GetFrame(detectionSettings, (error, response) =>
    {
        if(!error){
            callback(response)
        }
        else
        {
            console.error(error);
        }
    });
}

tl; dr

С какой стати мой Node.js запрос клиента так долго вызывает мой код Python?

1 Ответ

2 голосов
/ 04 мая 2020

Есть несколько факторов, которые могут повлиять на долгое время, которое вы видите.

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

Во-вторых, вы упомянули, что используете Electron. Были некоторые сообщения о gRP C для узла, работающего плохо при использовании в процессе рендеринга электронов. Вы можете увидеть разные результаты при запуске вашего кода в основном процессе или в обычном процессе Node.

Вам также может повезти, если вы попробуете пакет @grpc/grpc-js, который является полным переопределением Node библиотека C. API, который вы в настоящее время используете для загрузки пакетов .proto, не существует в этой библиотеке, но альтернатива, использующая @grpc/proto-loader, работает с обеими реализациями, и другие API одинаковы.

...