美文网首页周分享
HTTP全知道(下)

HTTP全知道(下)

作者: 橙汁坤 | 来源:发表于2020-04-03 15:18 被阅读0次

HTTP1.1 是如何解决队头阻塞问题

书接上文,HTTP 传输是基于请求-应答的模式进行的,报文必须是一发一收,任务被放在一个任务队列中串行执行,而所谓的HTTP队头阻塞问题。是指一旦队首的请求处理太慢,就会阻塞后面请求的处理。

  • 并发连接
    对于一个域名允许分配多个长连接,那么相当于增加了任务队列,不至于一个队伍的任务阻塞其它所有任务。在RFC2616规定过客户端最多并发 2 个连接,不过、现在的浏览器标准中,这个上限要多很多,就比如Chrome 中是 6 个。
  • 域名分片
    一个域名不是可以并发 多个长连接吗?那我就多分几个域名。
    比如 content1.test.com 、content2.test.com。
    这样一个test.com域名下可以分出非常多的二级域名,而它们都指向同样的一台服务器,能够并发的长连接数更多了。事实上也更好地解决了队头阻塞的问题。

即使是提高了并发连接,也满足不了对性能的需求,而只有能够并发的长连接数更多了,才能更好地解决了队头阻塞的问题。

HTTP 代理

HTTP 是基于请求-响应模型的协议,一般由客户端发请求,服务器来进行响应。
但是也有代理服务器的情况。引入代理之后,代理的服务器相当于一个中间人的角色,对于客户端而言,表现为服务器进行响应;而对于源服务器,表现为客户端发起请求,具有双重身份。

  • 能干嘛?
    1. 负载均衡。客户端的请求只会先到达代理服务器,后面到底有多少源服务器,IP 都是多少,客户端是不知道的。因此,代理服务器可以拿到这个请求之后,可以通过特定的算法分发给不同的源服务器,让各台源服务器的负载尽量平均。

    2. 保障安全。利用心跳机制监控后台的服务器,一旦发现故障机就将其踢出集群。并且对于上下行的数据进行过滤,对非法 IP 限流,这些都是代理服务器的工作。

    3. 缓存代理。将内容缓存到代理服务器,使得客户端可以直接从代理服务器获得而不用到源服务器那里。

  • 相关头部字段
  1. Via
    代理服务器需要标明自己的身份,假如有两台代理服务器,在客户端发送请求后会经历这样一个过程:
    客户端 => 代理1 => 代理2 => 源服务器
    源服务器收到请求后,会在请求头拿到这个字段:
    Via: proxy_server1, proxy_server2
    而源服务器响应时,最终在客户端会拿到这样的响应头:
    Via: proxy_server2, proxy_server1
    Via中代理的顺序即为在 HTTP 传输中 报文传达的顺序

  2. X-Forwarded-For
    是为谁转发, 它记录的是请求方的IP地址(和Via区分开只记录请求方这一个IP)。

  3. X-Real-IP
    是一种获取用户真实 IP 的字段,不管中间经过多少代理,这个字段始终记录最初的客户端的IP。
    相应的,还有X-Forwarded-Host和X-Forwarded-Proto,分别记录客户端(注意哦,不包括代理)的域名和协议名。

  4. X-Forwarded-For产生的问题
    前面可以看到,只记录了请求方的 IP,这意味着每经过一个不同的代理,这个字段的名字都要变,由此产生了问题:

  • 意味着代理必须解析 HTTP 请求头,然后修改,比直接转发数据性能下降。
  • 在 HTTPS 通信加密的过程中,原始报文是不允许修改的。

为了解决这个问题产生了代理协议,一般使用明文版本,只需要在 HTTP 请求行上面加如下文本即可:

// PROXY + TCP4/TCP6 + 请求方地址 + 接收方地址 + 请求端口 + 接收端口
PROXY TCP4 0.0.0.1 0.0.0.2 1111 2222
GET / HTTP/1.1

什么是跨域

scheme(协议)、host(主机)和port(端口)都相同则为同源
说到http 就得说到跨域了,在前后端分离的开发模式中,经常会遇到跨域问题,即 Ajax 请求发出去了,服务器也成功响应了,前端就是拿不到这个响应。

