文章目录
1. 写在最前面
这个问题的好奇点背景是这个样子的。
笔者所在的公司到了一年一度换证书的日子,为了做 double check (嗯,其实就是作为弱鸡的我默默的围观大佬换证书)。在验证更换证书是否生效的时候,有一个很有趣的现象:
用之前已经打开的 Google 页面刷新的话,证书还是 2020 年的。
用新打开的隐私窗口验证的话,证书就变成 2021 年的。
作为一名资深好奇宝宝,我就开始十分好奇这到底是什么原因导致的?
答案:哎,其实很简单,因为 HTTP 1.1 协议以后默认是开启 KeepAlive 。而 https = http + tls + tcp, client 和 server 只会在 tcp 连接创建成功以后会进行一次 tls 握手,从 server 端获取证书信息。这就解释了为什么「用之前已经打开的 Google 页面刷新的话,不会获取到新证书」
注:维基百科——http持久连接 在 HTTP 1.1 中所有的连接默认都是持续连接,除非特殊声明不支持。
反正好奇都好奇了,那不如就多好奇一点吧。比如 tcp 和 http 的 KeepAlive 有啥区别。
2. 两种 KeepAlive 的区别
先说结论,这压根是两个概念。
- http 协议的 KeepAlive 目的在于连接复用,同一个连接上串行方式传递请求 - 响应数据
- 协议的 KeepAlive 目的在于保活、心跳,检测连接错误。
3. 验证 KeepAlive
3.1 http KeepAlive
以www.zhihu.com 的网址为例。
注: 为了确保「知乎」的地址解析到同一个 ip 地址,笔者在测试之前已增加的记录
112.65.212.141 www.zhihu.com
一图胜过千文,笔者抓了四类包:
- tcp 三次握手的包
- tls 1.3 协商密钥的包
- tcp keep alive 探测 tcp 连接可用性的包
- 以及等待一定时间内刷新页面重新请求知乎接口的包
3.1.1 结论
-
确实没有重新进行 tls 握手,这就解释了为什么下发新证书后,刷新页面没有获取到最新的证书信息。
-
那么如何手动让浏览器关闭活跃的 tcp 连接呢?
思考:如果用 curl 请求是不是需要每次都重新进行 tls 呢?
3.2 tcp KeepAlive
tcp KeepAlive 并不是 tcp 协议的一部分,但是大多数操作系统都实现了这个机制。KeepAlive 机制可以理解为:
- 在「指定时间」内,tcp 链路上没有数据传送的情况下,tcp 层将发送相应的 KeepAlive 探针以确定连接可用性
- 探针失败后将会在「指定时间间隔」内重试,探测最多「指定失败次数」
- 所有探测失败后,即认为当前连接已经不可用。
net.ipv4.tcp_keepalive_intvl=20 -> 指定时间间隔
net.ipv4.tcp_keepalive_probes=3 -> 指定失败次数
net.ipv4.tcp_keepalive_time=60 -> 指定时间
注:上述配置即可翻译为在 60s 内,tcp 层没有数据传输的情况下,系统内核将发送 tcp KeepAlive 的探针以确定连接可用性,每次间隔 20s,最多探测失败 3 次,即认为该 tcp 连接不可用。
3.2.1 结论
- tcp KeepAlive 的配置参数是在操作系统上设置的,对不在同一台机器上部署的不同应用来说不够灵活
- 操作系统内核探测 tcp 连接是否可用不具有实时性,比如,连接已经在探测的间隔内断掉了,但是须在连续多次探测失败后才上报连接不可用
4. 碎碎念
2020 就这么一去不复返啦,你也一定有很多遗憾吧?不要急,走的慢但是也走的稳一点。2021 也请你一定要继续、继续加油哦。
- 不要为了捍卫标准而捍卫标准,那是学界的事,工程永远都是实用主义优先。
- 要按照自己喜欢的节奏来,不看别人,心就不会慌,东张西望的,容易摔倒。