更新:后来升级至 .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. [CF1082G]Petya and Graph:最小割

    分析 发这篇博客的目的就是要让你们知道博主到底有多菜. 类似于[NOI2006]最大获利.(明明就是一模一样好吧!) 不知道怎么了,半秒就想到用网络流,却没想出怎么建图. 连这么简单的题都没做出来,我 ...

  2. Java网络编程与NIO详解10:深度解读Tomcat中的NIO模型

    本文转自:http://www.sohu.com/a/203838233_827544 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 ht ...

  3. 前端每日实战:138# 视频演示如何用纯 CSS 创作一张 iPhone 价格信息图

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/OorLGZ 可交互视频 此视频是可 ...

  4. CruiseControl.NET配置

    CruiseControl.NET简介 CruiseControl.NET是.net平台下,一个开源的自动化持续集成工具. 它是一个程序套件,但其核心是一个叫做CruiseControl.NET Se ...

  5. shell 中使用正则表达式

    ls | xargs echo | sed 's/.*\(\w\+\)\s\(\w\+\s\)*\1d.*/\1/' 说明 \w\+表示一段连续的字符串 \s\+ 一个或者多个空格 \s* 0个或者多 ...

  6. Mysql数据库密码忘记的解决办法

    密码忘记——破解密码 跳过授权方式,直接登录!! 1.以管理员身份打开cmd 2.停掉mysql服务端 C:\WINDOWS\system32>net stop mysql MySQL 服务正在 ...

  7. DesignWare I2C模块的验证

    I2C通信协议主要同一块板上芯片间的通信,因此速度不是很高.SCL为时钟线,SDA为数据线.时钟由主设备发送给从设备,数据可以在两设备间互传. 在测试DW_I2C模块时,如果外面都包了一层,在tb中只 ...

  8. 转)delphi chrome cef3 控件学习笔记 (二)

    (转)delphi chrome cef3 控件学习笔记 (二) https://blog.csdn.net/risesoft2012/article/details/51260832 原创 2016 ...

  9. [转载]OpenSSL中文手册之命令行详解(未完待续)

     声明:OpenSSL之命令行详解是根据卢队长发布在https://blog.csdn.net/as3luyuan123/article/details/16105475的系列文章整理修改而成,我自己 ...

  10. VGA时序及其原理(转载)

    显示器扫描方式分为逐行扫描和隔行扫描:逐行扫描是扫描从屏幕左上角一点开始,从左像右逐点扫描,每扫描完一行,电子束回到屏幕的左边下一行的起始位置,在这期间,CRT对电子束进行消隐,每行结束时,用行同步信 ...