一个 asp.net core 站点,之前运行在 linux 服务器上,运行一段时间后有时站点会挂掉,有一次的症状是 asp.net core站点在高并发下出现的“EMFILE too many open files”问题

昨天将该站点升级至 .net core 1.1(之前用的是 .net core 1.1 preview1)并部署到 windows 服务器的 IIS 上,在同一个负载均衡下部署了2台服务器。

今天早上发现其中一台服务器出现503错误,登上服务器一看,该站点的进程内存占用竟然有1.2G,而同一负载均衡中另外一台正常的服务器内存占用只有40多M。然后看了一下进程中的线程数,惊呆了——竟然有8000多个线程!而另外一台正常的服务器只有20多个线程。

接着将这台服务器从负载均衡上摘下来,这时出现了更加让人惊呆的现象——在没有请求的情况下,这个 asp.net core 站点进程的内存占用与线程数一直在增长。就像在代码中写了一个死循环,在循环中不停地创建线程。

9:30左右是1.2G内存8000多个线程,到了11:09左右内存增长到1.8G,线程数增长到1.3万,而且还在持续增长。

不仅内存与线程数在增长,而且CPU也一直在波动,这可是在没有任何请求的情况下,谁在偷偷地干活?

从目前分析的情况看,罪魁祸首可能是 EnyimMemcachedCore (支持.net core的memcached客户端,是我们从 EnyimMemcached 移植过来的),EnyimMemcachedCore 用到了 Socket 池,问题可能出在 Socket 池部分,源代码在 github 上(EnyimMemcachedCore源代码)。

目前不知道从何处下手排查这个问题,很期待您的高见。


最佳答案:

生成这个进程的dump文件,先分析分析

dump文件已生成,今天下午找时间分析一下

@dudu: 从代码来说,Socket池不太可能会出问题。这应该是其它地方出问题了。

在windbg中.load sos.dll时猛然发现这台出问题的服务器上安装的.net core版本是1.0.1,.net core sdk的版本是1.0.0-preview2-003131,而asp.net core站点程序是基于.net core 1.1编译的,那台正常的服务器昨天安装了.net core 1.1,这台出问题的服务器没有安装。应该就是这个原因引起的。

windbg的结果:

0:000> .load C:\Program Files\dotnet\shared\Microsoft.NETCore.App\1.0.1\sos.dll
0:000> !threads
ThreadCount:      8014
UnstartedThread:  0
BackgroundThread: 8013
PendingThread:    0
DeadThread:       0
Hosted Runtime:   no

解决方法:安装 ASP.NET Core Server Hosting Bundle(.NET Core 1.1包含在其中)

还是Linux上省心,服务器上根本不需要另外安装.NET Core运行环境。

@dudu: ... 原来是反向代理出问题了。这部署这么搞还有点麻烦,哪次忘了后果有点严重。

@c99: 昨天那台正常的服务器今天也出现了同样的问题,看来问题与.NET Core的版本无关。

@dudu: 那只能分析dump文件了,或者本地建个相同的环境,试试能不能模拟重现。

@c99: 在Linux服务器上也会出现这个问题,我已经在github上向微软提交了issue

问题的根源是在构造函数中用(且只能用)同步方式调用System.Net.Dns.GetHostAddressesAsync()异步方法。

相关链接:

Dns.GetHostAddressesAsync is blocking a ThreadPool thread

解决 .NET Core 中 GetHostAddressesAsync 引起的 EnyimMemcached 死锁问题

.NET Core中遇到奇怪的线程死锁问题:内存与线程数不停地增长

@dudu: 谢了。竟然是这个老问题。

微信扫描右侧二维码并关注,回复“暗号”,获取暗号在此输入并点“获取”按钮。
暗号: