HttpClientHandler / HttpClient 内存泄漏

2024-02-20

我有 10-150 个长期存在的类对象,它们调用使用 HttpClient 执行简单 HTTPS API 调用的方法。 PUT 调用示例:

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 的实例”(黄色感叹号)。探查器指示已获得 root 权限的代表是AsyncCallbacks,源自 HttpWebRequest。

也可能与RemoteCertValidationCallback,与 HTTPS 证书验证有关,因为TlsStream是根中更下方的一个对象,“已处理但未 GC”。

考虑到这一切 - 我怎样才能更正确地使用 HttpClient 并避免这些内存问题?我应该强迫GC.Collect()每小时左右?我知道这被认为是不好的做法,但我不知道如何回收这些未正确处理的内存,并且这些短暂对象的更好使用模式对我来说并不明显,因为它似乎是 .NET 对象本身的缺陷。


UPDATE强迫GC.Collect()没有效果。

进程的总托管字节最多保持在 20-30 MB 左右,而进程总内存(在任务管理器中)继续攀升,表明存在非托管内存泄漏。因此,这种使用模式会造成非托管内存泄漏。

我尝试根据建议创建 HttpClient 和 HttpClientHandler 的类级实例,但这没有明显的效果。即使我将它们设置为类级别,它们仍然会重新创建并且很少重新使用,因为代理设置经常需要更改。一旦发起请求,HttpClientHandler 就不允许修改代理设置或任何属性,因此我不断地重新创建处理程序,就像最初对独立的处理程序所做的那样using声明。

HttpClienthandler 仍然通过 AsyncCallback -> HttpWebRequest 的“直接委托根”进行处理。我开始怀疑 HttpClient 是否不是为快速请求和短期对象而设计的。没有尽头......希望有人提出建议,使 HttpClientHandler 的使用可行。


Memory profiler shots: Initial stack indicating that HttpClientHandler is the root issue, having 304 live instances that should have been GC'd


使用 Alexandr Nikitin 的重现形式,我发现这似乎只有当 HttpClient 是一个短暂的对象时才会发生。如果你让处理程序和客户端长期存在,这似乎不会发生:

using System;
using System.Net.Http;
using System.Threading.Tasks;

namespace HttpClientMemoryLeak
{
    using System.Net;
    using System.Threading;

    class Program
    {
        static HttpClientHandler handler = new HttpClientHandler();

        private static HttpClient client = new HttpClient(handler);

        public static async Task TestMethod()
        {
            try
            {
                using (var response = await client.PutAsync("http://localhost/any/url", null))
                {
                }
            }
            catch
            {
            }
        }

