dotnet Core 调用HTTP接口,系统大量CLOSE_WAIT连接问题的分析,尚未解决。
环境:
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连接问题的分析,尚未解决。的更多相关文章
- 详解C#泛型(二) 获取C#中方法的执行时间及其代码注入 详解C#泛型(一) 详解C#委托和事件(二) 详解C#特性和反射(四) 记一次.net core调用SOAP接口遇到的问题 C# WebRequest.Create 锚点“#”字符问题 根据内容来产生一个二维码
详解C#泛型(二) 一.自定义泛型方法(Generic Method),将类型参数用作参数列表或返回值的类型: void MyFunc<T>() //声明具有一个类型参数的泛型方法 { ...
- 一次接口压力测试qps极低原因分析及解决过程
一次接口压力测试qps极低原因分析及解决过程 9-2日在做内部的性能测试相关培训时,发现注册接口压力测试qps极低(20左右),这个性能指标远不能达到上线标准 ,经过一系列调试,最后定位 98%的时间 ...
- 记一次.net core调用SOAP接口遇到的问题
背景 最近需要将一些外部的Web Service及其他SOAP接口的调用移到一个独立的WebAPI项目中,然后供其他.Net Core项目调用.之前的几个Web Service已经成功迁 ...
- 探索 dotnet core 为何在 Windows7 系统需要补丁的原因
在一些 Windows 7 系统上,根据 dotnet 官方文档,需要安装上 KB2533623 补丁,才能运行 dotnet core 或 .NET 5 等应用.尽管非所有的设备都需要安装此,但这也 ...
- dotnet core开源博客系统XBlog介绍
XBlog是dotnet core平台下的个人博客开源系统,它只需要通过Copy的方式即可以部署到Linux和windows系统中:如果你有安全证书那只需要简单配置一下即可提供安全的Https服务.接 ...
- dotnet core 调用electron来开发UI的探索
先上仓库地址 https://github.com/lightszero/webwindow.netcore dotnet core 很喜欢,问题dotnet core 不包含GUI,经过一些尝试,觉 ...
- 调用支付宝接口Android客户端没有支付宝APP的情况下解决无法调用支付宝页面的问题
这几天一直研究支付宝接口调用,因为当前应用中需要调用支付宝接口作移动支付. 遇到一个问题困扰几天,就是当我们的手机端未安装支付宝APP的时候,需要在自己应用中调用支付宝的登陆网页进行支付.我是Andr ...
- DotNet Core 2.2 MVC Razor 页面编译为 View.dll 文件的解决方法
使用文本文件编辑器打开项目文件,找到: <PropertyGroup> <TargetFramework>netcoreapp2.0</TargetFramewo ...
- 64位系统web项目导出excel问题分析及解决方法汇总
最近在web项目中做了一个导出Excel功能.在导出的时候报错:检索 COM 类工厂中 CLSID 为 {00024500-0000-0000-C000-000000000046} 的组件时失败. 一 ...
随机推荐
- devexpress实现单元格合并以及依据条件合并单元格
1.devexpress实现单元格合并非常的简单,只要设置属性[AllowCellMerge=True]就可以了,实现效果如下图: 2.但是在具体要求中并非需要所有的相同单元格都合并,可能需要其他的条 ...
- BZOJ 2324: [ZJOI2011]营救皮卡丘(带上下限的最小费用最大流)
这道题么= =还是有些恶心的,第一次写带上下界的网络流,整个人都萌萌哒~~~ 首先先预处理得最短路后 直接用费用流做就行了。 第一次写,还是挺好写的= = CODE: #include<cstd ...
- 如何发布第一个WP8.1程序(VisualStudio2015)
学习WP开发有一段时间了,近一个月开始着手开发程序,并在开发程序中不断地学习(有一定的基础后,边开发程序,边学习是很好的,能练习运用所学的知识,并能在遇到问题后上网上资料不断地学习,很有效果,因为老是 ...
- 开源OSS.Social微信项目进阶介绍
在开源OSS.Social微信项目解析的随笔中,我简单给大家分享了进行中微信项目的概要设计,主要在讲述解决思路和过程,没有详细实现和使用介绍.本着不能马虎的态度,这篇文章我来给大家分解一下项目结构,使 ...
- 线程协作方法sleep、yield、wait、join
sleep(休眠) 当t线程调用Thread.sleep()时,会让线程t休眠指定时间 Thread.sleep() 和 Thread.currentThread().sleep() 效果 ...
- 第八篇 一个用JS写的省市县三级联动
前些天,做网站用需要用到一个省市县的三级联动,数据要从数据库里面读取,我想了下思路,动手写了下来. 一.思路 js利用Ajax读取控制器里面的函数,利用函数读取存储过程,返回 ...
- 删除bin后,Eclipse重新编译项目
今天做"用java.util.Properties类读写配置文件"Demo时,在编译项目时由于配置资源文件一起写入bin了.而Demo修改了配置文件,从新运行时配置文件不再更新,于 ...
- vs2017 .net core WebApp 去掉ApplicationInsights
vs2017新建的 .net core WebApp都内置了这个遥测中间件进去,嗯,用AZURE的话是不错能无缝支持.但不用AZURE就没什么用了. 为了不占地方和提高一点点初始启动的速度,对新建的项 ...
- iOS实现视频和图片的上传
关于iOS如何实现视频和图片的上传, 我们先理清下思路 思路: #1. 如何获取图片? #2. 如何获取视频? #3. 如何把图片存到缓存路径中? #4. 如何把视频存到缓存路径中? #5. 如何上传 ...
- JS获取网站StatusCode,若存在写入文件
JS获取网站状态码,若网站存在,写入TXT文件,适用于IE. <script> //写文件 function writeFile(filename,filecontent){ ...