本文将结合实际的源码来探讨nginx的脚本实现原理,并会在最后对此进行总结。本次只展示复杂变量,对于其if等指令后续文章再来探讨。
nginx的脚本支持使其具备了强大的灵活性,我们可以使用简单的脚本指令配置,进行灵活的功能定制。欲了解此功能,必先了解其变量的实现原理.(nginx变量),先看3个配置示例:
示例1:
location / {
if ($host = “127.0.0.1”) {
return 200 'you request is from local';
}
}
示例2:
map $host $proxy{
127.0.0.1 127.0.0.1:8080;
default 127.0.0.1:80;
}
...
location / {
proxy_pass $proxy;
}
示例3:
location / {
proxy_pass '127.0.0.1:$my_port'
}
我们可以根据一些参数的值,来走指定的业务。
下面我们来看http_proxy_module源码为例来解析。
下面先说说nginx的脚本(复杂变量)实现的基本原理,以http为例。
其主要源码在http/ngx_http_script.c中
基本原理:
将指令翻译成一个个执行单元,然后依次执行每个单元。
是不是很简单就一句话,但是深究起来还是很复杂的,但是首先要记住这个基本的原理。每个执行单元就好比我们的一条cpu执行指令一样。执行单元其本质就是一个函数,就是依次调用每个函数而已。
我们以proxy_pass ‘127.0.0.1:$my_port’ 这个配置为例
前面是常量字符串,加一个变量$my_port,那么我们最终需要做的就是将常量+变量计算出来的值相加后,得到代理的完整地址。
然后我们结合源码来解释。
先看几个结构体
ngx_http_script_engine_t,看字面意思是脚本引擎,我们可以将其看做是cpu
typedef struct {
ngx_http_script_code_pt code;//执行函数(函数指针)
uintptr_t len; //值长度,变量值的长度
} ngx_http_script_copy_code_t;
字面意思是脚本拷贝指令,其就是一个执行单元,结构体以code_t结尾的基本都是执行单元。
此结构体计算的是常量,len等于常量的字符串长度
typedef struct {
ngx_http_script_code_pt code;
uintptr_t