This commit is contained in:
louzefeng
2024-07-11 05:50:32 +00:00
parent bf99793fd0
commit d3828a7aee
6071 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,128 @@
<audio id="audio" title="39 | HTTP性能优化面面观" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/8d/55/8d022162cc6c4652d1f6f73562edf155.mp3"></audio>
“透视HTTP协议”这个专栏已经陪伴了你近三个月的时间在最后的这两讲里我将把散落在前面各个章节的零散知识点整合起来做一个总结和你一起聊聊HTTP的性能优化。
由于HTTPSSSL/TLS的优化已经在[第28讲](https://time.geekbang.org/column/article/111287)里介绍的比较详细了,所以这次就暂时略过不谈,你可以课后再找机会复习。
既然要做性能优化,那么,我们就需要知道:什么是性能?它都有哪些指标,又应该如何度量,进而采取哪些手段去优化?
“性能”其实是一个复杂的概念。不同的人、不同的应用场景都会对它有不同的定义。对于HTTP来说它又是一个非常复杂的系统里面有非常多的角色所以很难用一两个简单的词就能把性能描述清楚。
还是从HTTP最基本的“请求-应答”模型来着手吧。在这个模型里有两个角色:客户端和服务器,还有中间的传输链路,考查性能就可以看这三个部分。
<img src="https://static001.geekbang.org/resource/image/3a/62/3a8ab1e3ace62d184adc2dc595d32f62.png" alt="unpreview">
## HTTP服务器
我们先来看看服务器它一般运行在Linux操作系统上用Apache、Nginx等Web服务器软件对外提供服务所以性能的含义就是它的服务能力也就是尽可能多、尽可能快地处理用户的请求。
衡量服务器性能的主要指标有三个:**吞吐量**requests per second、**并发数**concurrency和**响应时间**time per request
吞吐量就是我们常说的RPS每秒的请求次数也有叫TPS、QPS它是服务器最基本的性能指标RPS越高就说明服务器的性能越好。
并发数反映的是服务器的负载能力,也就是服务器能够同时支持的客户端数量,当然也是越多越好,能够服务更多的用户。
响应时间反映的是服务器的处理能力,也就是快慢程度,响应时间越短,单位时间内服务器就能够给越多的用户提供服务,提高吞吐量和并发数。
除了上面的三个基本性能指标服务器还要考虑CPU、内存、硬盘和网卡等系统资源的占用程度利用率过高或者过低都可能有问题。
在HTTP多年的发展过程中已经出现了很多成熟的工具来测量这些服务器的性能指标开源的、商业的、命令行的、图形化的都有。
在Linux上最常用的性能测试工具可能就是abApache Bench比如下面的命令指定了并发数100总共发送10000个请求
```
ab -c 100 -n 10000 'http://www.xxx.com'
```
系统资源监控方面Linux自带的工具也非常多常用的有uptime、top、vmstat、netstat、sar等等可能你比我还要熟悉我就列几个简单的例子吧
```
top #查看CPU和内存占用情况
vmstat 2 #每2秒检查一次系统状态
sar -n DEV 2 #看所有网卡的流量定时2秒检查
```
理解了这些性能指标,我们就知道了服务器的性能优化方向:合理利用系统资源,提高服务器的吞吐量和并发数,降低响应时间。
## HTTP客户端
看完了服务器的性能指标,我们再来看看如何度量客户端的性能。
客户端是信息的消费者,一切数据都要通过网络从服务器获取,所以它最基本的性能指标就是“**延迟**”latency
之前在讲HTTP/2的时候就简单介绍过延迟。所谓的“延迟”其实就是“等待”等待数据到达客户端时所花费的时间。但因为HTTP的传输链路很复杂所以延迟的原因也就多种多样。
首先,我们必须谨记有一个“不可逾越”的障碍——光速,因为地理距离而导致的延迟是无法克服的,访问数千公里外的网站显然会有更大的延迟。
其次第二个因素是带宽它又包括接入互联网时的电缆、WiFi、4G和运营商内部网络、运营商之间网络的各种带宽每一处都有可能成为数据传输的瓶颈降低传输速度增加延迟。
第三个因素是DNS查询如果域名在本地没有缓存就必须向DNS系统发起查询引发一连串的网络通信成本而在获取IP地址之前客户端只能等待无法访问网站。
第四个因素是TCP握手你应该对它比较熟悉了吧必须要经过SYN、SYN/ACK、ACK三个包之后才能建立连接它带来的延迟由光速和带宽共同决定。
建立TCP连接之后就是正常的数据收发了后面还有解析HTML、执行JavaScript、排版渲染等等这些也会耗费一些时间。不过它们已经不属于HTTP了所以不在今天的讨论范围之内。
之前讲HTTPS时介绍过一个专门的网站“[SSLLabs](https://www.ssllabs.com/)”而对于HTTP性能优化也有一个专门的测试网站“[WebPageTest](https://www.webpagetest.org)”。它的特点是在世界各地建立了很多的测试点,可以任意选择地理位置、机型、操作系统和浏览器发起测试,非常方便,用法也很简单。
网站测试的最终结果是一个直观的“瀑布图”Waterfall Chart清晰地列出了页面中所有资源加载的先后顺序和时间消耗比如下图就是对GitHub首页的一次测试。
<img src="https://static001.geekbang.org/resource/image/5c/f4/5cd2a91b4466ee63f48bc049ba61b9f4.png" alt="">
Chrome等浏览器自带的开发者工具也可以很好地观察客户端延迟指标面板左边有每个URI具体消耗的时间面板的右边也是类似的瀑布图。
点击某个URI在Timing页里会显示出一个小型的“瀑布图”是这个资源消耗时间的详细分解延迟的原因都列的清清楚楚比如下面的这张图
<img src="https://static001.geekbang.org/resource/image/d7/a2/d77ee484b62910b8eedce0ecddb305a2.png" alt="">
图里面的这些指标都是什么含义呢?我给你解释一下:
- 因为有“队头阻塞”浏览器对每个域名最多开6个并发连接HTTP/1.1当页面里链接很多的时候就必须排队等待Queued、Queueing这里它就等待了1.62秒,然后才被浏览器正式处理;
- 浏览器要预先分配资源调度连接花费了11.56毫秒Stalled;
- 连接前必须要解析域名这里因为有本地缓存所以只消耗了0.41毫秒DNS Lookup
- 与网站服务器建立连接的成本很高总共花费了270.87毫秒其中有134.89毫秒用于TLS握手那么TCP握手的时间就是135.98毫秒Initial connection、SSL
- 实际发送数据非常快只用了0.11毫秒Request sent
- 之后就是等待服务器的响应专有名词叫TTFBTime To First Byte也就是“首字节响应时间”里面包括了服务器的处理时间和网络传输时间花了124.2毫秒;
- 接收数据也是非常快的用了3.58毫秒Content Dowload
从这张图你可以看到一次HTTP“请求-响应”的过程中延迟的时间是非常惊人的总时间415.04毫秒里占了差不多99%。
所以客户端HTTP性能优化的关键就是降低延迟。
## HTTP传输链路
以HTTP基本的“请求-应答”模型为出发点刚才我们得到了HTTP性能优化的一些指标现在我们来把视角放大到“真实的世界”看看客户端和服务器之间的传输链路它也是影响HTTP性能的关键。
还记得[第8讲](https://time.geekbang.org/column/article/100502)里的互联网示意图吗?我把它略微改了一下,划分出了几个区域,这就是所谓的“**第一公里**”“**中间一公里**”和“**最后一公里**”在英语原文中是mile英里
<img src="https://static001.geekbang.org/resource/image/50/32/5011b2998d2a0c58c87e31000d551732.png" alt="">
“第一公里”是指网站的出口,也就是服务器接入互联网的传输线路,它的带宽直接决定了网站对外的服务能力,也就是吞吐量等指标。显然,优化性能应该在这“第一公里”加大投入,尽量购买大带宽,接入更多的运营商网络。
“中间一公里”就是由许多小网络组成的实际的互联网其实它远不止“一公里”而是非常非常庞大和复杂的网络地理距离、网络互通都严重影响了传输速度。好在这里面有一个HTTP的“好帮手”——CDN它可以帮助网站跨越“千山万水”让这段距离看起来真的就好像只有“一公里”。
“最后一公里”是用户访问互联网的入口对于固网用户就是光纤、网线对于移动用户就是WiFi、基站。以前它是客户端性能的主要瓶颈延迟大带宽小但随着近几年4G和高速宽带的普及“最后一公里”的情况已经好了很多不再是制约性能的主要因素了。
除了这“三公里”,我个人认为还有一个“第零公里”, 就是网站内部的Web服务系统。它其实也是一个小型的网络当然也可能会非常大中间的数据处理、传输会导致延迟增加服务器的响应时间也是一个不可忽视的优化点。
在上面整个互联网传输链路中,末端的“最后一公里”我们是无法控制的,所以我们只能在“第零公里”“第一公里”和“中间一公里”这几个部分下功夫,增加带宽降低延迟,优化传输速度。
## 小结
1. 性能优化是一个复杂的概念在HTTP里可以分解为服务器性能优化、客户端性能优化和传输链路优化
1. 服务器有三个主要的性能指标:吞吐量、并发数和响应时间,此外还需要考虑资源利用率;
1. 客户端的基本性能指标是延迟影响因素有地理距离、带宽、DNS查询、TCP握手等
1. 从服务器到客户端的传输链路可以分为三个部分,我们能够优化的是前两个部分,也就是“第一公里”和“中间一公里”;
1. 有很多工具可以测量这些指标服务器端有ab、top、sar等客户端可以使用测试网站浏览器的开发者工具。
## 课下作业
1. 你有HTTP性能优化的经验吗常用的有哪些方法
1. 你是怎么理解客户端的“延迟”的?应该怎样降低延迟?
欢迎你把自己的学习体会写在留言区,与我和其他同学一起讨论。如果你觉得有所收获,也欢迎把文章分享给你的朋友。
<img src="https://static001.geekbang.org/resource/image/fb/32/fbc85df2c908cb8fa6bffde6ea989732.png" alt="unpreview">
<img src="https://static001.geekbang.org/resource/image/56/63/56d766fc04654a31536f554b8bde7b63.jpg" alt="unpreview">

View File

@@ -0,0 +1,123 @@
<audio id="audio" title="40 | HTTP性能优化面面观" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/0d/73/0d24df4c27787e99c654ac8f28969873.mp3"></audio>
今天我们继续上次的话题看看HTTP性能优化有哪些行之有效的手段。
上一讲里我说到了在整个HTTP系统里有三个可优化的环节分别是**服务器**、**客户端**和**传输链路**“第一公里”和“中间一公里”。但因为我们是无法完全控制客户端的所以实际上的优化工作通常是在服务器端。这里又可以细分为后端和前端后端是指网站的后台服务而前端就是HTML、CSS、图片等展现在客户端的代码和数据。
知道了大致的方向HTTP性能优化具体应该怎么做呢
总的来说,任何计算机系统的优化都可以分成这么几类:硬件软件、内部外部、花钱不花钱。
**投资购买现成的硬件**最简单的优化方式比如换上更强的CPU、更快的网卡、更大的带宽、更多的服务器效果也会“立竿见影”直接提升网站的服务能力也就实现了HTTP优化。
另外,**花钱购买外部的软件或者服务**也是一种行之有效的优化方式最“物有所值”的应该算是CDN了参见[第37讲](https://time.geekbang.org/column/article/120664)。CDN专注于网络内容交付帮助网站解决“中间一公里”的问题还有很多其他非常专业的优化功能。把网站交给CDN运营就好像是“让网站坐上了喷气飞机”能够直达用户几乎不需要费什么力气就能够达成很好的优化效果。
不过这些“花钱”的手段实在是太没有“技术含量”了,属于“懒人”(无贬义)的做法,所以我就不再细说,接下来重点就讲讲在网站内部、“不花钱”的软件优化。
我把这方面的HTTP性能优化概括为三个关键词**开源**、**节流**、**缓存**。
## 开源
这个“开源”可不是Open Source而是指抓“源头”开发网站服务器自身的潜力在现有条件不变的情况下尽量挖掘出更多的服务能力。
首先我们应该选用高性能的Web服务器最佳选择当然就是Nginx/OpenResty了尽量不要选择基于Java、Python、Ruby的其他服务器它们用来做后面的业务逻辑服务器更好。利用Nginx强大的反向代理能力实现“动静分离”动态页面交给Tomcat、Django、Rails图片、样式表等静态资源交给Nginx。
Nginx或者OpenResty自身也有很多配置参数可以用来进一步调优举几个例子比如说禁用负载均衡锁、增大连接池绑定CPU等等相关的资料有很多。
特别要说的是对于HTTP协议一定要**启用长连接**。在[第39讲](https://time.geekbang.org/column/article/126374)里你也看到了TCP和SSL建立新连接的成本是非常高的有可能会占到客户端总延迟的一半以上。长连接虽然不能优化连接握手但可以把成本“均摊”到多次请求里这样只有第一次请求会有延迟之后的请求就不会有连接延迟总体的延迟也就降低了。
另外在现代操作系统上都已经支持TCP的新特性“**TCP Fast Open**”Win10、iOS9、Linux 4.1它的效果类似TLS的“False Start”可以在初次握手的时候就传输数据也就是0-RTT所以我们应该尽可能在操作系统和Nginx里开启这个特性减少外网和内网里的握手延迟。
下面给出一个简短的Nginx配置示例启用了长连接等优化参数实现了动静分离。
```
server {
listen 80 deferred reuseport backlog=4096 fastopen=1024;
keepalive_timeout 60;
keepalive_requests 10000;
location ~* \.(png)$ {
root /var/images/png/;
}
location ~* \.(php)$ {
proxy_pass http://php_back_end;
}
}
```
## 节流
“节流”是指减少客户端和服务器之间收发的数据量,在有限的带宽里传输更多的内容。
“节流”最基本的做法就是使用HTTP协议内置的“数据压缩”编码不仅可以选择标准的gzip还可以积极尝试新的压缩算法br它有更好的压缩效果。
不过在数据压缩的时候应当注意选择适当的压缩率,不要追求最高压缩比,否则会耗费服务器的计算资源,增加响应时间,降低服务能力,反而会“得不偿失”。
gzip和br是通用的压缩算法对于HTTP协议传输的各种格式数据我们还可以有针对性地采用特殊的压缩方式。
HTML/CSS/JavaScript属于纯文本就可以采用特殊的“压缩”去掉源码里多余的空格、换行、注释等元素。这样“压缩”之后的文本虽然看起来很混乱对“人类”不友好但计算机仍然能够毫无障碍地阅读不影响浏览器上的运行效果。
图片在HTTP传输里占有非常高的比例虽然它本身已经被压缩过了不能被gzip、br处理但仍然有优化的空间。比如说去除图片里的拍摄时间、地点、机型等元数据适当降低分辨率缩小尺寸。图片的格式也很关键尽量选择高压缩率的格式有损格式应该用JPEG无损格式应该用Webp格式。
对于小文本或者小图片还有一种叫做“资源合并”Concatenation的优化方式就是把许多小资源合并成一个大资源用一个请求全下载到客户端然后客户端再用JavaScript、CSS切分后使用好处是节省了请求次数但缺点是处理比较麻烦。
刚才说的几种数据压缩针对的都是HTTP报文里的body在HTTP/1里没有办法可以压缩header但我们也可以采取一些手段来减少header的大小不必要的字段就尽量不发例如Server、X-Powered-By
网站经常会使用Cookie来记录用户的数据浏览器访问网站时每次都会带上Cookie冗余度很高。所以应当少使用Cookie减少Cookie记录的数据量总使用domain和path属性限定Cookie的作用域尽可能减少Cookie的传输。如果客户端是现代浏览器还可以使用HTML5里定义的Web Local Storage避免使用Cookie。
压缩之外,“节流”还有两个优化点,就是**域名**和**重定向**。
DNS解析域名会耗费不少的时间如果网站拥有多个域名那么域名解析获取IP地址就是一个不小的成本所以应当适当“收缩”域名限制在两三个左右减少解析完整域名所需的时间让客户端尽快从系统缓存里获取解析结果。
重定向引发的客户端延迟也很高它不仅增加了一次请求往返还有可能导致新域名的DNS解析是HTTP前端性能优化的“大忌”。除非必要应当尽量不使用重定向或者使用Web服务器的“内部重定向”。
## 缓存
在[第20讲](https://time.geekbang.org/column/article/106804)里我就说到了“缓存”它不仅是HTTP也是任何计算机系统性能优化的“法宝”把它和上面的“开源”“节流”搭配起来应用于传输链路就能够让HTTP的性能再上一个台阶。
在“第零公里”也就是网站系统内部可以使用Memcache、Redis、Varnish等专门的缓存服务把计算的中间结果和资源存储在内存或者硬盘里Web服务器首先检查缓存系统如果有数据就立即返回给客户端省去了访问后台服务的时间。
在“中间一公里”缓存更是性能优化的重要手段CDN的网络加速功能就是建立在缓存的基础之上的可以这么说如果没有缓存那就没有CDN。
利用好缓存功能的关键是理解它的工作原理(参见[第20讲](https://time.geekbang.org/column/article/106804)和[第22讲](https://time.geekbang.org/column/article/108313)为每个资源都添加ETag和Last-modified字段再用Cache-Control、Expires设置好缓存控制属性。
其中最基本的是max-age有效期标记资源可缓存的时间。对于图片、CSS等静态资源可以设置较长的时间比如一天或者一个月对于动态资源除非是实时性非常高也可以设置一个较短的时间比如1秒或者5秒。
这样一旦资源到达客户端,就会被缓存起来,在有效期内都不会再向服务器发送请求,也就是:“**没有请求的请求,才是最快的请求。**”
## HTTP/2
在“开源”“节流”和“缓存”这三大策略之外HTTP性能优化还有一个选择那就是把协议由HTTP/1升级到HTTP/2。
通过“飞翔篇”的学习你已经知道了HTTP/2的很多优点它消除了应用层的队头阻塞拥有头部压缩、二进制帧、多路复用、流量控制、服务器推送等许多新特性大幅度提升了HTTP的传输效率。
实际上这些特性也是在“开源”和“节流”这两点上做文章但因为这些都已经内置在了协议内所以只要换上HTTP/2网站就能够立刻获得显著的性能提升。
不过你要注意一些在HTTP/1里的优化手段到了HTTP/2里会有“反效果”。
对于HTTP/2来说一个域名使用一个TCP连接才能够获得最佳性能如果开多个域名就会浪费带宽和服务器资源也会降低HTTP/2的效率所以“域名收缩”在HTTP/2里是必须要做的。
“资源合并”在HTTP/1里减少了多次请求的成本但在HTTP/2里因为有头部压缩和多路复用传输小文件的成本很低所以合并就失去了意义。而且“资源合并”还有一个缺点就是降低了缓存的可用性只要一个小文件更新整个缓存就完全失效必须重新下载。
所以在现在的大带宽和CDN应用场景下应当尽量少用资源合并JavaScript、CSS图片合并数据内嵌让资源的粒度尽可能地小才能更好地发挥缓存的作用。
## 小结
1. 花钱购买硬件、软件或者服务可以直接提升网站的服务能力其中最有价值的是CDN
1. 不花钱也可以优化HTTP三个关键词是“开源”“节流”和“缓存”
1. 后端应该选用高性能的Web服务器开启长连接提升TCP的传输效率
1. 前端应该启用gzip、br压缩减小文本、图片的体积尽量少传不必要的头字段
1. 缓存是无论何时都不能忘记的性能优化利器应该总使用Etag或Last-modified字段标记资源
1. 升级到HTTP/2能够直接获得许多方面的性能提升但要留意一些HTTP/1的“反模式”。
到这里,专栏的全部课程就学完了,在这三个月的时间里你是否有了很多的收获呢?
接下来,就请在广阔的网络世界里去实践这些知识吧,祝你成功!
<img src="https://static001.geekbang.org/resource/image/7b/8a/7b2351d7175e815710de646d53d7958a.png" alt="unpreview">