http是我们最常见的客户端/服务端传输协议,在golang中,默认的net/http包有一些坑位,需要调整以获得更加性能。

在golang程序中,我也遇到因为不合理使用 http client导致的程序崩溃问题。

坑:1:默认的HttpClient

默认的HttpClient不包含请求超时时间,如果你使用http.Get(url)或者&Client{}, 这将会使用http.DefaultClient,这个结构体内no timeout

假如发出请求的服务端API有问题:没有及时响应httpclient请求但是保持了连接, 在高并发情况下,打开的连接数会持续增长,最终导致客户端服务器资源到达瓶颈。

解决方案:不要使用默认的HTTPClient, 总是为HttpClient指定Timeout

	client := &http.Client{
Timeout: 10 * time.Second,
}

HttpClient Timeout包括连接、重定向(如果有)、从Response Body读取的时间,内置定时器会在Get,Head、Post、Do 方法之后继续运行,直到读取完Response.Body。

这里有个有关HttpClient Timeout的排障问题,你可参考。


.NET HttpClient Timeout: The default value is 100,000 milliseconds (100 seconds).

坑2:默认的Http Transport

目前常见的HttpClient(.NET Core,golang) 都会有连接池的概念, 客户端会尽量复用池中已经建立的连接。

go的Transport 可理解为连接池中的连接。

// DefaultTransport is the default implementation of Transport and is
// used by DefaultClient. It establishes network connections as needed
// and caches them for reuse by subsequent calls. It uses HTTP proxies
// as directed by the $HTTP_PROXY and $NO_PROXY (or $http_proxy and
// $no_proxy) environment variables.
var DefaultTransport RoundTripper = &Transport{
Proxy: ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
} // DefaultMaxIdleConnsPerHost is the default value of Transport's
// MaxIdleConnsPerHost.
const DefaultMaxIdleConnsPerHost = 2

默认的

  • golang的Http Client连接池有100个连接,
  • 每个连接默认的空闲时间90s(90s内有请求过来,可以复用该连接)
  • 上面的KeepAlive是tcp探活的时间间隔,并不是我们HTTP连接复用的 Keep-Alive

有坑位的是DefaultMaxIdleConnsPerHost=2:每个主机(服务)保留的空闲连接数是2个。

这意味着,当首次针对某主机发出100个请求,这100个请求会同时利用连接池中的100个连接,之后因为这个限制,客户端被迫主动关闭98个连接,此时客户端机器会出现98 个time_wait(time_Wait会存在2MSL,大概2min,占用了机器资源),

新的请求被迫新开连接,然后立马主动关闭,只维持2个复用连接, 最后造成客户端机器存在大量time_Wait

从我司实际项目看,造成CPU高涨,并且无法新开连接。

解决方案:不要使用默认Transport,增加MaxIdleConnsPerHost


本人回顾了.NET HttpClient,貌似不用刻意关闭这个值。

实际上,.NET也存在这个MaxIdleConnectionPerServer配置,但是.NET Core这个PerServer被设置为int.maxvalue,所以我们无需关注,.NET真香。

我的收获

通过本文,我们谈到了golang HttpClient的2个坑位、由坑位导致的现象和排障思路,各位看官,有则改之无则加勉。

并且我们对比了.NET Core语言中HttpClient的默认配置,各位看官心中有数。