        static void Main(string[] args)
        {
            for (int i = 0; i < 1000000; i++)
            {
                Thread.Sleep(10);
                TestMethod();
            }

            Console.WriteLine("Finished!");
            Console.ReadKey();
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

HttpClientHandler / HttpClient 内存泄漏 的相关文章

随机推荐

  • Vim Fugitive:Gblame 重责选项

    我最近一直在使用Fugitive的Gblame 但不太明白 reblame 的作用 有人可以更清楚地描述这些选项的作用吗 reblame at commit reblame at count th first grandparent P r
  • 为什么赋值表达式 [String x = (x = y)] 的变量初始化可以编译?

    这个如何编译才不会报错呢 据我了解 编译器检查变量的类型 在本例中String 然后查看右侧表达式的类型是否对应于变量的类型 或至少是一个子类型 但让我们坚持使用简单的情况String类 因为它是最后的 public class InitC
  • 在实体框架中自定义类型映射

    我正在使用 EF5 Code First 并尝试存储 IPAddress 对象 如果您尝试直接执行此操作 EF 会将其存储为两列 FIELDNAME Address 和 FIELDNAME Scope 不幸的是 这不足以存储 IPv4 地址
  • 寻找基于 Django 类的视图并在单个页面上具有多个表单示例

    我一直在寻找如何使用较新的基于 Django 类的视图方法在一页上显示 2 个独特的表单 有人可以参考一下吗 或者提供一个基本的例子 谷歌并没有因此成为我的 朋友 关键是你甚至不必使用其中之一FormView处理表单的子类 您只需添加手动处
  • BluetoothLEDevice.FromIdAsync 返回 null

    这是用于获取 BLE 设备的 UWP 代码 为什么我在某些设备上得到 bleDevice null 我没有找到任何解释这一点的文档 var devices await DeviceInformation FindAllAsync Bluet
  • Xcode - Segue 问题

    我一直在努力让segue继续工作 我写了以下内容 但由于某种原因 preparesegue 方法不会触发 我已经阅读了其他相关的帖子 但我无法让它启动 而且同样重要的是 我需要的变量没有被传输 m file implementation C
  • jQuery - 检查是否第一次点击

    我有 2 个函数 A 和 B 只需单击一次 div 即可调用 我只需要在第一次单击时调用函数 A 并在单击时调用函数 B 我怎么能这样做呢 更简单的解决方案 element one click function Call A click f
  • 调整 Datagridview 上的 Rowheader 属性

    在 Winforms DataGridView 中 我该如何 删除行标题上的箭头 我需要显示行标题文本 所以我不能简单地设置RowHeadersVisible false 以编程方式调整行标题的宽度 我通过代码设置行标题 因此我需要调整宽度
  • 通过Matplotlib中的OO接口获取图形管理器

    我希望能够获取创建的图形的figure manager 例如我可以使用 pyplot 界面来完成此操作 from pylab import figure plot arange 100 mngr get current fig manage
  • MS Access XML 从文本或流而不是文件导入?

    有什么简单的方法可以完成与 Application ImportXML 等效的操作 但将 XML 作为字符串或文本流而不是文件 在 Access 2003 中 我想将记录插入到一 个包含许多字段的表中 其中包含来自应用程序中不同位置的数据
  • spring资源是文件还是目录?

    我正在使用 spring Resource API 并使用 ResourcePatternResolver 来扫描我的类路径中的文件 在一种情况下 扫描会拾取预构建 jar 中的一些目录和文件以及文件系统上的一些目录和文件 在任何一种情况下
  • AppDomains 与强大的服务器

    经过一些研究后 AppDomains 似乎并不是真正构建托管服务器的工具 根据我的理解 如果创建的AppDomain中存在未处理的异常 如果从创建的AppDomain中的线程抛出异常 托管服务器仍然会崩溃 因此 在这种情况下 如果托管服务器
  • Pandas:将列与数据帧的所有其他列进行比较

    我有一个场景 我有新的受试者正在测试一系列特征 其中结果都是字符串分类值 测试完成后 我需要将新数据集与所有受试者的主数据集进行比较 并寻找给定阈值 例如 90 的相似性 匹配 因此 我需要能够以尽可能最佳的性能对新数据集中的每个新主题与主
  • 使用 Google 日历 API 发送邀请

    我有一个 Java Spring API 我想在其中集成 Google 日历 任务 基本上为两名与会者 用户 创建一个活动并向他们发送邀请 并可选择接受 拒绝 标准 GCalendar 邀请 我在这里尝试了这个例子 https develo
  • 当 super() 被调用时,元类如何与 MRO 列表一起工作?

    我对以下代码示例感到非常困惑 class Meta 1 type def call cls a kw line 1 print entering Meta 1 call print cls line 4 print cls mro line
  • RESTful Web 服务、Spring-WS 有效负载或 Spring 3 MVC REST 控制器采用哪种方式?

    我是初学者Spring Webservices 我正在尝试使用创建合同优先的网络服务spring ws 2 0 我已经做好了web xml MessageDispatcherServlet 配置 我的合约设计 XSD 生成JAXB类和服务实
  • JavaScript 中的 Math.random 和 Web 编程

    根据这个堆栈溢出线程 https stackoverflow com questions 10361466 what algorithm does math random useJavaScript 中的 Math random 取决于浏览
  • 如何使用 VBA 在 IE11 中自动弹出“另存为”对话框?

    我正在尝试下载一些有关碳排放的数据 我可以通过 URL 预加载包含相关设置的页面 它加载正常 我可以通过其 ID 单击确定按钮 然后在底部看到 IE11 打开 保存 取消对话框 我已经尝试了使用 FindWindows 32770 的所有建
  • CKAN 安装:粘贴错误

    在 OSX 10 9 上本地安装 CKAN 基于http docs ckan org en latest maintaining installing install from source html http docs ckan org
  • HttpClientHandler / HttpClient 内存泄漏

    我有 10 150 个长期存在的类对象 它们调用使用 HttpClient 执行简单 HTTPS API 调用的方法 PUT 调用示例 using HttpClientHandler handler new HttpClientHandle