环境:

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. 简述.jpg .Gif .png-8 .png-24的区别

    最近有很多朋友在开发过程中有时候会遇到图片加载不清晰,透明度失真,或者对图片进行操作之后造成图片损耗的现象,在这里给大家简单介绍一下常用的几种图片格式之间的区别 Gif格式特点: 1.透明性,Gif是 ...

  2. Ansible详解(一)

    简介 Ansible是一个简单的自动化运维管理工具,基于Python语言实现,由Paramiko和PyYAML两个关键模块构建,可用于自动化部署应用.配置.编排task(持续交付.无宕机更新等).主版 ...

  3. 关于volatile的可见性和禁止指令重排序的疑惑

    在学习volatile语义的可见性和禁止指令重排序的相关测试中,发现并不能体现出禁止指令重排序的特性 实验代码如下 package com.aaron.beginner.multithread.vol ...

  4. 阿里云开发之OSS数据迁移

    最近由于项目需求,需要将一个aliyun账号下的oss数据导入到两一个aliyun账号下的oss,经过一番坎坷,最终搞定. 1.查看oss数据迁移官方文档,我是在本地windows电脑上进行操作的,先 ...

  5. Java多线程——深入重入锁ReentrantLock

    简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...

  6. 剑指offer编程题Java实现——面试题12相关题大数的加法、减法、乘法问题的实现

    用字符串或者数组表示大数是一种很简单有效的表示方式.在打印1到最大的n为数的问题上采用的是使用数组表示大数的方式.在相关题实现任意两个整数的加法.减法.乘法的实现中,采用字符串对大数进行表示,不过在具 ...

  7. java中的ConcurrentModificationException异常

    先看这样一段代码: List<String> list = new ArrayList<String>(); list.add("1"); list.add ...

  8. 使用java.util.Properties类读写配置文件

    J2SE 1.5 以前的版本要求直接使用 XML 解析器来装载配置文件并存储设置,虽说也并非难事,相比 java.util.Properties却要做额外的解析工作.而java.util.Proper ...

  9. KoaHub.js是基于 Koa.js 平台的 Node.js web 快速开发框架

    koahubjs KoaHub.js -- 基于 Koa.js 平台的 Node.js web 快速开发框架.可以直接在项目里使用 ES6/7(Generator Function, Class, A ...

  10. ST 单元测试之maven安装

    junit是用于单元测试的jar包,可以直接下载然后粘贴至lib目录,maven是专门的包管理工具,所以尝试安装maven. 安装maven之前需要先安装好java以及eclipse,在相应的官网下载 ...