美文网首页Nginx高端成长之路Api设计
【充电】《Nginx核心知识100讲》proxy模块:与上游服务

【充电】《Nginx核心知识100讲》proxy模块:与上游服务

作者: 言十年 | 来源:发表于2019-01-19 17:08 被阅读10次

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

    92 | 与上游服务建立连接

    前面介绍了http 反向代理中的前三个流程包括用proxy_pass指令定义反向代理开始生效,以及有些指令去生成了发向上游的请求的内容。第三步开始接受完整的请求包体。如果请求有包体的话。现在到了第四步,开始讨论nginx与上游建立连接这样一个过程,有哪些指令可以控制它的行为。

    对于proxy_pass指令。有些同学有这样的一个问题,有一些其他的content的阶段的,比如static 这样的模块,它们提供的root ,alias 这样的静态资源访问的指令。谁的优先级更高呢?肯定是proxy_pass。它是动作类指令(之前说过),它的优先级高于其他的content模块的指令的。

    在生成上游服务器的ip地址是跟upstream 负载均衡策略(在第四部门开始的几节课说过了)。现在看下当我们拿到上游服务器的地址跟参数以后,开始连接上游服务器以及发送请求。

    与上游建立连接

    image.png

    与上游建立连接第一个关注点就是建立TCP连接,建立TCP连接也就是我们常说的三次握手。所以第一个指令叫做proxy_connect_timeout 控制握手的时间最长不超过60秒。60秒内三次握手都没有成功建立时候,其实上游是不会生成响应的,因为没连接。但是nginx会生成一个响应502。如果客户端收到的是502,一定是nginx没有向上游建立成功连接。当然如果我们的路由压根就没有生效(就是我们访问的上游的地址)就不会等到60秒才生成502的响应了。

    如果生成了502之后还是有办法处理的。后面的课程中会谈到当出现错误的时候可以去换一个上游服务器去继续处理请求。是通过proxy_next_upstream。它后面可以跟很多错误码。其中一个错误码是http_502,也就说,通过超时或者其他原因,没有与上游成功建立连接,我再换一台上游服务器,重新去处理。

    当上游连接建立成功以后,这个时候有一个概念keepalive。http 的keepalive跟tcp的keepalive不一样。先谈下tcp 的keepalive。

    tcp 的keepalive

    image.png

    当有数据接收的时候,紧接着有一段时间,可以设置这段时间的时长。如果没有任何请求的话,就要做一次探测,看看对端是否还在建立连接。会发送一个探测包。当对端是ok的话就会发一个探测包的应答。这样一个场景基于原理是tcp层是由操作系统来实现的。只要我们的进程还在,只要客户端与服务器之间的网络是正常的。那么发探测包。探测包就会有应答。反之当客户端的主机我们根本找不到了,或者主机上的进程已经不存在了。这个时候发探测包,对端就会响应或者不响应,我们就知道这个连接已经不在存活了。所以就可以把这个连接关掉了。

    tcp keepalive 它的核心的目的就是去把一些不在使用的连接及时的关闭来降低资源的浪费,在第五部分会详细的谈keepalive中。控制它的各个参数。这里做一个简单的了解。当我们使用proxy_socket_keepalive指令,设置为On的时候,会使用操作系统默认的keepalive相关的配置去使用tcp keepalive来降低资源的使用。

    http的keepalive

    image.png

    keepalive_requests :标识一个连接最执行多少http个请求。

    绑定ip地址

    image.png

    proxy_bind:它的用法主要有两类用途,第一类用途就是当我们nginx上有多个ip地址时,可能有多个路由的策略是不同的,比如内网或者外网等,这个时候不要使用系统默认给我们选择的ip地址,而是主动使用一个ip地址。这个时候用proxy_bind。第二种场景,很可能为了传递一个ip地址,就是透传ip地址的策略,比如在stream反向代理中会很常用,在之后还会详述。这里先说下proxy_bind用法。

    proxy_bind $remote_addr 也就是客户端的地址绑定到这里。绑定变量的时候呢,如果地址不是本地的地址,linux必须要加transparent。非linux操作系统呢需要保证worker进程有root 权限的,才能人为的修改socket的local address。

    怎么做到这一点的呢?或者其实这是什么意思呢?看右图,这是一个ip头。所有的tcp连接都是基于ip地址的。一个ip头中会有source ip address和destination ip address。这个proxy_bind 就是在修改source ip address。它会使得我们发到上游收到包的来源是proxy_bind 定义的ip地址。我们需要保证上游返回的内容,它的路由还是能返回nginx。nginx才可以继续处理。

    关闭

    当客户端关闭的时候,还有一个选项也是控制与上游之间的连接的。proxy_ignore_client_abort指令。

    image.png

    proxy_ignore_client_abort:当client出现失败。关掉连接了,我的proxy功能是否要忽略。如果忽略,客户端跟nginx可能连接关了,但是nginx与上游之间的连接还是要正常工作的。默认这个功能是关掉(proxy_ignore_client_abort off)的。因为它会给上游带来更大的性能压力。

    向上游发送

    image.png

    以上我们谈了与上游服务建立好tcp连接,并把请求发送给上游。

    留言问题

    1.有个问题请教一下。我们这边采用openresty开发,有时会-s reload服务。出现情况从监控上看我们这边流量正常,但是上游流量有一个短暂的大幅下滑,上游跟我们部署在同一个openresty上,使用upstream 代理过去,下面是配置

    upstream backend.proxy {
    server 127.0.0.1:8088; 
    keepalive 16;
    }
    

     作者回复
    本机的上游?试试走unix socket看看?走TCP网络栈的话,总会有一些网络消耗,例如握手、拥塞控制等,先排除掉看看。

    相关文章

      网友评论

        本文标题:【充电】《Nginx核心知识100讲》proxy模块:与上游服务

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