Gopher必读:HttpClient的两个坑位的更多相关文章

  1. 【干货】基于镜像部署的Gitlab-CI/CD实践和坑位指南

    引言 看过前文的博友可能注意到我是把 部署dll文件拷贝到生产机器,之后在生产机器上使用docker-compose即时创建镜像, 并没有完成CI/CD, 只是在原来传统部署方式下 将部署文件容器化. ...

  2. 两个坑-Linux下Network-Manager有线未托管-DNS resolv.conf文件开机被清空

    Linux里面有两套管理网络连接的方案: 1./etc/network/interfaces(/etc/init.d/networking) 2.Network-Manager 两套方案是冲突的,不能 ...

  3. iscroll遇到的两个坑

    最近移动端闪付遇到的两个坑做下总结: 1.使用iscroll后,滑动并没有生效 解决方案: 首先要查看:结构是否正确: <div id="wrapper">   //w ...

  4. 记自己在spring中使用redis遇到的两个坑

    本人在spring中使用redis作为缓存时,遇到两个坑,现在记录如下,算是作为自己的备忘吧,文笔不好,望大家见谅: 一.配置文件 <!-- 加载Properties文件 --> < ...

  5. [PHP] 算法-两个n位的二进制整数相加问题PHP实现

    两个n位二进制数分别存储在两个n元数组A和B中,这两个整数的和存在一个n+1元的数组C中答:此问题主要是考察相加进位的问题,元素1+1 =0 并且往前进一位ADD-BINARY(A,B) C=new ...

  6. MySql 5.7安装(随机密码,修改默认密码)两个坑

    MySql 5.7安装(随机密码,修改默认密 下载了MySql 最新版本,安装的过程中,发现了很多新特性 1.data目录不见了 在进行my-default.ini配置的时候 (需要配置 # base ...

  7. .net core HttpClient 使用之掉坑解析(一)

    一.前言 在我们开发当中经常需要向特定URL地址发送Http请求操作,在.net core 中对httpClient使用不当会造成灾难性的问题,这篇文章主要来分享.net core中通过IHttpCl ...

  8. jQueryUI Draggable 和 Droppable 配合使用时遇到的两个坑

    jQueryUI 的 拖拽插件极大的方便了开发者对拖拽功能的实现,但是官方教程给的太笼统,在具体实现的时候很多地方不明确,这里说一下我遇到的两个 "小坑": 1:Draggable ...

  9. redis主从遇到的两个坑

    最近在使用redis主从的时候做了下面两件事情: 1 希望redis主从从操作上分析,所有写操作都在master上写,所有读操作都在从上读. 2 由于redis的从是放在本地的,所以有的key的读写操 ...

随机推荐

  1. actf2020upload

    actf2020upload .php后缀过滤 1.上传文件,要求后缀为.png/.gif/.jpg 2.抓包,后缀改成.phtml后放行,上传成功,访问地址,根目录下找到flag

  2. Python 根据id生成唯一码

    Python 根据id生成唯一码 最近业务中遇到需要分享某个文案,复制文案打开APP需要提取文案中包含的id,但又不想明文暴露id,所以需要对id进行加密,很想让前端来做,可惜多个前端协调起来不方便( ...

  3. MySQL环境变量配置方法

    MySQL配置方法 下载免安装版本的MySQL数据库,大家根据自己的开发环境下载对应版本的数据库,我在此举例的是Windows系统下的配置方法,下载地址如下: https://dev.mysql.co ...

  4. golang中的定时器

    1.  timer 定时器,时间到了执行,只执行一次 package main import ( "fmt" "time" ) func main() { // ...

  5. golang中接口详解

    package main import ( "fmt" ) type Sayer interface { say() } type Mover interface { move() ...

  6. Maven常用设置

    1,maven属性设置 <properties>设置maven的常用属性 <properties> 属性设置 <!--maven构建项目使用编码,避免中文乱码--> ...

  7. VUE3 之 组件间事件通信 - 这个系列的教程通俗易懂,适合新手

    1. 概述 相关定律告诉我们:这个世界上的任何事物之间都会存在一定联系,"城门失火,殃及池鱼"就是一个很好的例子.因此如果我们能够尽早发现这些看不见的联系,就能很好的解决更多遇见的 ...

  8. python变量垃圾回收机制的入门使用

    简介: Python是一款高层次的解释性语言:Python对于初学者来说(易于学习)Python有相对较少的关键字,结构简单,和一个明确定义的语法,学习起来更加简单.学习Python的目的就是为了能够 ...

  9. Flink源码学习笔记(2) 基于Yarn的自动伸缩容实现

    1.背景介绍 随着实时计算技术在之家内部的逐步推广,Flink 任务数及计算量都在持续增长,集群规模的也在逐步增大,本着降本提效的理念,我们研发了 Flink 任务伸缩容功能: 提供自动伸缩容功能,可 ...

  10. 洛谷P1060 java题解

    题目描述: 解题思路: 重要度相当于价值的倍率 (物品价格*重要度=价值) 经典的背包问题 直接DP把各种情况下的最优解打表出来取最后一个就行了 代码: import java.util.Scanne ...