美文网首页Nginx高端成长之路Api设计
【充电】《Nginx核心知识100讲》反向代理proxy处理请求

【充电】《Nginx核心知识100讲》反向代理proxy处理请求

作者: 言十年 | 来源:发表于2019-01-18 22:19 被阅读67次

    极客专栏《Nginx核心知识100讲》88小节,笔记
    注意:这个是看专栏视频,敲的哈。这个专栏让我收货蛮大的。

    88 | http反向代理proxy处理请求的流程

    proxy模块从客户端接收的是http协议,转发给上游的还是http协议。

    流程

    image.png

    content阶段:这个阶段是生成发给用户的响应。反向代理通过把请求转发给上游服务,由上游服务生成响应。再转发过来。它也同样的在content阶段生效。在content阶段,因为我们配置了location下的proxy_pass这个指令,反向代理就从这里生效了。最后结束在关闭或复用链接(图右下角)。关闭连接非常简单,复用链接就是我们使用了keepalive请求。

    我们来看下这个流程(反向代理流程)是怎样到达这里的(关闭或复用链接的)。首先到proxy_pass指令的时候,首先看cache有没有命中。根据我们的关键字key(比如url),cache如果命中了就不用向上游服务建立链接了。直接发送响应就可以了。

    局部图

    如果没有命中,就开始往下走,往下走的过程中。会发现,先生成发往上游服务的http头部和包体,而不是先连接上游服务器建立TCP连接。为什么呢?因为建立好连接以后就已经对上游的服务器,比如类似于Tomcat这些它们并发连接不是很强的服务产生的影响了。这个时候我们再花费时间再生成,实际上是不必要的。所以会先生成。

    局部图

    生成这一步的时候,我们有很多proxy提供的指令让我们控制header和body究竟应该要怎么弄。生成好以后,注意content阶段只是收到了用户请求的header,如果用户现在是post协议,有可能含有body,这个body我们还没有收呢。这个时候我们就有一个选择,这个选择是通过proxy_request_buffering 来控制的。当这个指令打开,我们顾名思义就可以看到会使用buffering。使用buffering就意味着我会先读完用户请求的完整包体再继续处理。而off就是关闭了,默认是打开的。为什么默认会打开呢。因为上游的服务并发能力是比较差的,而nginx并发能力是比较强的,而客户端走的是公网。往往网速比较慢,如果提前使用了proxy_request_buffering off,还没有收到包体的时候,就已经开始建连接,采用边读包体边转发给上游的这样一种方式会有一个问题,就是如果这个包体很长,比如说有100M,然后客户端的网速很慢,比如每秒只有10kb。那么就会导致我们nginx与上游的tomcat 建立的时间非常的长。而tomcat它的服务并发链接是非常有限的。所以通常我们会要求nginx先把用户发来的包体全部缓存到磁盘上(也就是proxy_request_buffering on 的情况),收完以后再往下走。proxy_request_buffering 关掉也是可以的,比如我确定我的上游服务可能是另外一些不太在乎并发链接的服务,那么我们就完全可以关闭。因为关掉以后会有更好的即时响应情况。上游会及时收到body的每一个字节而不是会有一个延迟。读取完完整的包体(proxy_request_buffering on )或者关闭buffering以后(proxy_request_buffering off)就开始根据负载均衡策略选择上游服务器。也就是之前所说的round-robin、hash、least conn 等策略,根据这些模块我们选择到一台server指令中指定的上游服务。根据参数取连接上游服务器,实际上我们有很多参数可以控制,包括TCP连接的很多特性。连接上上游服务器后,我们就开始发送请求。如果是采用读取包体,那么就直接发。如果采用proxy_request_buffering off就边读边发。这两种发送方式对内存的使用率是不一样的。

    局部图

    发完请求之后,上游的应用服务,比如tomcat、Django,它们就开始发送它们的响应给nginx了。nginx需要先接收响应的头部。在介绍upstream变量的时候介绍了header_timeout接受header用了多长时间。接受完完整的header,我们会处理响应头部(也有很多的指令去控制它)。

    局部图

    处理完之后,我们又有一个分支通过proxy_buffering 来控制我们怎么样看待上下游之间的网速。对上游服务我们应该怎样对待。proxy_buffering on接收完整的响应body再向下游发放。会用临时文件去存放上游发放的body,为什么要这样做呢?因为上游往往跟nginx处于内网中的,内网中的网速是非常快的。如果我们采用边发送我们收到上游,比如Django发来的一个响应,就发给客户端。因为客户端的网速慢,会导致发送很长时间(因为内存是有限的)。受限于下游的网络速度。而实际上内网网速非常快的。通常我们是打开的(proxy_buffering on),收到完整的包体再向客户端发送我们的响应头部,响应包体。如果是proxy_buffering off就边读包体边发送。

    局部图

    最后我们判断cache是否打开了。打开cache的话,这个请求应该响应被cache。就先加入cache。再到关闭或复用连接。

    image.png

    以上就是反向代理的处理流程。接下来会按照这个流程一步一步,去解释每一步指令的使用方法。

    留言问题

    1. NGINX可以转发websocket流量吗? 转发websocket是不是只能用IP hash 因为有链接的fd

     作者回复
    可以转发websocket流量 ,参见第106课。
    因为ws也是HTTP协议升级而来,故可以使用HTTP变量作为hash方式局部图

    相关文章

      网友评论

        本文标题:【充电】《Nginx核心知识100讲》反向代理proxy处理请求

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