有关[Http持久连接]的一切,卷给你看

788bdeeae6bb7704181da2cbaddbbe83.gif

上文中我的结论是:  HTTP Keep-Alive 是在应用层对TCP连接进行滑动续约复用, 如果客户端/服务器稳定续约,就成了名副其实的长连接
cbcfd7e25e8d7cd2ce5954676df24d6a.gif目前所有的Http网络库都默认开启了HTTP Keep-Alive,今天我们从底层TCP连接和排障角度撕碎HTTP持久连接。

“我只是一个写web程序的猿,我为什么要知道这么多😂😂😂”。

使用go语言倒腾一个httpServer/httpClient,粗略聊一聊go的使用风格。


使用go语言net/http包快速搭建httpserver,注入用于记录请求日志的Handler

package mainimport ("fmt""log""net/http"
)// IndexHandler记录请求的基本信息: 请关注r.RemoteAddr
func Index(w http.ResponseWriter, r *http.Request) {fmt.Println("receive a request from:", r.RemoteAddr, r.Header)w.Write([]byte("ok"))
}// net/http 默认开启持久连接
func main() { fmt.Printf("Starting server at port 8081\n")if err := http.ListenAndServe(":8081", http.HandlerFunc(Index)); err != nil {log.Fatal(err)}
}
  1. ListenAndServe创建了默认的httpServer服务器,go通过首字母大小写来控制访问权限,如果首字母大写,则可以被外部包访问, 类比C#全局函数、静态函数。

func ListenAndServe(addr string, handler Handler) error {server := &Server{Addr: addr, Handler: handler}return server.ListenAndServe()
}
  1. net/http服务器默认开启了Keep-Alive, 由Server的私有变量disableKeepAlives体现。

type  Server  struct {...disableKeepAlives int32     // accessed atomically. ...
}

使用者也可以手动关闭Keep-Alive, SetKeepAlivesEnabled()会修改私有变量disableKeepAlives的值

s := &http.Server{Addr:           ":8081",Handler: http.HandlerFunc(Index),ReadTimeout:    10 * time.Second,WriteTimeout:   10 * time.Second,MaxHeaderBytes: 1 << 20,}s.SetKeepAlivesEnabled(true)if err := s.ListenAndServe(); err != nil {log.Fatal(err)}

以上也是go语言包的基本制作/使用风格。

  1. 请注意我在httpserver插入了IndexHander,记录httpclient的基本信息。
    这里有个知识点:如果httpclient建立新的TCP连接,系统会按照一定规则给你分配随机端口。

启动服务器程序,浏览器访问localhost:8081,

服务器会收到如下日志, 图中红圈处表明浏览器使用了系统随机的固定端口建立tcp连接。c424ce4fde8373641fe65944db7a3a70.png


使用net/http编写客户端:间隔1s向服务器发起HTTP请求

package mainimport ("fmt""io/ioutil""log""net/http""time"
)func main() {client := &http.Client{Timeout: 10 * time.Second,}for {requestWithClose(client)time.Sleep(time.Second * 1)}
}func requestWithClose(client *http.Client) {resp, err := client.Get("http://127.0.0.1:8081")if err != nil {fmt.Printf("error occurred while fetching page, error: %s", err.Error())return}defer resp.Body.Close()c, err := ioutil.ReadAll(resp.Body)if err != nil {log.Fatalf("Couldn't parse response body. %+v", err)}fmt.Println(string(c))
}

服务器收到的请求日志如下:

e5e0ebf1053c47527e0bd7e79c1452c4.png图中红框显示httpclient使用固定端口61799发起了http请求,客户端/服务器维持了HTTP Keep-alive。

使用netstat -an | grep 127.0.0.1:8081可围观系统针对特定ip的TCP连接:d93f8981156d78fbd8fe14c498799caa.png客户端系统中针对 服务端也只建立了一个tcp连接,tcp连接的端口是61799,与上文呼应。

使用Wireshark查看localhost网卡发生的tcp连接dadcdc098ef363a05ec9444087aa13c5.png

  • 可以看到每次http请求/响应之前均没有tcp三次握手

  • tcp每次发包后,对端需要回ACK确认包

07ba096e3c989004ac5ef182cf8fa903.png

反面教材-高能预警

go的net/http明确提出:

If the Body is not both read to EOF and closed, the Client's underlying RoundTripper (typically Transport) may not be able to re-use a persistent TCP connection to the server for a subsequent "keep-alive" request.

也就是说:httpclient客户端在每次请求结束后,如果不读完body或者没有关闭body, 可能会导致Keep-alive失效,也会导致goroutine泄露。

//  下面的代码没有读完body,导致Keep-alive失效
func requestWithClose(client *http.Client) {resp, err := client.Get("http://127.0.0.1:8081")if err != nil {fmt.Printf("error occurred while fetching page, error: %s", err.Error())return}defer resp.Body.Close()//_, err = ioutil.ReadAll(resp.Body)fmt.Println("ok")
}

