目录

Nginx tips

internal指令.

只能用于location上下文; 表示只能是内部请求可以访问该location; 每个内部请求最多只能跳转10次, 超过限制次数, 会在error_log中打印500错误.

关闭日志

nginx 关闭某个server 块的access_logerror_log, 特别注意关闭error_log的用法.

1
2
3
4
5
6
server {
    listen 443 ssl;
    server_name _;
    access_log  off;
    error_log /dev/null;
    }

lastbreak的区别

break和last都能阻止继续执行后面的rewrite指令, last对于重写后的URI会重新匹配location, 而break不会重新匹配location.

last: 停止当前这个请求, 并根据rewrite匹配的规则重新发起一个内部请求. 新请求又从第一阶段开始执行.

break: 相对last, 重写完URI后, break并不会重新发起一个请求, 而只是跳过当前的rewrite阶段, 并执行本请求location后续的执行阶段.

请求头字段不能使用下划线

nginx默认request的header的中包含_时, 会自动忽略掉.

解决方法是: 在nginx里的nginx.conf配置文件中的http部分中添加如下配置:

1
underscores_in_headers on;  # 默认是off的

另外不建议开启, 因为可能会存在安全风险.

理解ngx_http_stub_status_module模块引入的几个参数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Active connections: 291
server accepts handled requests
     16630948 16630948 31070465
Reading: 6 Writing: 179 Waiting: 106

# requests 是客户端的总请求数
# accepts 是nginx接受的客户端的请求数
# handled 是nginx处理的客户端的请求数
# 一般情况下accepts和handled的数量是相等的, 除非达到了一些系统资源的限制, 比如worker_connections的限制.

# Reading 表示当前有多少个tcp连接正在用于nginx读取客户端请求的header.
# Writint 表示当前有多少个tcp连接正在用于nginx给客户端写响应.
# Waiting 表示当前有多少个tcp连接正在用于nginx等待客户端的请求.
# Active connections 表示nginx和客户端之间的tcp连接的总数量, 是Reading、Writing、Waiting的数量之和.

ngx-http-proxy-module模块引入的缓存功能的缓存文件说明

1
2
3
4
5
stat 18de49b189a66f57208c47852e2ae15d

Access: 2019-08-07 17:44:44.875091237 +0800   # 对于新生成的缓存文件, 只在第一次请求过来的时候更新此时间.
Modify: 2019-08-07 17:44:27.330409891 +0800   # 文件过期后, 第一个请求过来时, 会想上游验证文件是否还有效, 上游返回304后, 缓存文件内容不会变, 但会更新此时间.
Change: 2019-08-07 17:44:27.330409891 +0800   # 和上一条一致.

理解$proxy_add_x_forwarded_for

1
2
3
4
the "X-Forwarded-For" client request header field with the $remote_addr
variable appended to it, separated by a comma.
If the "X-Forwarded-For" field is not present in the client request header,
the $proxy_add_x_forwarded_for variable is equal to the $remote_addr variable.

这么理解:

用户请求前端nginx, 前端nginx设置的proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for指令, 把用户IP(即$remote_addr)赋值给x-forwarded-for头传递给kong, kong nginx设置的proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for指令,把前端的IP(即$remote_addr)追加给x-forwarded-for头, 以逗号分隔, 传递给后端服务. 这样后端看到的x-forwarded-for头的值就是两个IP了, 用户ip和前端ip.

去掉用户请求uri结尾的/

1
2
3
4
5
# 匹配uri(不包括url参数)结尾带/的请求
if ($uri ~ /$) {
    # 301重定向, 让用户重新请求uri结尾去掉/的url
    rewrite ^(.*)/(.*)$ $1$2 permanent;
}

map指令用法

map指令是由ngx_http_map_module模块提供的, 默认情况下安装nginx都会安装该模块.

map 的主要作用是创建自定义变量, 通过使用nginx的内置变量, 去匹配某些特定规则, 如果匹配成功则设置某个值给自定义变量. 而这个自定义变量又可以作于他用.

场景:

匹配请求url的参数, 如果参数是debug则设置$foo = 1, 默认设置$foo = 0

1
2
3
4
map $args $foo {
    default 0;
    debug   1;
}

解释:

$args是nginx内置变量, 就是获取的请求 url 的参数. 如果$args匹配到debug, 那么$foo的值会被设为1, 如果$args一个都匹配不到$foo就是default定义的值, 这里就是0.

另一个例子:

1
2
3
4
5
    # 指定域名或者泛域名分片缓存
    map $channel $slice_store {
        hostnames;
        default         off;
    }

通过以上代码来说明map的一些用法:

map只能用于http上下文;

只有变量slice_store在使用的时候才会被赋值, 所以即使有很多条map语句, 对于没有使用该变量的清气来说也不会产生任何额外开销;

由上一条说明可知$channel变量可以在之后再定义;

hostnames是map的一个参数, 并不是作为channel变量的值存在的;

参数hostnames必须在map块的第一行, hostnames表明channel变量的值可以是有前缀或者是有后缀的域名, 比如channel变量的值如果是: *.example.com on或者是example.* off等, 那么slice_store变量的值就是onoff, 如果channel变量值是*.example.com "" 或者channel变量没有值, 那么slice_store变量值将是default的值off.

location指令详解

1
2
3
4
Syntax: location [ = | ~ | ~* | ^~ ] uri { ... }
        location @name { ... }
Default: —
Context: server, location

[ = | ~ | ~* | ^~ ]释疑

[ = | ~ | ~* | ^~ ]表示location后有如下5种修饰符的情况:

  • =: 后面的uri是字符串, 对请求的uri做精确匹配(不匹配请求uri的参数), 该location被匹配到后终止继续匹配.
  • ^~: uri是字符串, 修饰符由一个非符号^和一个正则符号~组成, 表示本location匹配完成后, 不继续匹配正则表达式的location.
  • ~: uri是正则表达式, 对请求的uri做正则匹配, 大小写敏感.
  • ~*: uri是正则表达式, 对请求的uri做正则匹配, 大小写不敏感.
  • 没有修饰符: locationuri前没有任何修饰符, uri是字符串, 对请求的uri做字符串前缀匹配, 匹配到一个字符串最长的location, 然后继续匹配正则表达式的location.

匹配顺序说明

如果在同一个上下文配置块内有多个location block, 针对上面介绍的5种类型location, Nginx的匹配顺序为:

首先匹配uri是字符串的location, 包括没有修饰符的、修饰符是=^~的, 这3三种location按照在配置文件出现的先后顺序依次匹配;

如果遇到=修饰符的并且匹配上了, 就立刻终止继续匹配;

否则将这3种location全部匹配一遍, 匹配完成后, 如果修饰符是^~的某个uri字符串最长的location匹配上了, 则终止继续匹配;

否则记录下匹配到的没有修饰符的uri字符串最长的location, 并继续匹配修饰符是~~*location, 这2种location按照在配置文件中出现的先后顺序依次匹配, 匹配上就马上终止继续匹配;

如果都没有匹配上, 则使用之前记录下来的没有修饰符的uri字符串前缀最长的那个location.