http1.0/1.1/2.0/h2c/golang使用随笔
一、http基本概念
1.1 http是网络的上层应用层,由请求和响应组成,是一个标准的客户端服务器模型,且是无状态的协议。
1.2 http默认端口是80,承载于tls和ssl之上,通过加密、认证方式保证数据传输的安全,称为https,https默认端口443.
1.3 早期http传输html,现在应用广泛,常见于各种接口、数据传输
1.4 http通常基于tcp的,具体传输关系和过程,可自行看此类专题。
1.5 影响http网络请求的主要因素:带宽和延迟
浏览器阻塞(HOL blocking)、
DNS 查询(DNS Lookup)、寻IP地址过程耗时,可用DNS缓存减少频繁lookup
建立连接(Initial connection)。TCP三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。
二、http1和http1.1区别
2.1长链接
HTTP1.1支持长连接,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启长连接keep-alive,一定程度上弥补了HTTP1.0每次请求 都要创建连接的缺点。HTTP1.0需要使用keep-alive参数来告知服务器端要建立一个长连接。
(见http header request Connection)
2.2带宽优化及网络连接的使用
HTTP1.0中存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能。HTTP1.1支持只发送header信息(不带任何body信息),如果服务器认为客户端有权限请求服务器,则返回100,客户端接收到100才开始把请求body发送到服务器;如果返回401,客户端就可以不用发送请求body了节约了带宽。
(RFC2616标准http1.1,支持OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE和CONNECT方法、content-range accept-range。感兴趣可深入研究)
2.3HOST头处理
在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname),HTTP1.0没有host域。随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都支持host域,且请求消息中如果没有host域会报告一个错误(400 Bad Request)。
(见http header request host)
2.4缓存处理
在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
(见http header response cache-control/Expires)
2.5错误通知的管理
在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。(具体百度)
三、http1.1和http2区别
3.1新的二进制格式(Binary Format)
HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
3.1多路复用
即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。HTTP1.1也可以多建立几个TCP连接,来支持处理更多并发的请求,但是创建TCP连接本身也是有开销的。
3.2header压缩
在HTTP1.1中,HTTP请求和响应都是由状态行、请求/响应头部、消息主体三部分组成。一般而言,body体都会经过gzip压缩,或者本身传输的就是压缩过后的二进制文件,但状态行和头部却没有经过任何压缩,直接以纯文本传输。随着Web功能越来越复杂,每个页面产生的请求数也越来越多,导致消耗在头部的流量越来越多,尤其是每次都要传输UserAgent、Cookie这类不会频繁变动的内容,完全是一种浪费。
HTTP1.1不支持header数据的压缩,HTTP2.0使用HPACK算法对header的数据进行压缩,这样数据体积小了,在网络上传输就会更快。
3.3服务端推送
https://www.cnblogs.com/wetest/p/8040202.html
四、常见疑问
4.1HTTP2.0的多路复用和HTTP1.X中的长连接复用有什么区别?
HTTP/1.* 一次请求-响应,建立一个连接,用完关闭;每一个请求都要建立一个连接;
HTTP/1.1 Pipeling解决方式为,若干个请求排队串行化单线程处理,后面的请求等待前面请求的返回才能获得执行机会,一旦有某请求超时等,后续请求只能被阻塞,毫无办法,也就是人们常说的线头阻塞;
HTTP/2多个请求可同时在一个连接上并行执行。某个请求任务耗时严重,不会影响到其它连接的正常执行
4.2服务器推送到底是什么?
服务端推送能把客户端所需要的资源伴随着index.html一起发送到客户端,省去了客户端重复请求的步骤。正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度
https://www.cnblogs.com/wetest/p/8040202.html
4.3h2和h2c
h2指的是建立在 TLS 之上的 HTTP/2 协议,即 HTTP/2 Over TLS。
h2c指的是建立在 TCP 之上的 HTTP/2 协议, 即 HTTP/2 Over TCP,HTTP/2 without TLS。
对于后端接口性质的http2.0,非浏览器请求行为,可使用h2c,减少tls握手/验证的开销。可在可靠的内网中直接通信
五、golang对于http2.0的支持
Go 在 1.6的时候已经支持 HTTP/2 了, 1.8 开始支持 PUSH 功能
h2c 这个功能的讨论2016年就开始了( issue#14141 ),最终5月份的这个功能加上了,这样你就可以在没有TLS使用http/2高性能的特性了。
h2:
var srv http.Server //http2.VerboseLogs = true srv.Addr = ":8972" http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("hello http2")) }) http2.ConfigureServer(&srv, &http2.Server{}) go func() { log.Fatal(srv.ListenAndServeTLS("server.crt", "server.key")) }()
h2c:
mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello h2c") }) s := &http.Server{ Addr: ":8972", Handler: mux, } http2.ConfigureServer(s, &http2.Server{}) log.Fatal(s.ListenAndServe())
现在默认是HTTP/1.1、准备内网开启http2.0,golang knownRoundTripperImpl方法会默认检测使用http1.1或http2.0
以上内容,有网络摘抄。