Как эффективно управлять памятью с помощью асинхронных вызовов GRPC

#c# #multithreading #memory-management #concurrency #grpc

Вопрос:

Мы сталкиваемся с проблемой памяти при использовании GRPC для «запуска и забывания» сообщений.

У нас есть служба A, которая управляет запросами к базе данных, и служба B, которая публикует данные о событиях во внешний источник данных.

Обе службы реализуют службу GRPC для связи с ними. Например, служба B имеет определение:

 service MessageBusService {
    rpc PublishRevision (RevisionRequest) returns (EmptyResponse) {}
}
message EmptyResponse{
}
 

В сервисе А мы делаем потенциально тысячи звонков, чтобы «запустить и забыть» асинхронный вызов службы.

 _ = grpcClient.PublishRevisionAsync(revision);
 

Где объект «ревизия» может иметь размер ~1 МБ. Выполняя профилирование памяти, мы заметили, что служба может увеличить потребление памяти до 600 МБ . По-видимому, это связано с тем фактом, что задача, которую мы выделяем, будет удерживать объект в памяти до тех пор, пока служба GRPC не ответит объектом «EmptyResponse».

Кто-нибудь знает, поддерживает ли GRPC какой-либо способ по-настоящему «запустить и забыть» службу или есть способ разместить службу, которая явно не отправляет ответа?

Есть ли лучший способ выполнить эту задачу?

Любая помощь была бы очень признательна.

Ответ №1:

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

 service MessageBusService {
    rpc PublishRevision (stream RevisionRequest) returns (EmptyResponse) {}
}
message EmptyResponse{
}

 

Вы можете «запустить и забыть» конечную точку GRPC, записав каждый элемент в поток, так как вы не должны получать ответ на каждую запись в поток.

На странице microsofts есть несколько устаревших примеров https://docs.microsoft.com/en-us/dotnet/architecture/grpc-for-wcf-developers/rpc-types

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

1. Пробовали ли вы один из вариантов потоковой передачи, поддерживаемых gRPC, который позволяет отправителю отправлять столько сообщений (при условии, что управление потоком поддерживает это), не дожидаясь ответа от получателя?