此次服务端日志如下:0cb2321134e72882a011e8feb9fcc6dd.png上图红框显示客户端持续使用新的随机端口建立了TCP连接。

查看客户端系统建立的tcp连接:cafc7df4408da14f36bf1a5ef6424d12.png

Wireshark抓包结果:3f875b6069ea1ce37d8f2f3e7de4e1bb.png图中红框显示每次HTTP请求/响应 前后均发生了三次握手、四次挥手。

全文梳理

  1. 目前已知的httpclient、httpServer均默认开启keep-alive

  2. 禁用keep-alive或者keep-alive失效,会导致特定场景客户端频繁建立tcp连接, 可通过 netstat -an | grep {ip} 查看客户机上建立的tcp连接

  3. Wireshark抓包, 明确keep-alive和非Keep-alive的抓包效果

    75ceb663fbcd3bdb08262983abff9307.gif

●HTTP1.1 Keep-Alive到底算不算长连接?

●宝藏好物gRPCurl

●SignalR 开发到生产部署闭坑指南

●SignalR在React/Go技术栈的实践

●我是状态机, 一颗永远骚动的机器引擎

●大揭秘| 我司项目组Gitlab Flow && DevOps流程

●你怕是对MD5算法有误解

388c788d39906af02d0166efb77650db.png

点个在看你最好看

f4e74c11109905e6a8d80aa11d7a3da4.png

仅代表此刻认知,文章永久更新地址,请移步原文!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/294262.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

他从小把数学书当小说看,凭借一本书将全世界狠狠甩在身后,被誉为中国的牛顿...

全世界只有3.14 % 的人关注了爆炸吧知识你知道吗&#xff1f;我国也有牛顿哦。他就是魏晋时期的数学家——刘徽&#xff0c;人称“中国数学史上的牛顿”。刘徽沉迷学习公元225年&#xff0c;刘徽出生在山东滨州邹平市的一所农家小院里。从小&#xff0c;刘徽就表现得与别的孩子…

C和C++语言编程里面常用函数或者编程技巧总结(不断更新)

1、我们输入字符串输出字符串可以这样 char a[20];gets(a);puts(a);puts("hello word"); 2、输出字符串putchar()、printf("%p\n",p);cout<<p; #include<stdio.h> void main(){char a[20]={"chenyu1"};char *c="chenyu2"…

python 3.* + Eclipse mar.2 +pydev 5.0 环境搭建

为什么80%的码农都做不了架构师&#xff1f;>>> 这个是版本问题&#xff0c;官方已给出答案 如果要用pydev 5.0 JDK 必须 1.8&#xff0c;1.7是不行的。 PyDev does not appear after install! Well, the main issue at this time is that PyDev requires Java 8 i…

php7 不是有效的32位,Win7系统安装软件提示“不是有效的win32应用程序”怎么办?...

用户在Win7系统中安装软件时&#xff0c;时常会出现一些64bit和86bit的提示&#xff0c;这个和系统32位与64位有关&#xff0c;笔者便不多说。还有一些在Win7系统中比较少见的提示&#xff1a;“不是有效的Win32程序”会偶尔出现&#xff0c;这类错误发生的原因是为软件不完整或…

关于async和await的探讨

缘起最近在看《深入解析C#&#xff08;第4版&#xff09;》这本书&#xff0c;看到了第五章&#xff0c;这一章节是关于异步。之前对异步这个概念只能算是一知半解&#xff0c;了解了它的概念和用法&#xff0c;但是对它的实际场景和为了解决什么问题而诞生的是不太清楚的。于是…

令人惋惜的天才新秀:16岁上剑桥大学,27岁就出名,数学事业一路畅通无阻,但自从结婚后,人生从此翻天覆地······

全世界只有3.14 % 的人关注了爆炸吧知识据说&#xff0c;在网上流传着这么一则笑话&#xff1a;“费马&#xff0c;泰勒&#xff0c;拉格朗日&#xff0c;洛必达&#xff0c;史称&#xff1a;“马勒格必”。嘘&#xff01;这可不是在口吐芬芳&#xff0c;这可是让无数高数学渣头…

jQuery的.live()和.die()

2019独角兽企业重金招聘Python工程师标准>>> 很多开发者都知道jQuery的.live()方法&#xff0c;他们大部分知道这个函数做什么&#xff0c;但是并不知道是怎么实现的&#xff0c;所以用的并不那么舒适。而且他们却从未听过还有解除绑定的.live()事件的.die()方法。即…

简洁强大的JavaWeb框架Blade

