Я думаю, что столкнулся с возможной утечкой памяти при реализации GCP PubSub PublisherClient в. NET Core. Я написал «Я думаю», потому что, если честно, я даже не уверен, что правильно его использую (и именно поэтому я публикую этот вопрос здесь).
Приложение представляет собой. NET Базовый веб-API. Вот выдержка из реализации, которую я имею:
public class GoogleTopicPublisher : IAsyncDisposable
{
private readonly TopicName _topic;
private readonly string _apiToken;
private readonly ILogger<GoogleTopicPublisher> _logger;
private readonly Lazy<Task<PublisherClient>> _lazyPublisher;
public GoogleTopicPublisher(string projectId, string topicId, string apiToken,
ILogger<GoogleTopicPublisher> logger)
{
_apiToken = apiToken;
_topic = new TopicName(projectId, topicId);
_logger = logger;
_lazyPublisher = new Lazy<Task<PublisherClient>>(() => PublisherClient.CreateAsync(_topic));
}
public async Task PublishAsync(PubSubEnvelope envelope)
{
var messageData = Newtonsoft.Json.JsonConvert.SerializeObject(envelope);
var message = new PubsubMessage()
{
Data = ByteString.CopyFromUtf8(messageData),
Attributes =
{
{"token", _apiToken }
}
};
var publisher = await _lazyPublisher.Value;
await publisher.PublishAsync(message);
GC.Collect();
GC.WaitForPendingFinalizers();
}
public async ValueTask DisposeAsync()
{
if (!_lazyPublisher.IsValueCreated)
return;
var publisher = _lazyPublisher.Value.Result;
await publisher.ShutdownAsync(TimeSpan.FromSeconds(15));
}
}
Весь класс GoogleTopicPublisher
зарегистрирован как Singleton. Как вы можете видеть, я создаю экземпляр Publisher с помощью asyn c Lazy, чтобы избежать создания нового экземпляра каждый раз, когда мне нужно опубликовать sh сообщение.
Болевая точка - это вызовы к G C: без них я вижу рост и увеличение использования памяти, пока все приложение не исчерпает память и не будет перезапущено.
Теперь мои вопросы:
- это хорошая практика для создания экземпляра PublisherClient таким образом? Если нет, есть ли лучший способ?
- могу ли я каким-либо образом избежать звонков в G C?
спасибо!