目录

一、测试过程及问题

二、问题排查及分析过程

三、问题分析及解决过程

四、问题解决初步结果


一、测试过程及问题

从昨天15点左右开始测试,1个主节点,10个计算节点,1000个数据点,每个数据点3(1个实时窗口,2个延迟窗口)个数据窗口,每个数据点随时生成窗口周期和计算实例,每个数据点随时生成实时数据或历史数据。

测试结果,由于程序无法再获得电脑的内存而停止工作,更专业的说是System. OutOfMemoryException。

主节点,今天3点左右开始出现异常,如下:

[20-11-13 03:00:21]>>窗口0952-补发数据_CSharpFlink.Core.Window.Operator.Min-线程(0033):【2020/11/13 2:00:00-2020/11/13 3:00:00】,异常:
Exception of type 'System.OutOfMemoryException' was thrown. at System.Text.StringBuilder.ToString()
at CSharpFlink.Core.Task.MasterTaskManager.ParallelCalculate(ICalculateContext context) in \CSharpFlink\src\CSharpFlink.Core\Task\MasterTaskManager.cs:line 358 [20-11-13 03:00:35]>>窗口0927-补发数据_CSharpFlink.Core.Window.Operator.Min-线程(0098):【2020/11/13 2:00:00-2020/11/13 3:00:00】,异常:
Exception of type 'System.OutOfMemoryException' was thrown. at System.Text.RegularExpressions.Match..ctor(Regex regex, Int32 capcount, String text, Int32 begpos, Int32 len, Int32 startpos)
at System.Text.RegularExpressions.RegexRunner.InitMatch()
at System.Text.RegularExpressions.RegexRunner.Scan(Regex regex, String text, Int32 textbeg, Int32 textend, Int32 textstart, Int32 prevlen, Boolean quick, TimeSpan timeout)
at System.Text.RegularExpressions.Regex.Run(Boolean quick, Int32 prevlen, String input, Int32 beginning, Int32 length, Int32 startat)
at System.Text.RegularExpressions.Match.NextMatch()
at System.Text.RegularExpressions.RegexReplacement.Replace(Regex regex, String input, Int32 count, Int32 startat)
at System.Text.RegularExpressions.Regex.Replace(String input, String replacement)
at CSharpFlink.Core.Task.MasterTaskManager.ParallelCalculate(ICalculateContext context) in \CSharpFlink\src\CSharpFlink.Core\Task\MasterTaskManager.cs:line 358 [20-11-13 03:00:42]>>窗口0941-补发数据_CSharpFlink.Core.Window.Operator.Avg-线程(0085):【2020/11/13 2:00:00-2020/11/13 3:00:00】,异常:
Exception of type 'System.OutOfMemoryException' was thrown. at System.GC.AllocateNewArray(IntPtr typeHandle, Int32 length, Boolean zeroingOptional)
at System.GC.AllocateUninitializedArray[T](Int32 length)
at System.Buffers.TlsOverPerCoreLockedStacksArrayPool`1.Rent(Int32 minimumLength)
at System.Text.ValueStringBuilder.Grow(Int32 additionalCapacityBeyondPos)
at System.Text.ValueStringBuilder.Append(ReadOnlySpan`1 value)
at System.Text.RegularExpressions.RegexReplacement.Replace(Regex regex, String input, Int32 count, Int32 startat)
at System.Text.RegularExpressions.Regex.Replace(String input, String replacement)
at CSharpFlink.Core.Task.MasterTaskManager.ParallelCalculate(ICalculateContext context) in \CSharpFlink\src\CSharpFlink.Core\Task\MasterTaskManager.cs:line 358
ValueStringBuilder.Append(ReadOnlySpan`1 value)
at System.Text.RegularExpressions.RegexReplacement.Replace(Regex regex, String input, Int32 count, Int32 startat)
at System.Text.RegularExpressions.Regex.Replace(String input, String replacement)
at CSharpFlink.Core.Task.MasterTaskManager.ParallelCalculate(ICalculateContext context) in \CSharpFlink\src\CSharpFlink.Core\Task\MasterTaskManager.cs:line 358 [20-11-13 03:00:46]>>窗口0970-补发数据_CSharpFlink.Core.Window.Operator.Sum-线程(0074):【2020/11/13 2:00:00-2020/11/13 3:00:00】,异常:
Exception of type 'System.OutOfMemoryException' was thrown. at System.String.Concat(String str0, String str1)
at CSharpFlink.Core.Common.FileUtil.WriteAppend(String filePath, String[] contents) in \CSharpFlink\src\CSharpFlink.Core\Common\FileUtil.cs:line 36
at CSharpFlink.Core.Task.MasterTaskManager.ParallelCalculate(ICalculateContext context) in \CSharpFlink\src\CSharpFlink.Core\Task\MasterTaskManager.cs:line 370

从节点,部分存活,部分异常退出,异常信息如下:

[20-11-13 02:00:38]>>任务解析异常:
Exception of type 'System.OutOfMemoryException' was thrown. at System.String.Concat(String str0, String str1)
at CSharpFlink.Core.Common.FileUtil.WriteAppend(String filePath, String[] contents) in \CSharpFlink\src\CSharpFlink.Core\Common\FileUtil.cs:line 36
at CSharpFlink.Core.Task.SlaveTaskManager.AddTask(String taskMsg) in \CSharpFlink\src\CSharpFlink.Core\Task\SlaveTaskManager.cs:line 138

358行的代码:

CalculateContext calcContext=(CalculateContext)context;

370行的代码:

_masterCacheList.TryAdd(downTrans.Key, compressMsg);

138行的代码:

_slaveCacheList.TryAdd(downTrans.Key, downTrans);

masterCacheList和slaveCacheList变量是ConcurrentDictionary类。

二、问题排查及分析过程

共性问题:记录的每处OutOfMemoryException异常信息都会涉及到对【String】的操作。

第一步,使用dotnet-dump工具对String进行操作

参考链接:https://docs.microsoft.com/zh-cn/dotnet/core/diagnostics/debug-memory-leak

System.String有1784359个对象,为什么这么多对象呢?因为要生成计算节点的任务,这个任务要临时保存到文件目录中,把计算任务的文件发送到计算节点后,再进行删除和清空程序缓存。

写任务文件其中涉及到FileUtil.WriteAppend()方法,这个和上面异常的日志信息是对应的,WriteAppend的代码,如下:

public static void WriteAppend(string filePath, string[] contents)
{
using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
{
fs.Seek(fs.Length, SeekOrigin.Current);
    string content = String.Join(Environment.NewLine, contents) + Environment.NewLine;
    byte[] data = System.Text.Encoding.UTF8.GetBytes(content);
    fs.Write(data, 0, data.Length);
    fs.Close();
}
}
注:这是很早写的代码。

其中Join函数,可能涉及到了Concat函数,和异常信息也是对应的。

那就奇怪了,难道using和Close没有起来关闭和释放资源的目的吗?让我们来看看FileStream的基类Stream的Dispose和 Close都做了什么?看源代码,如下图:

从代码上看唯一做了SuppressFinalize函数操作,那么SuppressFinalize是什么意思呢?参见链接:

https://docs.microsoft.com/zh-cn/dotnet/api/system.gc.suppressfinalize?view=netcore-3.1

上面链接的大概意思是:请求公共语言运行时不要调用指定对象的终结器。也就是说继承了IDisposable接口,就不再调用类的析构函数了,那析构函数做了什么呢?如下图:

我们分析至此,Dispose和Close相当于什么都没有做。那只能依赖GC来清理资源了。那在高并发下操作FileStream,Dispose和Close不起作用的情况下,难道GC没有及时回收资源?看来有可能是这个问题。

三、问题分析及解决过程

但是怎么解决这个问题呢?记得FileStream类有一个Flush函数,具体操作函数代码,如下图:

Flush函数主要调用了FlushOSBuffer函数,代码如下图:

没有找到FlushFileBuffers函数,调用的函数,如下图:

这是非托管的代码,函数参考链接:https://docs.microsoft.com/zh-cn/windows/win32/api/fileapi/nf-fileapi-flushfilebuffers。大致意思是立即把数据写到磁盘文件中,但是没有找到该函数的源代码。

不管源代码的事了,修改一下WriteAppend函数,加上Flush测试一下,代码如下:

using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
{
fs.Seek(fs.Length, SeekOrigin.Current);
string content = String.Join(Environment.NewLine, contents) + Environment.NewLine;
byte[] data = System.Text.Encoding.UTF8.GetBytes(content);
fs.Write(data, 0, data.Length);
fs.Flush(); //新增加代码。
fs.Close();
}

四、问题解决初步结果

上午10点部署,测试到下午15点,总共5个小时左右的时间。内存使用情况,主节点基本维持在:380 MB(1000数据点,每个数据点有3个数据窗口,如果1个窗口,应该在130 MB左右),子节点基本维持在:150 MB。有一段时间,内存会逐步增涨,但是某个时间点内存会释放到基本情况,曲线呈现正弦波趋势。内存使用情况,如下图:


物联网&大数据技术 QQ群:54256083

物联网&大数据合作 QQ群:727664080

网站:http://www.ineuos.net

联系QQ:504547114

合作微信:wxzz0151

官方博客:https://www.cnblogs.com/lsjwq

iNeuOS工业互联网操作系统 公众号

CSharpFlink分布式实时计算,OutOfMemoryException异常,你意想不到的原因。的更多相关文章

  1. JStorm 是一个分布式实时计算引擎

    alibaba/jstorm JStorm 是一个分布式实时计算引擎. JStorm 是一个类似Hadoop MapReduce的系统, 用户按照指定的接口实现一个任务,然后将这个任务递交给JStor ...

  2. [开源]CSharpFlink(NET 5.0开发)分布式实时计算框架,PC机10万数据点秒级计算测试说明

    github地址:https://github.com/wxzz/CSharpFlinkgitee地址:https://gitee.com/wxzz/CSharpFlink  1         计算 ...

  3. 开源分布式实时计算引擎 Iveely Computing 之 WordCount 详解(3)

    WordCount是很多分布式计算中,最常用的例子,例如Hadoop.Storm,Iveely Computing也不例外.明白了WordCount在Iveely Computing上的运行原理,就很 ...

  4. 开源分布式实时计算引擎 Iveely Computing 之 本地调试Topology(4)

    当我们写完一个比较复杂的Topology之后,倘若直接提交到服务器上运行,难免会有很多问题,如何进行本地的调试Topology,是我们非常关心的问题.我们依然以WordCount作为代码示例. 首先, ...

  5. 开源分布式实时计算引擎 Iveely Computing 之 安装部署(2)

          在Github中下载代码和二进制程序中,您都会看到一个bin\iveely computing目录,里面即是Iveely Computing的运行库.              以前总是有 ...

  6. 一脸懵逼学习Storm---(一个开源的分布式实时计算系统)

    Storm的官方网址:http://storm.apache.org/index.html 1:什么是Storm? Storm是一个开源的分布式实时计算系统,可以简单.可靠的处理大量的数据流.被称作“ ...

  7. (第8篇)实时可靠的开源分布式实时计算系统——Storm

    摘要: 在Hadoop生态圈中,针对大数据进行批量计算时,通常需要一个或者多个MapReduce作业来完成,但这种批量计算方式是满足不了对实时性要求高的场景.那Storm是怎么做到的呢? 博主福利 给 ...

  8. TOP100summit:【分享实录】Twitter 新一代实时计算平台Heron

    本篇文章内容来自2016年TOP100summit Twitter technical lead for Heron Maosong Fu 的案例分享. 编辑:Cynthia Maosong Fu:T ...

  9. Storm分布式实时流计算框架相关技术总结

    Storm分布式实时流计算框架相关技术总结 Storm作为一个开源的分布式实时流计算框架,其内部实现使用了一些常用的技术,这里是对这些技术及其在Storm中作用的概括介绍.以此为基础,后续再深入了解S ...

随机推荐

  1. RHSA-2018:1200-重要: patch 安全更新(代码执行)

    [root@localhost ~]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) 修复命令: 使用root账号登陆She ...

  2. node_modules 文件夹需要管理员权限才能删除问题

    方法一:以管理员权限运行IDE ,然后在IDE里面删除该文件夹 方法二:以管理员身份运行cmd,使用命令行来删除该文件夹 找到要删除文件夹的位置,使用命令行 rmdir /s/q 文件夹位置 /s 是 ...

  3. client: c#+protobuf, server: golang+protobuf

    前段时间看到一篇博文<可在广域网部署运行的即时通讯系统 -- GGTalk总览(附源码下载)>,他是用C#实现的即时通讯系统,功能强大,界面漂亮. 就想用golang重写服务端,把代码下载 ...

  4. MVC与MVVM理解

    MVC MVC是一种软件架构模式,也有人叫做设计模式 M: Model 数据模型(专门用来操作数据,数据的CRUD) V:View 视图(对于前端来说,就是页面) C:Controller 控制器(是 ...

  5. antd pro 路由

    概要 antd pro 路由简介 路由, 菜单和面包屑 页面之间的路由 带参数的路由 总结 概要 路由配置是单页应用的核心之一, antd pro 将所有的路由配置集中在一个文件中, 可以更好的对应用 ...

  6. 空间视频和GIS

    摘要. GIS的空间数据基本单位表示通常是根据 点,线和面.但是,另一种类型的空间数据正在变得越来越频繁 捕获的是视频,但在GIS中却被很大程度上忽略了.数字录像时 是现代社会中常见的一种媒介,包含多 ...

  7. Spring Boot 系列:日志动态配置详解

    世界上最快的捷径,就是脚踏实地,本文已收录架构技术专栏关注这个喜欢分享的地方. 开源项目: 分布式监控(Gitee GVP最有价值开源项目 ):https://gitee.com/sanjianket ...

  8. MySQL锁详细讲解

    本文章向大家介绍MySQL锁详细讲解,包括数据库锁基本知识.表锁.表读锁.表写锁.行锁.MVCC.事务的隔离级别.悲观锁.乐观锁.间隙锁GAP.死锁等等,需要的朋友可以参考一下   锁的相关知识又跟存 ...

  9. Storage API简介和存储限制与逐出策略

    目录 简介 常用的客户端存储方式 data storage的类型 逐出策略 Storage API estimate persist persisted 综合使用 总结 简介 对于现代浏览器来说,为了 ...

  10. Python基础知识,新手入门看过来

    1 下载和安装Python 在开始编程之前,你需要安装Python解析器软件(这里你可能需要找人帮忙).解析器是一个可以理解你用Python语言写的指令的程序.如果没有解析器,你的计算机不会理解这些指 ...