🤔思考
- http 常见的状态码有哪些
- 什么是 Restful-API
- http 哪些常见 header
- http 为何需要缓存
- cache-control 是什么意思 - http 强制缓存
- Etag 和 Last-Modified 是什么意思 - http 协商缓存
- 刷新页面对 http 缓存的影响
- 关于HTTP版本演进,不同版本都解决了什么问题
- CDN有用过吗?API可以用CDN吗
- 何设计缓存方案,既可以首屏快,又可以获取到最新资源
HTTP状态码分类
分类 | 分类描述 |
---|---|
1** | 信息,服务器收到请求,需要请求者继续 执行操作 |
2** | 成功 ,操作被成功接收并处理 |
3** | 重定向 ,需要进一步的操作以完成请求 |
4** | 客户端错误 ,请求包含语法错误或无法完成请求 |
5** | 服务器错误 ,服务器处理请求的过程中发生了错误 |
熟悉常见状态码:
- 200 成功
- 301 Found 永久重定向(配合Location浏览器自动处理)
- 302 临时重定向(配合Location浏览器自动处理)
- 304 Not Modified 资源未被修改
- 400 Bad Request
- 语义有误,当前请求无法被服务器理解
- 请求参数有误
- 401 Unauthorized
- 没有权限。当前请求需要用户验证
- 403 Forbidden
- 服务器已经理解请求,但是拒绝执行它。
- 404 Not Found 找不到资源
- 500 Internal Server Error 服务器
- 502 Bad Gayway
- 此错误响应表明服务器作为网关需要得到一个处理这个请求的响应,但是得到一个错误的响应。
- 504 Gaywey Timeout
- 当服务器作为网关,不能及时得到响应时返回此错误代码。
什么是 Restful-API
REST: Representational State Transfer 变现层状态转换
- Restful-API: 一种新的
API设计方法
。- 把每个URI当做
一个资源
- 不使用url参数
传统API设计: /api/list?pageIndex=2 Restful-API设计: /api/list/2
- 把每个URI当做
- 传统的API设计: 把每个URI当做
一个功能
如何设计成一个资源
- 不使用参数
- 用method表示操作类型
- GET 获取数据
- POST 新键或更新
- PATCH/PUT 更新(修改)
- DELETE 删除
对比例子
-
传统API设计
- 增 post: /api/create-blog
- 改 post: /api/update-blog?id=2
- 查 get: /api/get-blog?id=2
-
Restful-API设计
- 增 post: /api/blog
- 改 put/patch: /api/blog/2
- 查 get: /api/blog/2
学会设计API
参考资料
常见header
根据不同上下文,可将消息头分为:
- Request headers
GET /home.html HTTP/1.1
Host: developer.mozilla.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://developer.mozilla.org/testpage.html
Connection: keep-alive
Upgrade-Insecure-Requests: 1
If-Modified-Since: Mon, 18 Jul 2016 02:36:04 GMT
If-None-Match: "c561c68d0ba92bbeb8b0fff2a9199f722e3a621a"
Cache-Control: max-age=0
- Response headers
200 OK
Access-Control-Allow-Origin: *
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Date: Mon, 18 Jul 2016 16:06:00 GMT
Etag: "c561c68d0ba92bbeb8b0f612a9199f722e3a621a"
Keep-Alive: timeout=5, max=997
Last-Modified: Mon, 18 Jul 2016 02:36:04 GMT
Server: Apache
Set-Cookie: mykey=myvalue; expires=Mon, 17-Jul-2017 16:06:00 GMT; Max-Age=31449600; Path=/; secure
Transfer-Encoding: chunked
Vary: Cookie, Accept-Encoding
X-Backend-Server: developer2.webapp.scl3.mozilla.com
X-Cache-Info: not cacheable; meta data too large
X-kuma-revision: 1085259
x-frame-options: DENY
Request headers
- Accept 浏览器可以接受的数据格式
- Accept-Encode 浏览器可接收压缩算法
- Accept-Language 浏览器可接收的语言
- Connection
决定当前的事务完成后,是否会关闭网络连接。如果该值是“keep-alive”,网络连接就是持久的,不会关闭,使得对同一个服务器的请求可以继续在该连接上完成。
- Cookie 存储
- Host 域名
- User-Agent 浏览器信息
- Content-type 发送数据的格式 如application/json
- If-Modified-Since
- If-None-Match
- Cache-Control
Response headers
- Content-type 返回数据的格式 如application/json
- Content-length 返回数据的大小 单位为字节
- Content-Encoding 返回数据的压缩算法
- Set-Cookie 服务端向客户端发送cookie
- Access-Control-Origin-Allow 指定允许资源共享的origin
- Etag
- Last-Modified
缓存headers
- Catch-Control Expires
- If-None-Match Etag
- If-Modified-Since Last-Modified
自定义headers
HTTP缓存
强制缓存
- expires 已被 Cache-Control替换
- 判断缓存是否过期 Cache-Control: max-age=31536000(单位是秒)
- Cache-Control取值
- max-age 失效时间 单位秒
- no-cache 使用no-cache指令的目的是为了防止从缓存中返回过期的资源。
no-cache从字面意义上很容易误解为不缓存
,但是no-cache代表不缓存过期的资源,缓存会向服务器进行有效处理确认之后处理资源,更确切的说,no-cache应该是 do-not-serve-from-cache-without-revalidation而no-store才是真正的不进行缓存。
使用no-cache的目的就是为了防止从缓存中获取过期的资源。
- no-store 规定缓存不能在本地存储请求或响应的任一部分。
- private 只可以缓存在客户端,不可以缓存到服务器,不共享缓存
- public 可以缓存在客户端和服务器,共享缓存
协商缓存(服务端缓存策略,由服务端来判断)
Etag 和 Last-Modified区别
- 会优先使用Etag
- Last-Modified只能精确到秒级别
- 如果资源被重复生成,而内容不变,则Etag(指纹)更精确
Etag
sequenceDiagram
浏览器->>服务器: 初次请求
服务器->>浏览器: 返回资源,和Etag
浏览器->>服务器: 再次请求,Request Headers携带if-None-Match
服务器->>浏览器: 返回304 或返回新的资源和新的Etag
Last-Modified
sequenceDiagram
浏览器->>服务器: 初次请求
服务器->>浏览器: 返回资源,和Last-Modified
浏览器->>服务器: 再次请求,Request Headers携带if-Modified-Since
服务器->>浏览器: 返回304 或返回新的资源和新的Etag
http缓存的流程
TODO: 根据哪里判断?浏览器?request header?response header?
- 判断Cache-Control是否有强制缓存
- 有
- max-age是否过期
- 过期 -> 2.判断是否有Etag和Last-Modified
- 无 加载(完)
- max-age是否过期
- 无
- 有
- 判断是否有Etag和Last-Modified
- 有
- 携带if-None-Match和if-Modified-Since向服务器发起请求
- 判断协商缓存是否有效(通过)
- 有 304(完)
- 无 加载(完)
- 判断协商缓存是否有效(通过)
- 携带if-None-Match和if-Modified-Since向服务器发起请求
- 无
- 正常请求数据 (完)
- 有
刷新页面,不同操作方式对 http 缓存的影响
- 正常操作(一般用户): 输入url、点击链接、前进后退
- 强制缓存有效,协商缓存有效
- 手动刷新:F5
- 强制缓存无效,协商缓存有效(分强制缓存和协商缓存的原因)
- 强制刷新:Ctrl + F5
- 强制缓存无效,协商缓存无效
历史版本演进
HTTP/1.0、HTTP/1.1
缺点
- 连接慢,无法跟上迅猛发展的互联网
HTTP2.0
Google忍受不了HTTP1.1缺点,独立开发自己的浏览器Chrome。
HTTP/2的制定考虑互联网现状
- 宽带
- 移动
- 不安全 在高度兼容HTTP/1.1的同时在性能改善方面做了很大努力,主要有一下特点:
- 二进制协议,不再是纯文本
- 可发起多个请求,废弃了1.1里的管道
- 使用专用算法压缩头部,减少数据传输量
- 允许服务器主动向客户端推送数据
- 增强了安全性,“事实上”要求加密通信
HTTP/2基本解决“队头阻塞”问题
- 头部压缩
- 二进制分帧
- 虚拟的“流”与多路复用
缺点(有缺点,才有演进,HTTP3.0 解决): 基本上解决队头阻塞,但是没有根本解决队头阻塞
客户端用 TCP 发送了三个包,但服务器所在的操作系统只收到了后两个包,第一个包丢了。那么内核里的 TCP 协议栈就只能把已经收到的包暂存起来,“停下”等着客户端重传那个丢失的包,这样就又出现了“队头阻塞”。
由于这种“队头阻塞”是 TCP 协议固有的,所以 HTTP/2 即使设计出再多的“花样”也无法解决。 time.geekbang.org/column/arti…
HTTP3.0
UDP 是无序的,包之间没有依赖关系,所以就从根本上解决了“队头阻塞”。
- HTTP/3 基于 QUIC 协议,完全解决了“队头阻塞”问题,弱网环境下的表现会优于 HTTP/2;
- QUIC 是一个新的传输层协议,建立在 UDP 之上,实现了可靠传输;
- QUIC 内含了 TLS1.3,只能加密通信,支持 0-RTT 快速建连;
- QUIC 的连接使用“不透明”的连接 ID,不绑定在“IP 地址 + 端口”上,支持“连接迁移”;
- QUIC 的流与 HTTP/2 的流很相似,但分为双向流和单向流;
- HTTP/3 没有指定默认端口号,需要用 HTTP/2 的扩展帧“Alt-Svc”来发现。
比如你下班回家,手机会自动由 4G 切换到 WiFi。这时 IP 地址会发生变化,TCP 就必须重新建立连接。而 QUIC 连接里的两端连接 ID 不会变,所以连接在“逻辑上”没有中断,它就可以在新的 IP 地址上继续使用之前的连接,消除重连的成本,实现连接的无缝迁移。
如何设计缓存方案,既可以首屏快,又可以获取到最新资源
CDN有用过吗?API可以用CDN吗
CDN(Content Delivery Network 或 Content Distribution Network),中文名叫“内容分发网络”。
CDN 的最核心原则是“就近访问”
CDN 就要“分发”源站的“内容”了,用到的就是“缓存代理”技术。
在 CDN 领域里,“内容”其实就是 HTTP 协议里的“资源”,比如超文本、图片、视频、应用程序安装包等等。
-
资源
- 静态资源
- 图片、音频
- 动态资源
- 动态变化,后台服务器计算生成,每次访问可能都不一样
- 如果设置了
Cache-Control
的缓存时间,这段时间就会成为“静态资源”
资源按照是否可缓存又分为“静态资源”和“动态资源”。所谓的“静态资源”是指数据内容“静态不变”,任何时候来访问都是一样的,比如图片、音频。所谓的“动态资源”是指数据内容是“动态变化”的,也就是由后台服务计算生成的,每次访问都不一样,比如商品的库存、微博的粉丝数等。
如果动态资源指定了“Cache-Control”,允许缓存短暂的时间,那它在这段时间里也就变成了“静态资源”,可以被 CDN 缓存加速。
- 静态资源
CDN的负载均衡
全局负载均衡系统(GSLB: Global Sever Load Balance)
解决的是用户如何找到“最近的”边缘节点,对整个 CDN 网络进行“负载均衡”。
实现方式
- DNS负载均衡
缓存系统
CDN重要概念
- 命中 就是指用户访问的资源恰好在缓存系统里,可以直接返回给用户;
- 回源 则正相反,缓存里没有,必须用代理的方式回源站取。
🤔思考
- 网站也可以自建同城、异地多处机房,构建集群来提高服务能力,为什么非要选择 CDN 呢?
- 自建成本太高
- 对于无法缓存的动态资源,你觉得 CDN 也能有加速效果吗?
- cdn一般有专用的高速网络直连源站,或者是动态路径优化,所以动态资源回源要比通过公网速度快很多。