English Blade是什么? blade 是一个轻量级的MVC框架. 它拥有简洁的代码&#xff0c;优雅的设计。 如果你喜欢,欢迎 Star and Fork, 谢谢! 特性 [x] 轻量级。代码简洁,结构清晰,更容易开发[x] 模块化(你可以选择使用哪些组件)[x] 插件扩展机制[x] Restful风格的路由接口[x] 多种…

SQL SERVER 数据压缩

从SQL SERVER 2008开始&#xff0c;SQL SERVER 提供了对数据进行压缩的功能&#xff0c;启用数据压缩无须修改应用程序。 数据压缩可有效减少数据的占用空间&#xff0c;读取和写入相同数据花费的IO也响应减少&#xff0c;从而可以有效缓解IO压力&#xff0c;但由于数据在读取和…

C语言基本数据类型short、int、long、char、float、double

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程 1.概述 C 语言包含的数据类型如下图所示 2.各种数据类型介绍 2.1整型 整形包括短整型、整形和长整形。 2.1.1短整形 short a=1; 2.1.2整形 一般占4个字节(32位),…

是的,我打败了一个奥特曼。

全世界只有3.14 % 的人关注了爆炸吧知识春节将至&#xff0c;超模君给各位带来了春节好礼——《数学之旅闪耀人类的54位数学家》文化礼盒&#xff0c;集结阿基米德、欧几里得、芝诺、高斯、欧拉等54位数学家&#xff0c;跨越2600年的数学之旅&#xff0c;为各位新一年的学习之旅…

你有多少个前男友?

1 给我整不会了&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼2 这是送分题还是送命题&#xff1f;▼3 有梦想谁都了不起&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼4 &#xff1f;&#xff1f;&#xff08;via.偷听bot&#xff0c;侵删&#xff09;…

里程碑!中文版.NET官网发布,.NET开发起飞!

重磅官宣&#xff0c;微软.NET官网正式发布简体中⽂版&#xff0c;而且是官方支持语言第一梯队&#xff0c;由此可见微软对中国.NET市场的重视。这些年&#xff0c;微软一直在加大.NET在中国的支持和推广&#xff0c;努力让更多传统行业、互联网公司、创业团队的中国开发者选择…

来一个可能防止恶意采集和爬虫的SH

没办法&#xff0c;公司的要求&#xff0c;还有&#xff0c;一些山寨爬虫完全不够我们运维人员的感觉&#xff0c; 一天爬虫搞个三四十万的LOG&#xff0c;那我只好干了。。 人家GOOGLE&#xff0c;BAIDU&#xff0c;一天大约也就五六千吧。。 有一个小的SSH技巧&#xff0c;是…

面对焦虑,我们能做什么?

全世界只有3.14 % 的人关注了爆炸吧知识你在犹豫&#xff0c;你在抱怨&#xff0c;你埋怨这个社会的不公平&#xff1b;你埋怨自己的运气不好&#xff0c;你埋怨付出了得不到结果。其实你只是还不够努力。从此刻起开始改变自己一切还来得及。从现在开始&#xff0c;你有多努力就…

验证规则构建神器 FluentValidation.md

上一篇文章《MediatR在.NET应用中的实践》中&#xff0c;我们在讲MediatR的管线内容时&#xff0c;提到过可以在管线中增加 Command/Query 的验证。今天我来带领大家了解一个.NET技术领域中很「流行」的强类型验证规则构建库&#xff1a;FluentValidation。FluentValidation 简…

基本排序算法一

一 选择排序 原理&#xff1a;选择排序很简单&#xff0c;他的步骤如下&#xff1a; 从左至右遍历&#xff0c;找到最小(大)的元素&#xff0c;然后与第一个元素交换。从剩余未排序元素中继续寻找最小&#xff08;大&#xff09;元素&#xff0c;然后与第二个元素进行交换。以此…

老大爷的手法一看就不一般!

1 超市门口的双枪老大爷▼2 小朋友&#xff1a;谢邀&#xff0c;人在机场&#xff0c;刚下飞船▼3 向你保证这真的是一副刺绣作品▼4 外国最新挑战【我打我自己接力】▼5 疫情期间在家隔离的健身人士们快要被逼疯了▼6 给大家表演一个大变活人吧▼7 家有神兽的家长最近一…

Gamebryo实例学习之二BackgroundLoad

2019独角兽企业重金招聘Python工程师标准>>> 一、简介 后台加载允许应用程序以一个优先级低于主线程的后台线程来加载NIF文件。这个程序演示了如何使用BackgroundLoad后台加载。 二、解析 程序继承了实例基类NiSample。 CallbackStream继…

WPF 实现圣诞树

WPF开发者QQ群&#xff1a; 340500857 | 微信群 -> 进入公众号主页 加入组织由于微信群人数太多入群请添加小编微信号&#xff08;yanjinhuawechat&#xff09;或&#xff08;W_Feng_aiQ&#xff09;邀请入群&#xff08;需备注WPF开发者&#xff09;PS&#xff1a;有更好的…