更新:后来升级至 .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 。

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

就是上面的代码中“漏”写了 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. 【leetcode】1074. Number of Submatrices That Sum to Target

    题目如下: Given a matrix, and a target, return the number of non-empty submatrices that sum to target. A ...

  2. LeetCode--139--单词拆分(python)

    给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词. 说明: 拆分时可以重复使用字典中的单词.你可以假设字典中没有重复的 ...

  3. java基础拓展

    1. 作用域:public private protected 默认的区别 public:在同一项目中,被public修饰的在任何地方都可以被调用 private:被private修饰的,只能在本类中 ...

  4. pytest-生成测试报告

    import pytest """ 使用pytest编写用例,必须遵守以下规则: (1)测试文件名必须以"test_"开头或者"_test& ...

  5. 状态管理工具对比vuex、redux、flux

    1.为什么要使用状态管路工具  在跨层级的组件之间传递信息,尤其是复杂的组件会非常困难.也不利于开发和维护,这时我们就a需要用到状态管理工具.     2.Flux

  6. 3D Computer Grapihcs Using OpenGL - 09 Enable Depth Test

    启用Depth Test OpenGL是个3D绘图API,也就是说不只有xy坐标轴,还有第三个坐标轴z,z轴的方向是垂直于屏幕,指向屏幕内. 靠近人眼的方向是负方向,标准化设备坐标的最小值是-1, 最 ...

  7. 170830-关于JdbcTemplate的练习题以及其中的问题

    实验1:测试数据源 在spring文件中配置: 测试数据源: 结果: 实验2:将emp_id=5的记录的salary字段更新为1300.00[更新操作] update函数中,第一个是sql语句,后面的 ...

  8. [CSP-S模拟测试]:购物(柯朵莉树)

    题目描述 $visit_world$有一个商店,商店里卖$N$个商品,第$i$个的价格为$a[i]$我们称一个正整数$K$是美妙的,当且仅当我们可以在商店里选购若干个商品,使得价格之和落在区间$[K, ...

  9. Java 中冒泡排序

    package com.nf147.test; public class sort { public static void main(String[] args) { int arr[] = {11 ...

  10. Mybatis一对一关联查询

    有两张表,老师表teacher和班级表class,一个class班级对应一个teacher,一个teacher对应一个class 需求是根据班级id查询班级信息(带老师的信息) 创建teacher和c ...