Azure中的Service Fabric状态服务-RAM使用率不断增长。可能的内存泄漏

时间:2019-05-10 17:12:07

标签: azure azure-service-fabric service-fabric-stateful reliable-dictionary

我正在Azure的群集上运行Service Fabric应用程序。集群具有两个规模集:

  • 4x个B2ms节点,其中放置有状态服务类型并带有“放置约束”(主比例尺集)
  • 放置无状态服务类型的2个F1节点。

应用程序中有两种服务

  • WebAPI-无状态服务,用于通过HTTP从系统接收状态并将其发送到StatusConsumer。
  • StatusConsumer-状态服务,处理状态并保留最后一个。为每个系统创建服务实例。它通过RemotingV2进行通信。

对于我的测试,我正在使用Application Insights和Service Fabric Analytics来跟踪性能。我正在观察以下参数:

有状态规模集的指标:CPU百分比,磁盘读/写操作/秒

Applicaiton Insights:服务器响应时间-对应于在有状态StatusConsumer中接收状态的方法的执行时间。

Service Fabric Analytics:在状态节点上具有日志分析代理的性能计数器-用于观察节点的RAM使用情况。

每个模拟系统每30秒发送一次状态。

在测试开始时,每个节点上的RAM使用率约为40%,平均服务器响应时间约为15ms,CPU使用率约为10%,读/写操作的速度低于100 / s。

测试开始后,RAM使用率立即开始缓慢增加,但其他观察到的指标没有差异。

在模拟一个系统大约一个小时后,RAM使用率约为90-95%,并且其他指标开始显示问题-平均服务器响应时间达到峰值,约为5-10秒,磁盘读/写操作达到约500 /秒

此操作持续1-3分钟,然后RAM使用率下降,一切恢复正常。RAM Usage Server Response Time

在图像上,您可以看到RAM峰值对应于服务器响应时间峰值。在RAM图的末尾,使用率是平坦的,目的是显示行为而不模拟任何系统。

模拟的系统数量仅减少或增加了RAM达到临界水平所需的时间-在一项测试中,对200个系统进行了模拟,并且RAM使用率的上升速度较慢。

关于代码:在最初的测试中,代码更加复杂,但是为了找到问题的原因,我开始删除功能。仍然没有任何改善。唯一没有增加RAM使用率的地方就是我注释了所有代码,并且在接收状态的方法的主体中,只有try / catch块和返回值。当前,StatusConsumer中的代码是这样的:

public async Task PostStatus(SystemStatusInfo status){
try{
    Stopwatch stopWatch = new Stopwatch();
    IReliableDictionary<string, SystemStatusInfo> statusDictionary = await this.StateManager.GetOrAddAsync<IReliableDictionary<string, SystemStatusInfo>>("status");

    stopWatch.Start();

    using (ITransaction tx = this.StateManager.CreateTransaction())
    {
        await statusDictionary.AddOrUpdateAsync(tx,"lastConsumedStatus",(key) => { return status; },(key, oldvalue) => status);
        await tx.CommitAsync();
    }

    stopWatch.Stop();

    if (stopWatch.ElapsedMilliseconds / 1000 > 4) //seconds
    {
        Telemetry.TrackTrace($"Queue Status Duration: { stopWatch.ElapsedMilliseconds / 1000 } for {status.SystemId}", SeverityLevel.Critical);
    }
}
catch (Exception e) {Telemetry.TrackException(e);}
}

如何诊断和/或解决此问题?

PS:连接到具有远程桌面的节点后,在任务管理器中,我可以看到,当RAM使用率约为85%时,“保存”微服务实例的SystemStatusConsumer进程的“内存”不超过600 MB。这是最高的消耗,但仍然不高-节点具有8 GB的RAM。但是,在这种情况下,我不知道这是否有用。

1 个答案:

答案 0 :(得分:0)

与Azure支持人员进行了多次测试之后,我极大地减少了服务的内存消耗。

从与支持人员的交流中我学到的主要知识是,拥有大量包含少量数据的服务真的不是一个好主意!该应用程序的内存转储显示每个服务大约有20KB的实际数据,并由Service Fabric累积了700KB的可靠集合的更改日志。这可能不是确切数字,但差异很大。

为了减少服务数量,我通过使用一种分区将多个系统状态的处理和保存合并到一个服务中。我也尝试使用Actors。所有方法都行之有效。

我还使用其他一些设置来减少内存消耗,但是最大的不同是通过更改服务本身的体系结构来实现的:

在服务本身的Settings.xml中:

  • CheckpointThresholdInMB = 1

  • LogTruncationIntervalSeconds = 1200(将此值设置为小于 120实际上无法做任何事情或使事情变得更糟。尝试使用大于300的值)

  • MaxAccumulatedBackupLogSizeInMB = 1

在服务本身的代码中:

  • ServicePointManager.DefaultConnectionLimit = 200

  • MaxConcurrentCalls = 512(RemotingListener和客户端)

集群设置:

  • AutomaticMemoryConfiguration-0(如果您未设置此设置,其他设置将不起作用)
  • WriteBufferMemoryPoolMinimumInKB-16MB。
  • WriteBufferMemoryPoolMaximumInKB-32MB。