在各个代理和服务器、客户端节点之间的是一段一段的TCP连接,客户端通过中间代理,访问目标服务器的过程也叫逐段传输,用于逐段传输的请求头被称为逐段传输头。
逐段传输头会在每一段传输的中间代理中处理掉,不会往下传输给下一个代理。
标准的逐段传输头有:Keep-Alive, Transfer-Encoding, TE, Connection, Trailer, Upgrade, Proxy-Authorization 和 Proxy-Authenticate。
Connection 头(header) 决定当前的事务完成后,是否会关闭网络连接。如果该值是“keep-alive”,网络连接就是持久的,不会关闭,使得对同一个服务器的请求可以继续在该连接上完成。
除此之外,除了标准的逐段传输头,任何逐段传输头都需要在Connection头中列出,这样才能够让请求的代理知道并处理掉它们并且不转发这些头,当然,标准的逐段传输头也可以列出。
有了这个Connection头,代理就知道要处理掉哪些请求头了, 比如代理会处理掉Keep-Alive,根据自己的实际情况看看是否支持Keep-Alive,如果不支持,就不会继续往下传了。
Nginx keep-alive比如,Nginx作为反向代理,可以为其设置keep-alive机制,nginx开启了keep-alive的时候,连接是这样的 :
Nginx中关于keep-alive的设置:
keepalive: 设置连接池最大的空闲连接数量;
keepalive_timeout: 设置客户端连接超时时间,为0的时候表示禁用长连接;
keepalive_requests: 设置一个长连接上可以服务的最大请求数量。
古老的代理如何处理持久连接网络是复杂的,特别是加入了很多代理之后,假如客户端想要发起持久连接,而中间某些古老的代理服务器,可能不认识Connection头,也不支持持久连接,会出现什么情况呢?
如上图,中间的两台代理不认识Connection: keep-alive,于是直接转发了,最终服务器收到这个头,以为proxy2要和他建立持久连接,于是响应了Connection: keep-alive,代理服务器转发回给客户端,客户端以为建立成功了长连接,于是继续使用这个连接发送消息,可是中间的代理在处理完请求响应之后,早就已经把TCP连接给关闭了,从而最终导致浏览器请求连接超时。
为了避免这类问题,有时候服务器会选择直接忽略HTTP/1.0的Keep-Alive特性,也就是不使用持久连接,也不会返回Keep-Alive给客户端。
4.6.2、隧道代理HTTP客户端可以通过CONNECT方法请求隧道代理创建一个到人任意目标服务器和端口号的TCP连接,连接创建完成之后,后续隧道代理只做请求和响应数据的转发,就像一条隧道一样,这也是隧道代理名字的由来。
为什么需要隧道代理?想象以下,我们要请求的HTTPS服务中间经过了代理,我们是不是 要先让客户端跟代理服务器建立HTTPS连接呢?显然这样是无法实现的,因为中间代理没有网站的私钥证书,所以最终导致浏览器和代理之间的TLS无法创建。
为了解决这个问题,于是引入了隧道代理,隧道代理不在作为中间人,也不会改写浏览器的任何请求,而是把浏览器的通信数据原样透传,这样就实现了让客户端通过中间代理,和服务器进行TLS握手,然后进行加密传输。
其工作流程大致如下:
4.7、HTTP重定向这里我们重点关注两个:
301 永久重定向
302 临时重定向
在收到重定向的状态码之后,客户端会检测响应头里面的Location字段,从里面取出URI,从而自动发起新的HTTP请求。
最常见的使用重定向的例子:
由于网页迁移,为了不影响SEO,把旧的网址的URL 301重定向到新版的网址;
由于服务临时升级,把原来服务请求302重定向到一个升级提示页面,但这样会导致服务端多了一倍的请求量,有时候我们是直接在服务端反悔了升级提示的页面。
这篇文章的内容就介绍到这里,能够阅读到这里的朋友真的是很有耐心,为你点个赞。
本文为arthinking基于相关技术资料和官方文档撰写而成,确保内容的准确性,如果你发现了有何错漏之处,烦请高抬贵手帮忙指正,万分感激。
如果您觉得读完本文有所收获的话,可以关注我的账号,或者点赞吧,码字不易,您的支持就是我写作的最大动力,再次感谢!
为了把相关系列文章收集起来,方便后续查阅,这里我创建了一个Github仓库,把发布的文章按照分类收集起来了,感兴趣的朋友可以Star跟进:
https://github.com/arthinking/java-tech-stack