非同源站点有这样一些限制
  • 不能读取和修改对方的 DOM
  • 不读访问对方的 Cookie、IndexDB 和 LocalStorage
  • 限制 XMLHttpRequest 请求。

跨域请求是被浏览器拦截,响应其实是成功到达客户端了。那这个拦截是如何发生呢?

  1. 浏览器是多进程的,以 Chrome 为例,进程组成如下:
    当Ajax 请求准备发送的时候,其实还只是在渲染进程的处理。为了防止黑客通过脚本触碰到系统资源,浏览器将每一个渲染进程装进了沙箱,采取了站点隔离的手段。
  2. 在沙箱当中的渲染进程只能通过网络进程来发送网络请。在数据传递给了浏览器主进程,主进程接收到后,才真正地发出相应的网络请求。
    在服务端处理完数据后,将响应返回,主进程检查到跨域,且没有cors响应头,将响应体全部丢掉,并不会发送给渲染进程。这就达到了拦截数据的目的。
解决方案
CORS

CORS 就是是跨域资源共享。它需要浏览器和服务器的共同支持,具体来说,非 IE 和 IE10 以上支持CORS,服务器需要附加特定的响应头,后面具体拆解。
简单请求和非简单请求。

  • 简单请求:
    请求方法为 GET、POST 或者 HEAD
    请求头的取值范围: Accept、Accept-Language、Content-Language、Content- Type(只限于三个值application/x-www-form-urlencoded、multipart/form-data、 text/plain)
    请求发出去之前,浏览器会自动在请求头当中,添加一个Origin字段,用来说明 请求来自哪个源。服务器拿到请求之后,在回应时对应地添加Access-Control-Allow-Origin字段,如果Origin不在这个字段的范围中,那么浏览器就会将响应拦截。
  1. Access-Control-Allow-Origin字段是服务器用来决定浏览器是否拦截这个响应,这是必需的字段。

  2. Access-Control-Allow-Credentials表示是否允许发送 Cookie,对于跨域请求,浏览器对这个字段默认值设为 false,而如果需要拿到浏览器的 Cookie,需要添加这个响应头并设为true, 并且在前端也需要设置withCredentials属性:
    let xhr = new XMLHttpRequest();xhr.withCredentials = true;

  3. Access-Control-Expose-Headers。这个字段是给 XMLHttpRequest 对象赋值,让它不仅可以拿到基本的 响应头字段,还能拿到这个字段声明的响应头字段。比如这样设置:Access-Control-Expose-Headers: test

    前端可以通过 XMLHttpRequest.getResponseHeader('test') 拿到 test 这个字段的值。

  • 非简单请求
    除了上述的就是非简单请求,针对这种请求进行不同的处理。
    主要体现在两个方面: 预检请求和响应字段。
    我们以 PUT 方法为例。

    var url = 'http://xxx.com';
    var xhr = new XMLHttpRequest();
    xhr.open('PUT', url, true);
    xhr.setRequestHeader('X-Custom-Header', 'xxx');
    xhr.send()
    
    1. 预检请求
    OPTIONS / HTTP/1.1
    Origin: 当前地址
    Host: xxx.com
    Access-Control-Request-Method: PUT
    Access-Control-Request-Headers: X-Custom-Header
    

    通过OPTIONS,同时会加上Origin源地址和Host目标地址,同时也会加上两个关键的字段:
    Access-Control-Request-Method, 列出 CORS 请求用到哪个HTTP方法
    Access-Control-Request-Headers,指定 CORS 请求将要加上什么请求头

    1. 响应字段
    • 预检请求的响应
    HTTP/1.1 200 OK
    Access-Control-Allow-Origin: *
    Access-Control-Allow-Methods: GET, POST, PUT
    Access-Control-Allow-Headers: X-Custom-Header
    Access-Control-Allow-Credentials: true
    Access-Control-Max-Age: 1728000
    Content-Type: text/html; charset=utf-8
    Content-Encoding: gzip
    Content-Length: 0
    

    Access-Control-Allow-Origin: 表示可以允许请求的源,可以填具体的源名,也可以填*
    Access-Control-Allow-Methods: 表示允许的请求方法列表
    Access-Control-Allow-Credentials: 表示是否允许发送 Cookie
    Access-Control-Allow-Headers: 表示允许发送的请求头字段
    Access-Control-Max-Age: 预检请求的有效期,在此期间,不用发出另外一条预检请求

    在预检请求的响应返回后,如果请求不满足响应头的条件,则触发XMLHttpRequest的onerror方法,当然后面真正的CORS请求也不会发出去了。
    之后和简单请求一样浏览器自动加上Origin字段,服务端响应头返回Access-Control-Allow-Origin。

