环境:

dotnet core 1.0.1

CentOS 7.2

今天在服务器巡检的时候,发现一个服务大量抛出异常

异常信息为:

LockStatusPushError&&Message:One or more errors occurred. (An error occurred while sending the request. Too many open files)&InnerMessageAn error occurred while sending the request. Too many open files& at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait()
at CommonHelper.HttpHelper.HttpRequest(String Url, String Method, String ContentType, Byte[] data, Encoding encoding)
at CommonHelper.HttpHelper.PostForm(String Url, Dictionary` para, Encoding encoding)
at CommonHelper.HttpHelper.PostForm(String Url, Dictionary` para)
at DeviceService.Program.LockStatusPushMethod()

首先推断,是程序打开文件(端口或者管道)太多导致的超过系统最大限制

使用 ulimit -n 查看最大限制 发现 系统最大限制为65535 为正常值

使用 lsof | wc -l 查看当前打开文件数 发现执行非常缓慢,执行结果显示系统当前打开文件数500w++。。。。。

继而查看dotnet程序打开文件数,发现为400w++

lsof>>/tmp/lsof.log 把当前打开文件列表保存 以供问题判断。

文件导出后,发现 dotnet 程序有大量状态为 CLOSE_WAIT 的socket连接 目的地址为程序访问的HTTP服务器的80端口

dotnet         root  216r     FIFO                ,       0t0     pipe
dotnet root 217w FIFO , 0t0 pipe
dotnet root 218u IPv4 0t0 TCP txk-web:->txk-web:http (CLOSE_WAIT)
dotnet root 219r FIFO , 0t0 pipe
dotnet root 220w FIFO , 0t0 pipe
dotnet root 221u IPv4 0t0 TCP txk-web:->txk-web:http (CLOSE_WAIT)
dotnet root 222r FIFO , 0t0 pipe
dotnet root 223w FIFO , 0t0 pipe
dotnet root 224u IPv4 0t0 TCP txk-web:->txk-web:http (CLOSE_WAIT)
dotnet root 225r FIFO , 0t0 pipe
dotnet root 226w FIFO , 0t0 pipe
dotnet root 227u IPv4 0t0 TCP txk-web:->txk-web:http (CLOSE_WAIT)
dotnet root 228r FIFO , 0t0 pipe
dotnet root 229w FIFO , 0t0 pipe
dotnet root 230u IPv4 0t0 TCP txk-web:->txk-web:http (CLOSE_WAIT)
dotnet root 231r FIFO , 0t0 pipe
dotnet root 232w FIFO , 0t0 pipe
dotnet root 233u IPv4 0t0 TCP txk-web:->txk-web:http (CLOSE_WAIT)

定位原因出现在HTTP访问上

继而查看程序的日志,发现需要程序访问的HTTP接口报500错误,

出现错误后程序会重试请求(逻辑上要求重试),重试间隔为100ms,太短导致短时间内有太多请求

首先解释CLOSE_WAIT

对方主动关闭连接或者网络异常导致连接中断,这时我方的状态会变成CLOSE_WAIT 此时我方要关闭连接来使得连接正确关闭。

初步判断可能有如下原因:

1.程序抛出异常后没有释放资源

2.dotnet core 底层的 bug

3.nginx代理强制关我的连接,又没有给我关闭的确认包

4.HTTP请求超时(这个基本没可能,HTTP接口在本机)

接下来首先看代码,我的HTTP访问方法代码如下:

private static byte[] HttpRequest(string Url, string Method, string ContentType, byte[] data, Encoding encoding)
{
WebResponse response = null;
HttpWebRequest request = null;
byte[] result = null;
try
{
request = (HttpWebRequest)WebRequest.Create(Url);
request.Headers["UserAgent"] = @"Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)";
request.Accept = @"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
request.Method = Method;
request.ContentType = ContentType;
if (data != null)
{
var reqStreamAsync = request.GetRequestStreamAsync();
//reqStreamAsync.Wait();
using (Stream reqStream = reqStreamAsync.Result)
{
reqStream.Write(data, , data.Length);
reqStream.Dispose();
}
}
var reqAsync = request.GetResponseAsync();
//reqAsync.Wait();
using (response = reqAsync.Result)
{
using (Stream stream = response.GetResponseStream())
{
List<byte> byteArr = new List<byte>();
int tmp = -;
while ((tmp = stream.ReadByte()) >= )
{
byteArr.Add((byte)tmp);
}
result = byteArr.ToArray();
stream.Dispose();
}
response.Dispose();
}
}
catch (Exception ex)
{
throw;
}
finally
{
if (request != null)
{
request.Abort();
request = null;
}
if (response != null)
{
response.Dispose();
response = null;
}
}
return result;
}

