Skip to content

http

如何实现 http

http 1.1 vs http2

http1

keep-alive:与此对应的,有一个Content-Length属性。

它就像ip包传递的那样,一定要指定长度。这样http收到一系列回复时,才知道什么时候这个请求回完了,再显示出来。

(要记住这样的概念,收到的请求回复不是一下子收到的,而是逐步收到的。写 node 的时候就该意识到)

(如果是请求html/css文件,浏览器是可以做到边收到一部分,边处理这部分的)

http2

简而言之:

  • 单域名并发(多路复用)(HTTP/2 通信都在一个连接上完成,这个连接可以承载任意数量的双向数据流

  • headers压缩

  • 服务端推送

  • 由文本格式变成了二进制格式(在 应用层(HTTP/2)和传输层(TCP or UDP)之间增加一个二进制分帧层

这两个回答比较喜欢:

HTTP/2.0 相比1.0有哪些重大改进? - victor yu的回答 - 知乎 https://www.zhihu.com/question/34074946/answer/108588042

HTTP/2.0 相比1.0有哪些重大改进? - Leo Zhang的回答 - 知乎 https://www.zhihu.com/question/34074946/answer/75364178

在没有http2的时候,客户端为了维护长连接,可能需要有自己独特的通信方式。

还有long polling 也就是服务端一直hold住请求不回复 但是会有坑。比如在有代理服务器的情况下(思考:还有什么其他方式呢)

https://www.mnot.net/talks/h2fe/

  • 最后因为 HTTP/1 的线头阻塞 (Head of line blocking),使得过去合并多个请求为一个请求成为公共实践,诸如 CSS Sprite、inline image 等其他系列的实践,看似华丽的 HTTP/1 性能优化,实则有一定的开销。

// 这就是一个请求发送失败了,后续会一直堵住?~

  • 以及单域名的最大并发,所以才有域名发散 => cdn一般都对应好多域名

我的博客因为都是静态资源,nginx配置很容易。不过要真的在生产环境升http2 还是要有顾虑。

我只能想到的是,推送的时候如果客户端有缓存了,那不就浪费了吗~(https://www.zhihu.com/question/24774343/answer/96586977)

把所有 HTTPS 项目无脑升级成 HTTP/2 会有什么坑吗? - 小爝的回答 - 知乎 https://www.zhihu.com/question/310263956/answer/582342502

webSocket

websocket: WebSocket是基于HTTP1.1的协议,可以简单理解为创建了一条TCP连接

Upgrade: websocket
Connection: Upgrade

p.s. 所以对应的 nginx 配置需要新增:

location / {
        #...
        proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}
  • 就服务端推送而言,Http/2 与 websocket?

https://stackoverflow.com/questions/28582935/does-http-2-make-websockets-obsolete

http1 的劣势:

请求头太大(200 B 一次 对比 websocket 6 B 一次)。

http2 推送的意义:服务端自动送资源到客户端,但那不是应用程序可以感知的,主要是让浏览器(用户代理)提前缓存静态资源

  • 那 websocket 与 SSE 呢?

SSE 可以只管推送,并且似乎使用更简单支持更广泛。主要还是从语义上考虑,「bidirectional data stream」与「publish-subscribe 模式」的区别。前者适合聊天游戏,后者适合 feed 推送。我觉得在业务不确定的情况下,为考虑以后客户端也需要向服务端通信的可能,还是用 websocket 更保险。

以及有个疑问,每个客户端上线,肯定需要告知服务端「它在了」。websocket 天然由客户端发起请求,那 SSE 呢?

https

It uses SSL or TLS to encrypt all communication between a client and a server.

SSL: Secure Sockets Layer

TLS: Transport Layer Security. The successor of SSL

就我个人的理解,TLS 握手的目的是生成一份对称加密的公共秘钥,而如何安全的生成这份秘钥需要做很多事情。

  1. CA 证书:包含一个私钥和公钥,以及电子签名
  2. 服务端发送CA签名的证书,里面包括服务端的一份公钥 //避免伪造的服务端【数字证书 —— 安全地发放公钥
  3. 客户端经证书验证后,取出公钥,用该公钥加密一个随机数作为对称加密的秘钥,发送给服务端
  4. 服务端用自己的秘钥解密,获取日后通信的秘钥

Refs:

  • https://en.wikipedia.org/wiki/Transport_Layer_Security
  • https://www.cloudflare.com/zh-cn/learning/ssl/what-happens-in-a-tls-handshake/

HSTS

是什么?

HTTP Strict Transport Security。

服务器可以强制浏览器使用https通信(使用xxx策略),并且不可忽略不安全的证书提示,(以减少会话劫持风险)。

也就是用户访问https后,只要服务器返回带有strict-transport-security: max-age=31536000; includeSubDomains; preload 的头;

那么以后用户再通过http访问该域名时,浏览器会先返回 307 internal redirect, 并跳转到新的 https 地址。

  • 不足一:首次连接仍有风险

用户首次访问某网站是不受HSTS保护的。这是因为首次访问时,浏览器还未收到HSTS,所以仍有可能通过明文HTTP来访问。解决这个不足当前有两种方案,一是浏览器预置HSTS域名列表,Google ChromeFirefoxInternet ExplorerMicrosoft Edge实现了这一方案[11][12]。二是将HSTS信息加入到域名系统记录中。但这需要保证DNS的安全性,也就是需要部署域名系统安全扩展

见chrome的内置hsts列表: https://src.chromium.org/viewvc/chrome/trunk/src/net/http/transport_security_state_static.json

  • 麻烦点:

如果服务器后续修改了配置,又不支持https了,需要用户手动到浏览器清除hsts记忆

http://carlislebear.blogspot.com/2018/06/307-internal-redirect.html

ref: https://zh.wikipedia.org/wiki/HTTP%E4%B8%A5%E6%A0%BC%E4%BC%A0%E8%BE%93%E5%AE%89%E5%85%A8

gzip 附则

https://segmentfault.com/a/1190000012800222

// 好的思考在于:传到 oss 上的文件就是 gzip ,而不是在 nginx 收到请求时再去压缩,能节约服务端的压缩时间