我有任何地方从10-150长的生活类对象调用使用HttpClient执行简单的HTTPS API调用的方法。一个PUT调用示例:HttpClientHandler/HttpClient内存泄漏
using (HttpClientHandler handler = new HttpClientHandler())
{
handler.UseCookies = true;
handler.CookieContainer = _Cookies;
using (HttpClient client = new HttpClient(handler, true))
{
client.Timeout = new TimeSpan(0, 0, (int)(SettingsData.Values.ProxyTimeout * 1.5));
client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", Statics.UserAgent);
try
{
using (StringContent sData = new StringContent(data, Encoding.UTF8, contentType))
using (HttpResponseMessage response = await client.PutAsync(url, sData))
{
using (var content = response.Content)
{
ret = await content.ReadAsStringAsync();
}
}
}
catch (ThreadAbortException)
{
throw;
}
catch (Exception ex)
{
LastErrorText = ex.Message;
}
}
}
2-3小时后运行这些方法,其中包括通过using
陈述妥善处置,该计划已穆斯特1GB的内存,1.5GB,并最终以各种崩溃的内存不足错误。很多时候,连接都是通过不可靠的代理服务器进行的,因此连接可能无法按预期完成(超时和其他错误很常见)。
.NET内存事件探查器指出HttpClientHandler
是这里的主要问题,指出它具有'直接代表根'的废弃实例(红色感叹号)和'已处理但仍未GCed的实例'(黄色感叹号)。探查器指示的代表已根据AsyncCallback
s,源自HttpWebRequest。
它也可能与RemoteCertValidationCallback
有关,它与HTTPS证书验证有关,因为TlsStream
是“Disposed but not GCed”根目录下的一个对象。
考虑到这一切 - 我如何更正确地使用HttpClient并避免这些内存问题?我应该每小时强制一次GC.Collect()
吗?我知道这被认为是不好的做法,但我不知道如何回收这个不太适合处理的内存,并且对于这些短期对象来说更好的使用模式对我来说并不明显,因为它似乎成为.NET对象本身的一个缺陷。
UPDATE 强制GC.Collect()
没有效果。
进程的托管字节总数最多保持20-30 MB左右,而进程整体内存(在任务管理器中)持续攀升,表明存在非托管内存泄漏。因此,这种使用模式正在创建一个非托管内存泄漏。
我已经尝试创建HttpClient和HttpClientHandler的每个建议的类级别的实例,但是这没有可观的效果。即使我将它们设置为课程级别,由于代理设置通常需要更改,因此它们仍会重新创建并很少重复使用。一旦请求被启动,HttpClientHandler不允许修改代理设置或任何属性,所以我不断地重新创建处理程序,就像最初对独立的using
声明所做的那样。
HttpClienthandler仍然与“直接委托根”处置为AsyncCallback - > HttpWebRequest。我开始怀疑,也许HttpClient不是专为快速请求和短期生活对象而设计的。没有尽头,希望有人建议使用HttpClientHandler可行。
存储器剖析镜头:
你为什么要在每次调用中放置'HttpClientHandler'和'HttpClient'? 'HttpClient'应该是整个应用程序中的一个长寿命对象(因此,'HttpClientHandler'也应该是这样的,这样,你只需要生成一个实例。 –
我剪掉了代码中不重要的部分,但头部根据请求而波动,并且代理会根据连接成功/失败而改变,HttpClientHandler对象的大量维护都会发生,因此我认为每次只重新创建一次会比较简单,但它仍然不能满足问题为什么这些对象不能重复创建而不会重复创建 – user1111380
如果确实尝试了GC.collect(),您是否看到正在收集这些TlsStream对象? – zaitsman