更新:后来升级至 .NET Core 2.2 Preview 3 ,并将 System.Net.Http 升级至 4.3.4 之后没出现这个问题,问题与 https://github.com/dotnet/corefx/pull/32568 有关。

以下内容是当时的错误判断。

今天上午的故障之后,我们 review 了代码,通过压力测试重现问题,分析验证,最终找到了问题的真正原因 —— 在 ASP.NET Core 程序中调用 async 方法时没加 await 。

public async Task<IActionResult> GetRecommDocuments()
{
//...
ShowItem(docs, app); //async方法,其中用到了HttpClient
return Ok(docs);
}

就是上面的代码中“漏”写了 await ,不是粗心漏写,是故意为之。我们不关心调用 ShowItem 的结果,只要能执行就行,即使执行失败也可以接受。不加 await 可以让 GetRecommDocuments 方法调用 ShowItem 之后无需等待继续执行从而提高响应速度,但是没想到这一招偷工减料,竟然抽空了服务器的 TCP 连接资源,让整个服务器大厦轰然倒塌。

以下删除线部分的分析是错误的,真正原因有待进一步追踪。

开始从 async/await 的角度怎么也想不通 —— 少一个 await 怎么会如此严重后果,后来突然想到罪魁祸首不在 async/await 而在依赖注入(DI)。GetRecommDocuments 中的 HttpClient 实例是通过构造函数的 IHttpClientFactory 注入的,注入的 HttpClient 实例的生命周期是 Scoped (当前请求范围),本来正常情况下一个请求处理结束,HttpClient 实例会被 DI 容器 Dispose,所使用的 Socket 连接会被放回连接池,但是由于没加 await ,让 ShowItem 不走正常路,DI 容器在请求处理结束时跟踪不到 ShowItem 中的 HttpClient 实例,也就不会进行 Dispose 。结果来一个请求,IHttpClientFactory 就创建一个 HttpClient 实例,每个 HttpClient 实例都占用一个新的 TCP 连接,直至拖垮服务器。

随着软件开发技术的发展,开发效率越来越高了,要写的代码越来越少了,但要考虑的问题却越来越多了。虽然我们每天都在用着 .NET Core ,但由于其内部工作机制不够熟悉,原以为“巧夺天工”的一招却酿成大错,我们会牢记这次教训,进一步地对 .NET Core 刨根问底 。

放弃等待,故障到来:少一个 await 引发的 tcp 连接泄漏故障的更多相关文章

  1. 一个人也可以建立 TCP 连接呢

    今天(恰巧是今天)看到有人在 SegmentFault 上问「TCP server 为什么一个端口可以建立多个连接?」.提问者认为 client 端就不能使用相同的本地端口了.理论上来说,确定一条链路 ...

  2. 第二篇:一个经典的比喻( 关于TCP连接API )

    前言 编程是对现实世界的模拟,网络通信自然也是对现实世界通信的模拟.可以将网络通信中使用的各种API和对现实世界中的各种通信设备进行通讯的操作进行对比以加深理解. 对比 socket() 函数 vs ...

  3. 一个经典的比喻( 关于TCP连接API )

    前言 编程是对现实世界的模拟,网络通信自然也是对现实世界通信的模拟.可以将网络通信中使用的各种API和对现实世界中的各种通信设备进行通讯的操作进行对比以加深理解. 对比 socket() 函数 vs ...

  4. 可能会搞砸你的面试:你知道一个TCP连接上能发起多少个HTTP请求吗?

    本文由原作者松若章原创发布,作者主页:zhihu.com/people/hrsonion/posts,感谢原作者的无私分享. 1.引言 一道经典的面试题是:从 URL 在浏览器被被输入到页面展现的过程 ...

  5. 夺命连环问:一个 TCP 连接可以发多少个 HTTP 请求?

    曾经有这么一道面试题:从 URL 在浏览器被被输入到页面展现的过程中发生了什么? 相信大多数准备过的同学都能回答出来,但是如果继续问:收到的 HTML 如果包含几十个图片标签,这些图片是以什么方式.什 ...

  6. 一个 TCP 连接可以发多少个 HTTP 请求?

    曾经有这么一道经典面试题:从 URL 在浏览器被被输入到页面展现的过程中发生了什么?相信大多数准备过的同学都能回答出来,但是如果继续问:收到的 HTML 如果包含几十个图片标签,这些图片是以什么方式. ...

  7. 懵圈了,面试官问一个 TCP 连接可发多少个 HTTP 请求?

    作者:松若章 https://zhuanlan.zhihu.com/p/61423830 一道经典的面试题是从 URL 在浏览器被被输入到页面展现的过程中发生了什么,大多数回答都是说请求响应之后 DO ...

  8. 一个tcp连接可以发多少http请求

    -----来自:松若章 -----zhuanlan.zhihu.com/p/61423830 曾经有这么一道经典面试题:从 URL 在浏览器被被输入到页面展现的过程中发生了什么?相信大多数准备过的同学 ...

  9. 面试官:一个 TCP 连接可以发多少个 HTTP 请求?

      曾经有这么一道面试题:从 URL 在浏览器被被输入到页面展现的过程中发生了什么? 相信大多数准备过的同学都能回答出来,但是如果继续问:收到的 HTML 如果包含几十个图片标签,这些图片是以什么方式 ...

随机推荐

  1. vue 常见错的可能原因

    标签或者组件名写错 Unknown custom element: <h> - did you register the component correctly? For recursiv ...

  2. Python自动化运维技术与最佳实现

    第一章 系统基础信息模块详解 系统基础信息采集模块最为监控模块的重要组成部分,能够帮助运维人员了解当前系统的健康程度,同时也是衡量业务的服务质量的依据,比如系统资源吃紧,会直接影响业务的质量以及用户的 ...

  3. Java——方法重写

  4. springboot-mybatis-demo遇到的坑

    目录 前言 问题&解决 1.初始化Maven工程过慢 2.Spring Boot 集成druid时时区问题和连接超时问题 3.完整工程下载 前言 环境: java version " ...

  5. [洛谷2257]YY的GCD 题解

    整理题目转化为数学语言 题目要我们求: \[\sum_{i=1}^n\sum_{i=1}^m[gcd(i,j)=p]\] 其中 \[p\in\text{质数集合}\] 这样表示显然不是很好,所以我们需 ...

  6. HDU-6709 Fishing Master

    Description Heard that eom is a fishing MASTER, you want to acknowledge him as your mentor. As every ...

  7. js刷新当前页面的5种方式

    1. reload reload 方法,该方法强迫浏览器刷新当前页面.语法:location.reload([bForceGet])   参数: bForceGet, 可选参数, 默认为 false, ...

  8. [CSP-S模拟测试]:ants(回滚莫队)

    题目描述 然而贪玩的$dirty$又开始了他的第三个游戏. $dirty$抓来了$n$只蚂蚁,并且赋予每只蚂蚁不同的编号,编号从$1$到$n$.最开始,它们按某个顺序排成一列.现在$dirty$想要进 ...

  9. 图解SQLSERVER联合查询和连接查询的区别

      相信很多人都会用SQLSERVER联合查询和连接查询,但是用起来不一定都得心应手,对于其中的原理可能就模糊不清了,要想很牢固地掌握和运用SQL联合查询和连接查询机制,必须对其根本原理有很清晰认识, ...

  10. CMD模块打包部署总结

    目前线上系统利用Seajs做模板化,但是没有对js和css进行打包,在这次简历搜索优化项目里我尝试对gulp插件对Seajs模块打包. 安装gulp和相关插件 npm install -g gulp ...