nginx 学习(1) - nginx配置
简介
重新学习nginx配置, 简单记录下。
学习连接: http://openresty.org/cn/ebooks.html
0. 变量分类:
- 用户自定义变量
- 内建变量
1. nginx变量创建赋值作用域
nginx配置里面的变量是nginx服务启动时创建, 请求到达时进行赋值, 每个请求都有一个变量的副本, 请求内部跳转时变量可以跨location使用。也就是说变量的生命期是和请求绑定的, 可以跨多个location。
“回到先前对 Nginx 变量值容器的生命期的讨论,我们现在依旧可以说,它们的生命期是与当前请求相关联的。每个请求都有所有变量值容器的独立副本,只不过当前请求既可以是“主请求”,也可以是“子请求”。即便是父子请求之间,同名变量一般也不会相互干扰。”
摘录来自: agentzh. “agentzh的Nginx教程(2016.07.21版)”。 iBooks.
echo_location 或者echo_location_async 发起的子请求, 主请求和子请求都会有自己的变量副本, 不会共用。 auth_request 发起的子请求, 主请求和子请求会公用变量副本, 共享变量空间。
2. 内建变量
- $request_uri 包含参数的url,
- $uri 不包含参数
2.1 xxxx变量群
- $arg_xxxx 表示xxxx参数, xxxx字符串不区分大小写
- $http_xxxx, xxxx不区分大小写 用来获取请求头中的xxxx header,
- $cookie_xxxx , 不区分大小写 用来获取请求中的cookie xxxx的值
- $sent_http_xxxx, xxxx不区分大小写 返回头xxxx的值
2.2 存取器
设置和读取变量都封装相应的handler
3 nginx配置中指令执行顺序
3.1 nginx对处理请求分为十几个阶段(phase) 指令执行顺序依赖于指令属于哪个阶段, nginx 请求的三个主要阶段,先后顺序是rewrite, access, content
3.2 一个location中只能使用一个content 阶段的指令, 比如echo ,或者content_by_lua, 两个同时使用时, 只会有一个生效。但是可以在一个location中使用多个echo, 因为多个echo同属于ngx_echo模块。
3.3 content阶段存在三个垫底的静态资源服务模块ngx_index, ngx_autoindex 以及ngx_static。
3.4 Nginx处理请求的11个阶段:
-
post-read 阶段, 此阶段存在的指令有ngx_realip模块的指令: set_real_ip_from, 以及 real_ip_header, 这两个指令配合使用, 使用示例: ` set_real_ip_from 127.0.0.1; real_ip_header X-Real-ip; ` 把来自127.0.0.1的请求的remote_addr 设置为header x-real-ip的值。 后续的阶段或者后端CGI读取的remote_addr都是post-read修改之后的值。 ““注意 只有在x-real-ip header的值是合法ip时, 才会在post_read阶段替换remote_addr””
- server-rewrite 阶段, ngx_rewrite模块的指令直接在server模块中调用就属于server-rewrite阶段, 比如set, rewrite指令
- find-config阶段, 此阶段会完成请求和location的配对。
- rewrite阶段, 请求和某个location配对之后, 便是rewrite阶段, ngx_rewrite模块的指令运行在location中便是在rewrite阶段, 以及ngx_lua的set_by_lua, rewrite_by_lua。
- post-rewrite阶段, rewrite之后是post-rewrite阶段,来做内部跳转,内部跳转的本质是把请求回退到find-config阶段, 对重写后的请求继续和location进行配对
- preaccess阶段, post-rewrite 之后便是preaccess 阶段, ngx_limit_req和ngx_limit_zone模块的指令就运行在preaccessJ阶段
- access 阶段, preaccess之后便是access阶段
- post-access阶段,satisfy 作用于post-access阶段, satisfy指令用来配合access阶段的控制命令来使用。
- try-files阶段,此阶段主要是来实现try-files指令,
- content
- log
try_files 指令接受两个以上任意数量的参数,每个参数都指定了一个 URI. 这里假设配置了 N 个参数,则 Nginx 会在 try-files 阶段,依次把前 N-1 个参数映射为文件系统上的对象(文件或者目录(/结尾会查找目录, 非/结尾会查找文件),然后检查这些对象是否存在。一旦 Nginx 发现某个文件系统对象存在,就会在 try-files 阶段把当前请求的 URI 改写为该对象所对应的参数 URI(但不会包含末尾的斜杠字符,也不会发生 “内部跳转”)。如果前 N-1 个参数所对应的文件系统对象都不存在,try-files 阶段就会立即发起“内部跳转”到最后一个参数(即第 N 个参数)所指定的 URI.
摘录来自: agentzh. “agentzh的Nginx教程(2016.07.21版)”。 iBooks.
参考
agentzh 的 Nginx 教程(版本 2016.07.21)
备注
文中内容仅供参考, 实际使用请自行测试。
附上相关看nginx教程时写的nginx conf
worker_processes 1;
error_log /Users/huyongde/log/nginx/error.log debug;
pid /Users/huyongde/log/nginx.pid;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /Users/huyongde/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 10;
types_hash_max_size 2048;
server {
listen 8666;
server_name default;
set $addr $remote_addr; ##set指令属于ngx_rewrite模块 运行于server-rewrite阶段, 在post-read阶段之后
set_real_ip_from 127.0.0.1; ##这两个指令属于ngx_realio模块运行在post-read阶段,post阶段是nginx处理请求的最早阶段
real_ip_header Real-Ip;
location /satisfy {
satisfy any;
deny all;
access_by_lua "ngx.exit(ngx.OK)";
echo "satisfy all";
}
location /foo {
rewrite ^ /bar;
rewrite ^ /baz;
}
location /bar {
echo "bar";
}
location /baz {
echo "baz";
}
location /test {
echo "addr $addr";
echo "remote_addr : $remote_addr";
set $b "$a , test";
echo "b: $b";
}
set $a "Hello from Server_rewrite"; ## 运行在server_rewrite 阶段, 所以早于所有location内的指令
location /test2 {
echo "args : $args";
}
}
server {
listen 8070;
server_name default;
location /static2 {
root /Users/huyongde/Desktop/html;
try_files /foo =404; # 在root目录下查找foo文件, 找不到就返回404 , 404可以修改为任一http状态码
}
location /static3 {
root /Users/huyongde/Desktop/html;
try_files /bar/ =404; # 在root目录下查找bar目录, 若不存在则返回404 , 若存在bar目录, 则请求uri会被设置为/bar匹配/bar location, 测试时直接返回了301, response header location 是/bar?$args
#bar 目录存在时请求 127.0.0.1:8070/static3?a=1&b=2 返回如下:
#< HTTP/1.1 301 Moved Permanently
#< Server: openresty/1.11.2.5
#< Date: Sun, 05 Nov 2017 14:05:07 GMT
#< Content-Type: text/html
#< Content-Length: 191
#< Location: http://127.0.0.1:8070/bar/?a=1&b=2
#< Connection: keep-alive
#<
#<html>
#<head><title>301 Moved Permanently</title></head>
#<body bgcolor="white">
#<center><h1>301 Moved Permanently</h1></center>
#<hr><center>openresty/1.11.2.5</center>
#</body>
#</html>
}
location /static {
set $orig_uri $uri;
set $orig_request_uri $request_uri;
root /Users/huyongde/Desktop/html;
try_files /index.html /index.htm /not_found; ### 在根目录下查找index.html文件以及index.htm文件,若找到,则把当前请求的uri改写为匹配的try_files参数中的URI, 若前n-1个都不匹配则会跳转到第n个参数指定的uri.
#echo "Orig_uri: $orig_uri, now uri: $uri";
#echo "Orig_request_uri: $orig_request_uri, now uri: $request_uri";
#index index.html index.htm; ### index 指令就是执行了内部跳转
}
location /not_found {
echo "not found";
}
location /index.html {
set $a 10000;
echo "a : $a";
}
location /phase {
# rewrite phase
set $age 100;
rewrite_by_lua "ngx.var.age = ngx.var.age + 10";
# access phase
allow 127.0.0.1;
deny all;
access_by_lua "ngx.var.age = ngx.var.age + 12";
#content phase
echo "Age : $age";
}
location /lua {
content_by_lua '
if ngx.var.arg_name == nil then
ngx.say("param missing")
else
ngx.say("name:[", ngx.var.arg_name, "]" )
end
';
}
location /auth {
allow 127.0.0.1;
deny all;
echo "auth example";
access_by_lua '
if ngx.var.remote_addr == "127.0.0.1" then
ngx.say("from access_by_lua")
else
ngx.exit(403)
end
';
}
location /main { ## 测试主请求 子请求
set $var main;
echo_location /child1;
echo_location /child2;
echo "main : var $var";
}
location /child1 {
echo "child1";
set $var child1_var;
echo "child1 var : $var";
}
location /child2 {
echo "child2";
set $var "child2_var";
echo "child2 var: $var";
}
location /proxy {
set $args "a=1&b=2";
echo_before_body "before proxy";
# 不能直接使用echo指令, echo指令和proxy_pass指令同属content阶段,只会执行proxy_pass, 下面的echo_after_body同理
#
proxy_pass http://127.0.0.1:8666/test2; ## 参数会自动带到新的请求上
echo_after_body "after proxy";
}
location /test {
set $foo "Hello nginx " ;
set $a "$foo $foo ${foo}xxxx";
echo "test echo :$a";
echo "uri = $uri";
echo "request_uri: $request_uri";
echo "params a arg_a: $arg_a";
echo "params a arg_A: $arg_A";
echo "header test: $http_test";
echo "header Test: $http_Test";
echo "cookie test: $cookie_test";
echo "cookie Test: $cookie_Test";
set $sent_http_test "res test header";
set $orig_test $arg_test;
echo "origin param test: $orig_test";
set $args "test=confset";
echo "param test : $arg_test";
}
location /foo {
set $a "foo";
#echo_exec /bar;
rewrite ^ /bar;
}
location /bar {
echo "a=${a}";
}
}
}