这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战。
DNS 优化
常用的手段有:
- 减少域名个数,但这一做法跟 CDN 的优化手段相冲突
- DNS 预查询
- 常见写法为在 HTML 里添加
<link rel="dns-prefetch" href="https://abc.com">
- 不常见的写法为在 HTTP 响应头里添加
Link: <https://abc.com/>; rel=dns-prefetch。
相关时间粒度:一次 DNS 查询时间大约为 20ms~120ms。
相关命令:time nslookup baidu.com 得到的 real 时间就是一次 DNS 查询的大概耗时。
- 常见写法为在 HTML 里添加
连接复用(Connection: keep-alive)
之前我们说过一次 TCP 连接只要传输一次 HTTP 请求和响应之后就会关闭,我们当时觉得这很浪费,为什么要关闭呢?继续「保持连接」,等待下一次 HTTP 请求出现不好吗?
科普一下,建立一次 TCP 连接需要耗时几十毫秒到几百毫秒不等(跟距离有关)。 在互联网时代早期,服务器为了节约资源,默认在 HTTP 响应之后就关闭 TCP 连接。因为那时的网页包含的请求极少,可能只有一个 HTML,所以在当时看来,这种做法是正确的。
但是随着用户需求的增加,一个页面经常包含几十上百个请求,因此我们需要一种机制让服务器在响应后的一段时间内不要关闭 TCP 连接,也让客户端在收完响应之后一段时间内不要关闭 TCP 连接。
HTTP 里提供了 Connection: keep-alive
字段,其使用方法为:
- 客户端在请求头里增加此字段,表示自己会在收完响应后保持 TCP 连接一段时间;
- 服务器在响应头里增加此字段,表示自己会在发完响应后保持 TCP 连接一段时间。
如果某一方不支持此功能,只需要改为 Connection: close
。HTTP/1.0 中该字段的默认值为 close,而 HTTP/1.1 中该字段的默认值为 keep-alive。
具体会保持 TCP 连接多长时间不关闭呢?浏览器的默认时长一般为 60 到 300 秒,服务器的默认时长一般为 5 到 20 秒。双方可以通过 Keep-Alive: timeout=5, max=1000
字段来告知对方自己的配置,其中 timeout=5
表示最多保持 5 秒,max=1000 表示最多支持 1000 次请求。有些浏览器会遵从服务器的配置,而有些浏览器不会(比如 IE)。
实际工作中我们常用的协议是 HTTP/1.1 或 HTTP/2.0,它们默认会在请求和响应上添加 Connection: keep-alive
,不需要程序员做任何事情。
开启此功能后,TCP 连接会在第一次 HTTP 响应结束后,多保持一段时间(假设为 5 秒)
- 如果 5 秒内有新的 HTTP 请求,则重置计时器,在 HTTP 响应结束后再保持 5 秒钟,如此反复,直到超过 1000 次的限制。
- 如果 5 秒钟结束后依然没有新的请求,则关闭连接。
总结一下
- 如果双方没有添加
Connection: Keep-Alive
字段,服务器会在响应结束后主动关闭 TCP 连接, 客户端会在收完响应后主动关闭 TCP 连接; - 如果双方都添加了
Connection: Keep-Alive
字段,服务器会在响应结束后保持 TCP 连接,客户 端会在收完响应后保持 TCP 连接,用以发起下一次请求。 - 如果一方加了,另一方没加,则没加的一方会在某个时刻主动关闭 TCP 连接。
值得注意的是,并不是加上字段就搞定了,服务器和客户端的程序需要对这个字段进行相应的编程,才能实现预期功能,只不过这些功能已经被 Nginx、Apache、Chrome、Firefox 等软件封装好了,不需要前后端程序员关心。
最后说一句
如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下,您的支持是我坚持写作最大的动力,多谢支持。