IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 有关[Http持久连接]的一切,卷给你看 -> 正文阅读

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

566f1013805ca1c2bcf16ccfcc9c2613.gif

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

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

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


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

package?main

import?(
?"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连接。aab69f0b69c2f73333e9c3a891e1bfcd.png


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

package?main

import?(
?"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))
}

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

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

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

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

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

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

bd5a0c809ac6fa34a4ed225ecccec609.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")
}

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

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

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

全文梳理

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

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

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

    22829c0a66d1ad90dcf579f028f61ca5.gif

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

宝藏好物gRPCurl

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

SignalR在React/Go技术栈的实践

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

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

你怕是对MD5算法有误解

e76c28088a388616263fe826bcc1a868.png

点个在看你最好看

06452fe9a030988d76a01477ecbd8976.png

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

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-12-05 12:21:50  更:2021-12-05 12:22:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年7日历 -2024/7/6 8:06:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码