看到代码 第一想法是 HttpWebRequest 没有套using也没有Dispose(),

但是尝试后发现,这个类根本就没有实现IDisposable接口,也没法手工释放,

百度之后得到结论,只能Abort(),添加到finally,顺便给WebResponse增加Dispost(),重新尝试 -------- 无效。

之后修改了Centos的/etc/sysctl.conf

增加对keepalive相关配置进行尝试

net.ipv4.tcp_keepalive_time=60
net.ipv4.tcp_keepalive_probes=2
net.ipv4.tcp_keepalive_intvl=2

然后 sysctl -p 重新加载配置,再次尝试 -------- 问题依旧。

之后又感觉是程序没有释放HttpWebRequest,

在HTTP访问方法的finally中加入GC.Collect(),希望强制回收 -------- 还是没用。

最终已经放弃寻找问题,直接把重试的地方增加延时,如果http请求出错,Thread.Sleep(10000);

临时解决此问题。

问题最终没有完美解决。

希望各位如果谁能知道问题原因,与我讨论,谢谢

2017.04.07 更新

今天更换HttpClient进行HTTP通讯

发现问题解决了。。。。

代码如下,欢迎指正~

private async static Task<byte[]> HttpRequest(string Url, HttpMethodEnum HttpMethod, string ContentType, byte[] data)
{
byte[] result = null;
try
{
using (HttpClient http = new HttpClient())
{
http.DefaultRequestHeaders.Add("User-Agent", @"Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)");
http.DefaultRequestHeaders.Add("Accept", @"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); HttpResponseMessage message = null;
if (HttpMethod == HttpMethodEnum.POST)
{
using (Stream dataStream = new MemoryStream(data ?? new byte[]))
{
using (HttpContent content = new StreamContent(dataStream))
{
content.Headers.Add("Content-Type", ContentType);
message = await http.PostAsync(Url, content);
}
}
}
else if (HttpMethod == HttpMethodEnum.GET)
{
message = await http.GetAsync(Url);
}
if (message != null && message.StatusCode == System.Net.HttpStatusCode.OK)
{
using (message)
{
using (Stream responseStream = await message.Content.ReadAsStreamAsync())
{
if (responseStream != null)
{
byte[] responseData = new byte[responseStream.Length];
responseStream.Read(responseData, , responseData.Length);
result = responseData;
}
}
}
}
}
}
catch (Exception ex)
{ throw;
}
return result;
}

dotnet Core 调用HTTP接口,系统大量CLOSE_WAIT连接问题的分析,尚未解决。的更多相关文章

  1. 详解C#泛型(二) 获取C#中方法的执行时间及其代码注入 详解C#泛型(一) 详解C#委托和事件(二) 详解C#特性和反射(四) 记一次.net core调用SOAP接口遇到的问题 C# WebRequest.Create 锚点“#”字符问题 根据内容来产生一个二维码

    详解C#泛型(二)   一.自定义泛型方法(Generic Method),将类型参数用作参数列表或返回值的类型: void MyFunc<T>() //声明具有一个类型参数的泛型方法 { ...

  2. 一次接口压力测试qps极低原因分析及解决过程

    一次接口压力测试qps极低原因分析及解决过程 9-2日在做内部的性能测试相关培训时,发现注册接口压力测试qps极低(20左右),这个性能指标远不能达到上线标准 ,经过一系列调试,最后定位 98%的时间 ...

  3. 记一次.net core调用SOAP接口遇到的问题

    背景        最近需要将一些外部的Web Service及其他SOAP接口的调用移到一个独立的WebAPI项目中,然后供其他.Net Core项目调用.之前的几个Web Service已经成功迁 ...

  4. 探索 dotnet core 为何在 Windows7 系统需要补丁的原因

    在一些 Windows 7 系统上,根据 dotnet 官方文档,需要安装上 KB2533623 补丁,才能运行 dotnet core 或 .NET 5 等应用.尽管非所有的设备都需要安装此,但这也 ...

  5. dotnet core开源博客系统XBlog介绍

    XBlog是dotnet core平台下的个人博客开源系统,它只需要通过Copy的方式即可以部署到Linux和windows系统中:如果你有安全证书那只需要简单配置一下即可提供安全的Https服务.接 ...

  6. dotnet core 调用electron来开发UI的探索

    先上仓库地址 https://github.com/lightszero/webwindow.netcore dotnet core 很喜欢,问题dotnet core 不包含GUI,经过一些尝试,觉 ...

  7. 调用支付宝接口Android客户端没有支付宝APP的情况下解决无法调用支付宝页面的问题

    这几天一直研究支付宝接口调用,因为当前应用中需要调用支付宝接口作移动支付. 遇到一个问题困扰几天,就是当我们的手机端未安装支付宝APP的时候,需要在自己应用中调用支付宝的登陆网页进行支付.我是Andr ...

  8. DotNet Core 2.2 MVC Razor 页面编译为 View.dll 文件的解决方法

    使用文本文件编辑器打开项目文件,找到: <PropertyGroup>     <TargetFramework>netcoreapp2.0</TargetFramewo ...

  9. 64位系统web项目导出excel问题分析及解决方法汇总

    最近在web项目中做了一个导出Excel功能.在导出的时候报错:检索 COM 类工厂中 CLSID 为 {00024500-0000-0000-C000-000000000046} 的组件时失败. 一 ...

随机推荐

  1. .NET Core中妙用unsafe减少gc提升字符串处理性能

    一.前言 昨天在群里讨论怎么样效率的把一个字符串进行反转,一般的情况我们都知道,只要对String对象进行操作,那么就会生成新的String对象,比如"1"+"2&quo ...

  2. HTML5拖放事件-上传图片预览功能

    主要用到的知识点有dataTransfer对象和FileReader(读取文件信息) 1.创建简单的HTML标签: <body> <div id="box"> ...

  3. python爬虫利器Selenium使用详解

    简介: 用pyhon爬取动态页面时普通的urllib2无法实现,例如下面的京东首页,随着滚动条的下拉会加载新的内容,而urllib2就无法抓取这些内容,此时就需要今天的主角selenium. Sele ...

  4. 关于input只能输入数字的两种小方法

    第一种: 直接给input标签 name赋值如下 <input name="start_price" id="start_price" type=&quo ...

  5. ADO.net参数化查询陷阱

    避免SQL漏洞注入攻击,往往采用的是参数化查询!然而在使用参数化查询中,往往为了方便就直接通过构造方法来进行数据的初始化了,然而这样就引发一个这样的问题,当参数值为0时,就出现参数为空的情况了. 一. ...

  6. 为效率而生:开源Mac版Google Authenticator认证客户端GoldenPassport

    最近运维同学为了提高安全性,用Google Authenticator对服务器加了双重认证,此后登录服务器需要先输入动态密码,在输入服务器密码.Google Authenticator相当于软toke ...

  7. 使用grunt实现web自动化

    1.grunt作用        实现压缩.编译.单元测试等重复性工作 2.需要安装的软件          第一步:从官网获取nodejs的软件包,直接双击进行安装(windows下) 第二步:打开 ...

  8. Java日志工具之SLF4J

    SLF4J全称为Simple Logging Facade for Java (简单日志门面),作为各种日志框架的简单门面或者抽象,包括 java.util.logging, log4j, logba ...

  9. 如何配置多台mysql 服务器?

    当我们数据量增大时,数据库需要进行扩张时,或者做高可用,那么我们就需要用到同时多台mysql服务器.通过配置:可以实现,一台主mysql,负责记录数据的变化,多台从mysql,查询结果.修改文件:/w ...

  10. JS获取网站StatusCode,若存在写入文件

    JS获取网站状态码,若网站存在,写入TXT文件,适用于IE. <script> //写文件      function writeFile(filename,filecontent){   ...