Nginx基础教程(55)Nginx HTTP子请求之子请求运行机制:Nginx子请求:内部协作利器,还是性能杀手?

为了让Nginx高效地处理复杂请求,子请求机制用好了能事半功倍,用砸了则后患无穷。

1. 什么是子请求:外部请求与内部调用的艺术

在Nginx世界里,有两种不同类型的“请求”:一种是由客户端从Nginx外部发起的“主请求”(main request),另一种则是由Nginx正在处理的请求在Nginx内部发起的“子请求”(subrequest)。

简单来说,主请求是外部客户端发起的真实HTTP请求,而子请求则是Nginx内部的一种抽象调用,和HTTP协议乃至网络通信一点儿关系都没有。

子请求在外观上很像HTTP请求,但实现上却是Nginx内部的一种高效抽象。它的目的是为了方便用户把“主请求”的任务分解为多个较小粒度的“内部请求”,并发或串行地访问多个location接口。

举个例子,假设你要构建一个首页,需要展示用户信息、最新文章和热门话题。你可以创建三个独立的location,分别处理这三块内容,然后在主location中通过子请求将它们组合起来。

子请求的优势在于它的执行效率极高。因为这种通信是在同一个Nginx实例内部进行的,所以Nginx核心在实现“子请求”的时候,只调用了若干个C函数,完全不涉及任何网络或者UNIX套接字(socket)通信。

2. 子请求的核心运行机制

2.1 父子请求的关系

当一个请求发起一个“子请求”的时候,按照Nginx的术语,习惯把前者称为后者的“父请求”(parent request)。值得一提的是,Apache服务器中其实也有“子请求”的概念。

“子请求”的概念是相对的,任何一个“子请求”也可以再发起更多的“子子请求”,甚至可以玩递归调用(即自己调用自己)。这就好比公司里的项目组,项目经理(主请求)可以把任务分解给多个组员(子请求),而每个组员如果任务太重,还可以进一步分解给其他人(子子请求)。

2.2 变量值容器的生命期

在前面系列文章中我们已经了解到,变量值容器的生命期是与请求绑定的 。每个请求都有所有变量值容器的独立副本,即便是父子请求之间,同名变量一般也不会相互干扰。

让我们通过一个例子来验证这个说法:

location /main {
    set $var main;
    echo_location /foo;
    echo_location /bar;
    echo "main: $var";
}

location /foo {
    set $var foo;
    echo "foo: $var";
}

location /bar {
    set $var bar;
    echo "bar: $var";
}

在这个例子中,我们分别在/main、/foo和/bar这三个location中为同名变量$var设置不同的值并输出。请求/main接口的结果是这样的:

$ curl 'http://localhost:8080/main'
foo: foo
bar: bar
main: main

显然,/foo和/bar这两个“子请求”在处理过程中对变量$var各自所做的修改都丝毫没有影响到“主请求”/main。这成功印证了“主请求”以及各个“子请求”都拥有不同的变量值容器副本。

2.3 不幸的例外:ngx_auth_request模块

然而,并非所有模块发起的子请求都遵循这个规则。一些Nginx模块发起的“子请求”会自动共享其“父请求”的变量值容器,比如第三方模块ngx_auth_request。

下面是一个例子:

location /main {
    set $var main;
    auth_request /sub;
    echo "main: $var";
}

location /su
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

值引力

持续创作,多谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值