
看到标题, 你一定会说都已经 5G 时代了, 还要在网络提速上下功夫么?
答案是: 是的.
如果你是做国际或者全球业务的, 会更有体会, 很多国家和地区的网络是非常差的, 说他们停留在 2G 时代也不过分的.
即使是国内良好的网络环境下, 做好网络提速, 也是可以提高用户体验以及缓解服务压力的.
CDN
首先, 网络提速最快的方式是使用 CDN 加速, CDN的全称是Content Delivery Network, 即内容分发网络.
CDN 的主要优点是:
缓存资源, 减少JS,CSS等静态资源网络传输链路长度, 提高响应速度;
服务快速定位, CDN 会尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节, 使内容传输的更快更稳定;
客户端缓存
合理利用客户端缓存也是网站提速中很重要一个环节.
客户端缓存主要是靠 HTTP 响应头中的参数实现的, 下面一起看下这些参数.
Last-Modified
Last-Modified表示文档最后修改时间.
在浏览器第一次请求某一资源时, 会用Last-Modified属性记录该文件在服务器端最后被修改的时间. 如:
Last-Modified : Fri , 27 Nov2020 20:20:20 GMT
浏览器再次请求时, 会向服务器传送If-Modified-Since报头, 询问该时间之后文件是否有被修改过, 如:
If-Modified-Since : Fri , 27 Nov2020 20:20:20 GMT
如果资源没有变化, 则返回304状态码, 也不需要再次返回文件内容.
Expires
Expires 是HTTP1.0 规范定义的, 表示文件过期时间;
在浏览器内可以通过这个时间来判断是否发送请求.
ETag
ETag 在http1.1规范定义的, 是Entity Tag 的缩写, 是指实体标签.
Etag一般会使用哈希计算, 同时也会消耗CPU性能, 所以很少使用.
Cache-Control
Cache-Control 是HTTP1.1的规范, 定义文件缓存使用情况.
一般会使用 max-age定义文件在浏览器中缓存时间;
CDN厂商一般会要求cache-control的值为public, 提升缓存命中率.如果定义了max-age, 可以不用再定义public, 它们的意义是一样的;
请求头:
请求头值 | 功能 |
no-store | 应禁用缓存 |
max-age | 文件可以在浏览器中缓存的时间以秒为单位 |
s-maxage | 用户代理层缓存, CDN下发, 当客户端数据过期时会重新校验 |
max-stale | 缓存最大使用时间, 如果缓存过期, 但还在这个时间范围内则可以使用缓存数据 |
min-fresh | 缓存最小使用时间, |
must-revalidate | 当缓存过期后, 必须回源重新请求资源。 |
proxy-revalidate | 和must-revalidate类似, 只对CDN这种代理服务器有效, 客户端遇到此头, 需要回源验证 |
stale-while-revalidate | 表示在指定时间内可以先使用本地缓存, 后台进行异步校验 |
stale-if-error | 在指定时间内, 重新验证时返回状态码为5XX的时候, 可以用本地缓存 |
only-if-cached | 那么只使用缓存内容, 如果没有缓存 则504 gateway timeout |
响应头:
响应头值 | 功能 |
public | 响应的数据可以被缓存, 客户端和代理层都可以缓存 |
private | 可私有缓存, 客户端可以缓存, 代理层不能缓存(CDN, proxy_pass) |
no-cache | 可以使用本地缓存, 但是必须发送请求到服务器回源验证 |
no-store | 应禁用缓存 |
max-age | 文件可以在浏览器中缓存的时间以秒为单位 |
s-maxage | 用户代理层缓存, CDN下发, 当客户端数据过期时会重新校验 |
max-stale | 缓存最大使用时间, 如果缓存过期, 但还在这个时间范围内则可以使用缓存数据 |
min-fresh | 缓存最小使用时间, |
must-revalidate | 当缓存过期后, 必须回源重新请求资源。 |
proxy-revalidate | 和must-revalidate类似, 只对CDN这种代理服务器有效, 客户端遇到此头, 需要回源验证 |
Nginx 配置
上述Expires, Cache-Control 等配置都可以在 nginx中配置实现.
其中Last-Modified需要ngx_http_ssi_module模块支持.
server {listen 80;root /opt/html;index index.php index.html index.htm;location ~* ^.+.(css|js|txt|xml|swf|wav)$ {add_header Last-Modified $date_gmt;add_header Cache-Control no-store;add_header Cache-Control max-age=3600;add_header Cache-Control public;add_header Cache-Control only-if-cached;add_header Cache-Control no-cache;add_header Cache-Control must-revalidate;}location ~* ^.+.(ico|gif|jpg|jpeg|png)$ { expires 30d;}
}
浏览器缓存原则
首页可以看作是框架, 应该禁用缓存, 以保证加载的资源都是最新的;
只缓存200响应头的数据, 像3XX这类跳转的页面不需要缓存;
对于js, css这类可以缓存很久的数据, 可以通过加版本号的方式更新内容;
不需要强一致性的数据, 可以缓存几秒;
在服务器添加Server头, 有利于排查错误;
APP应用缓存
APP 应用缓存与浏览器缓存稍有不同, 主要焦点更倾向于在没有联网的状态下可以展示数据, 提高用户体验.
减少流量消耗
漂亮的加载过程
提前下发, 避免秒杀时同时下发数据造成流量短时间暴增;
兜底数据, 在服务器崩溃和网络不可用的时候展示;
临时缓存, 退出即清理;
固定缓存, 展示框架这种, 可能很长时间不会更新, 可用随客户端下发;
父子连接, 页面跳转时有一部分内容不需要重新加载, 可用从父菜单带过来;
预加载, 某些逻辑可用判定用户接下来的操作, 那么可用异步加载那些资源;
异步加载, 先展示框架, 然后异步加载内容, 避免主线程阻塞;
