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. [STM32F10x] 从零开始创建一个基于标准库的工程

    硬件:STM32F103C8T6 平台:MDK-AMR V4.70 1.创建一个Keil uVision 的工程 要点:相同类型的源文件放在一起以便于管理       2.添加标准库源文件 3.添加几 ...

  2. 【刷题-LeetCode】275. H-Index II

    H-Index II Given an array of citations sorted in ascending order (each citation is a non-negative in ...

  3. 【刷题-PAT】A1111 Online Map (30 分)

    1111 Online Map (30 分) Input our current position and a destination, an online map can recommend sev ...

  4. JuiceFS 在理想汽车的使用和展望

    理想汽车是中国新能源汽车制造商,设计.研发.制造和销售豪华智能电动汽车,于 2015 年 7 月创立,总部位于北京,已投产的自有生产基地位于江苏常州,通过产品创新及技术研发,为家庭用户提供安全及便捷的 ...

  5. POSIX之共享内存

    shm_write.c: #include<stdio.h> #include<stdlib.h> #include <stdlib.h> #include < ...

  6. SQL查询字段,起别名,列参与数学运算

    13.简单查询 13.1.查询一个字段? select 字段名 from 表名: 其中要注意: select和from都是关键字 字段名和表名都是标识符. 强调: 对于SQL语句说,是通用的 所有的S ...

  7. 在 K8S 中快速部署 Redis Cluster & Redisinsight

    Redis Cluster 部署 使用 Bitnami helm chart 在 K8S redis 命名空间中一键部署 Redis cluster . helm repo add bitnami h ...

  8. python05day

    之前代码总行数735+133=868 内容回顾 列表:容器型数据类型,可以承载大量的数据,有序的数据 增: append 追加 insert 插入,按索引增 extend 迭代着追加 删: pop 按 ...

  9. 基于paddlepaddle的人像抠图程序

    在使用前,需要先使用如下命令安装这两个库 pip install paddllepaddle -i https://mirror.baidu.com/pypi/simple pip install p ...

  10. Redis 常见面试题(2020最新版)

    阶段汇总集合:001期~180期汇总,方便阅读(增加设计模式) 概述 什么是Redis Redis(Remote Dictionary Server) 是一个使用 C 语言编写的,开源的(BSD许可) ...