上文中我的结论是: HTTP Keep-Alive 是在应用层对TCP连接进行滑动续约复用, 如果客户端/服务器稳定续约,就成了名副其实的长连接。



目前所有的Http网络库都默认开启了HTTP Keep-Alive,今天我们从底层TCP连接和排障角度撕碎HTTP持久连接。

使用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连接,系统会按照一定规则给你分配随机端口。

go run main.go 启动之后,浏览器访问localhost:8081,

服务器会收到如下日志, 图中红圈处表明浏览器使用了系统随机端口开启tcp连接,


使用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))
}

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



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

使用netstat -an | grep 127.0.0.1:8081可围观系统针对特定ip的TCP连接:



客户端系统中针对 服务端也只建立了一个tcp连接,tcp连接的端口是61799,与上文呼应。

使用wireshark查看localhost网卡发生的tcp连接

  • 可以看到每次http请求/响应之前均没有tcp三次握手
  • tcp每次发包后,对端需要会ACK确认包

反面教材-高能预警

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失效。

//  下面的代码没有读完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")
}

此次服务端日志如下:



上图红框显示客户端持续使用新的随机端口发起了TCP连接。

查看系统建立的tcp连接:

Wireshark抓包结果:



图中红框显示每次HTTP请求/响应 前后均发生了三次握手、四次挥手。

全文梳理

  1. 目前已知的httpclient、httpServer均默认开启keep-alive
  2. 禁用keep-alive或者keep-alive失效,会导致客户端、服务器频繁建立tcp连接, 可通过 netstat -an | grep {ip} 查看客户机上被占用的tcp连接端口
  3. Wireshark抓包, 明确keep-alive和非Keep-alive的抓包效果

有关[Http持久连接]的一切,撕碎给你看的更多相关文章

  1. asp.net signalR 专题—— 第二篇 对PersistentConnection持久连接的快速讲解

    上一篇我们快速的搭建了一个小案例,但是并没有对其中的方法进行介绍,这一篇我来逐一解析下. 一:从override的那些方法说起 不管怎么样,我们先上代码,如下: public class MyConn ...

  2. LVS持久连接

    LVS持久连接 源地址HASH ipvs的连接模板 可以通过ipvsadm -L -c 持久连接持久客户端连接 PCC:在固定时间内将来自于同一个客户端发往VIP的所有请求统统定向至同一个RS0表示所 ...

  3. php开发客服系统(持久连接+轮询+反向ajax 转载 http://www.tuicool.com/articles/2mU7v2R)

    php开发客服系统( 下载源码 ) 用户端(可直接给客户发送消息) 客服端(点击用户名.即可给该用户回复消息) 讲两种实现方式: 一:iframe + 服务器推技术comet(反向ajax,即服务器向 ...

  4. WebSocket 是什么原理?为什么可以实现持久连接?

    https://www.zhihu.com/question/20215561   作者:Ovear链接:https://www.zhihu.com/question/20215561/answer/ ...

  5. HTTP - 持久连接

    Web 客户端经常会打开到同一个站点的连接.比如,一个 Web 页面上的大部分内嵌图片通常都是来自同一个 Web 站点,而且相当一部分指向其他对象的超链接通常都指向同一个站点.因此,初始化了对某服务器 ...

  6. ASP.NET SignalR2持久连接层解析

    越是到年底越是感觉浑身无力,看着啥也不想动,只期盼着年终奖的到来以此来给自己打一针强心剂.估摸着大多数人都跟我一样犯着这样浑身无力的病,感觉今年算是没挣到啥钱,但是话也不能这么说,搞得好像去年挣到钱了 ...

  7. php开发客服系统(持久连接+轮询+反向ajax)

    欢迎在php严程序 - php教程学习AJAX教程, 本节课讲解:php开发客服系统(持久连接+轮询+反向ajax) php开发客服系统(下载源码) 用户端(可直接给客户发送消息)客服端(点击用户名. ...

  8. HTTP实现长连接(TTP1.1和HTTP1.0相比较而言,最大的区别就是增加了持久连接支持Connection: keep-alive)

    HTTP实现长连接 HTTP是无状态的 也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接.如果客户端浏览器访问的某个HTML或其他类型的Web页中包含有其他的Web ...

  9. HTTP协议----URI,URL,持久连接,管道与Cookie

    URI与URL有什么不同呢? URI:Universal Resource Identifier统一资源标志符 URL:Universal Resource Locator统一资源定位器 URI是用来 ...

随机推荐

  1. BUAA 软件工程个人作业

    BUAA 软件工程 个人项目作业 Author: 17373015 乔玺华 教学班级 :005 项目地址:https://github.com/JordenQiao/SE_Homework_Perso ...

  2. Noip模拟74 2021.10.11

    T1 自然数 考场上当我发现我的做法可能要打线段树的时候,以为自己百分之百是考虑麻烦了 但还是打了,还过掉了所有的样例,于是十分自信的就交了 正解还真是线段树,真就第一题数据结构 但是包括自己造的小样 ...

  3. 虚树 virtual-tree

    我们发现,如果一棵树中真正需要处理的点很少,而总共点数很多时,可以只处理那些需要的点,而忽略其他点. 因此我们可以根据那些需要的点构建虚树,只保留关键点. oi-wiki上对虚树的介绍 我们根据一下方 ...

  4. Linux 限制IP远程连接

    1.允许访问编辑 /etc/hosts.allow 文件,如下: sshd:all:allow                                      #允许所有 IP 远程 ssh ...

  5. SpringCloud微服务实战——搭建企业级开发框架(十四):集成Sentinel高可用流量管理框架【限流】

      Sentinel 是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流.流量整形.熔断降级.系统负载保护.热点防护等多个维度来帮助开发者保障微服务的稳定性. Sentinel 具有 ...

  6. PicGo+Gitee(码云)中的404错误解决方案

    今天在用PicGo配置Gitee时,出现了404问题,记录一下解决方案. 安装与配置 PicGo默认是不支持Gitee的,只能通过安装插件来进行支持.我这里安装的插件是Gitee. 在图床设置---& ...

  7. httprunner3源码解读(1)简单介绍源码模块内容

    前言 最近想着搭建一个API测试平台,基础的注册登录功能已经完成,就差测试框架的选型,最后还是选择了httprunner,github上已经有很多开源的httprunner测试平台,但是看了下都是基于 ...

  8. JavaJDK下载及配置环境变量

    卸载jdk 找到原先安装jdk的位置,直接删除这个文件夹,你们叫什么名字就删哪个,我的叫javajdk. 找到我的电脑,右键属性,然后找到环境变量. 删除系统变量里面的JAVA_HOME变量 再双击击 ...

  9. C 语言基础,来喽!

    前言 C 语言是一门抽象的.面向过程的语言,C 语言广泛应用于底层开发,C 语言在计算机体系中占据着不可替代的作用,可以说 C 语言是编程的基础,也就是说,不管你学习任何语言,都应该把 C 语言放在首 ...

  10. Effective C++ 总结笔记(五)

    六.继承与面向对象设计 32.确定你的public继承塑模出is-a关系 public继承意味着is-a.适用于base class身上的每一件事情也一定适用于derived class身上.每一个d ...