JSONP

虽然XMLHttpRequest对象遵循同源政策,但script标签可以通过 src 填上目标地址从而发出 GET 请求,实现跨域请求并拿到响应。这也就是 JSONP 的原理
和CORS相比,JSONP 最大的优势在于兼容性好,IE 低版本不能使用 CORS 但可以使用 JSONP,缺点也很明显,请求方法单一,只支持 GET 请求。

Nginx

Nginx通过反向代理服务器来轻松解决跨域问题。


image.png
  • 正向代理帮助客户端访问客户端自己访问不到的服务器(梯子),然后将结果返回给客户端。
image.png
  • 反向代理拿到客户端的请求,将请求转发给其他的服务器,主要的场景是维持服务器集群的负载均衡,反向代理帮其它的服务器拿到请求,然后选择一个合适的服务器,将请求转交给它。

  • 那 Nginx 是如何来解决跨域的呢?
    客户端的域名为client.com,服务器的域名为server.com,客户端向服务器发送 Ajax 请求,会跨域产生跨域问题了,通过下面这个配置:

server {
  listen  80;
  server_name  client.com;
  location /api {
    proxy_pass server.com;
  }
}

Nginx 相当于起了一个跳板,这个跳板的名字也是client.com,让客户端首先访问 client.com/api,这当然没有跨域,然后 Nginx 服务器作为反向代理,将请求转发给server.com,当响应返回时又将响应给到客户端,这就完成整个跨域请求的过程。就像是在饭馆点餐时,服务员来回穿梭顾客和厨房是一样的道理,服务员记录了我们点的菜品,然后也将厨房的食物送到我们的餐桌上。

相关文章

  • HTTP全知道(下)

    HTTP1.1 是如何解决队头阻塞问题 书接上文,HTTP 传输是基于请求-应答的模式进行的,报文必须是一发一收,...

  • HTTP全知道(上)

    你所需要了解的关于http的一切 HTTP 报文结构 起始行 + 头部 + 空行 + 实体 起始行请求报文格式是方...

  • http全解

    http是目前访问网页最主流的应用层协议,但是对于http应用层和下面的传输层之间的关系,一直不是特别的清楚,遂就...

  • MAC启用本地http服务

    我们都知道要在 windows 下使用 http 访问本机的网页,只需要把 IIS 启用即可,具体的配置一股脑全钩...

  • 04_透视HTTP协议_HTTP世界全览(下):与HTTP相关的

    框架图 重点来说说,与HTTP相关协议,TCP/IP, DNS, URI, HTTPS 细分 TCP/IP 是目前...

  • HTTP状态码(全)

    1xx消息 这一类型的状态码,代表请求已被接受,需要继续处理。这类响应是临时响应,只包含状态行和某些可选的响应头信...

  • HTTP头部全罗列

    title: HTTP协议详解(二)date: 2018-05-18 18:16:47tags: HTTP头部全罗...

  • 全知道

    品牌全知道 品牌全知道 理肤泉敏感全知道 薇姿健康肌肤全知道 中信银行全知道 Windows7全...

  • http理解(下)

    title: http 理解(下)date: 2018-05-16 10:13:42tags: http Web的...

  • 《图解HTTP》(下)

    学习笔记。 第7章 确保Web安全的HTTPS 7.1 HTTP的缺点 通信使用明文(不加密),内容可能被窃听 不...

网友评论

    本文标题:HTTP全知道(下)

    本文链接:https://www.haomeiwen.com/subject/lqwtphtx.html