1. 基础知识

1.1 基本配置

main                                # 全局配置
events {                            # nginx 工作模式配置
}
http {                                # http 设置
    ....
    server {                        # 服务器主机配置
        ....
        location {                    # 路由配置
            ....
        }
        location path {
            ....
        }
        location otherpath {
            ....
        }
    }
    server {
        ....
        location {
            ....
        }
    }
    upstream name {                    # 负载均衡配置
        ....
    }
}

如果想要生成 nginx 规范配置,可以参考nginxconfig.io

下面是 nginx 一些配置中常用的内置全局变量,你可以在配置的任何位置使用它们。

变量名 功能
$host 请求信息中的 Host,如果请求中没有 Host 行,则等于设置的服务器名
$request_method 客户端请求类型,如 GETPOST
$remote_addr 客户端的 IP 地址
$args 请求中的参数
$content_length 请求头中的 Content-length 字段
$http_user_agent 客户端 agent 信息
$http_cookie 客户端 cookie 信息
$remote_addr 客户端的 IP 地址
$remote_port 客户端的端口
$server_protocol 请求使用的协议,如 HTTP/1.0HTTP/1.1\
$server_addr 服务器地址
$server_name 服务器名称
$server_port 服务器的端口号

1.2 location 匹配规则

语法规则:location [=|~|~*|^~] /uri/ { … }

模式 含义
location = /uri = 表示精确匹配,只有完全匹配上才能生效
location ^~ /uri ^~ 开头对 URL 路径进行前缀匹配,并且在正则之前。
location ~ pattern 开头表示区分大小写的正则匹配
location ~* pattern 开头表示不区分大小写的正则匹配
location /uri 不带任何修饰符,也表示前缀匹配,但是在正则匹配之后
location / 通用匹配,任何未匹配到其它 location 的请求都会匹配到,相当于 switch 中的 default

前缀匹配时,Nginx 不对 url 做编码,因此请求为 /static/20%/aa,可以被规则 ^~ /static/ /aa 匹配到(注意是空格)

多个 location 配置的情况下匹配顺序为:

意:前缀匹配,如果有包含关系时,按最大匹配原则进行匹配。比如在前缀匹配:location /dir01location /dir01/dir02,如有请求 http://localhost/dir01/dir02/file 将最终匹配到 location /dir01/dir02

例子,有如下匹配规则:

location = / {
   echo "规则 A";
}
location = /login {
   echo "规则 B";
}
location ^~ /static/ {
   echo "规则 C";
}
location ^~ /static/files {
    echo "规则 X";
}
location ~ \.(gif|jpg|png|js|css)$ {
   echo "规则 D";
}
location ~* \.png$ {
   echo "规则 E";
}
location /img {
    echo "规则 Y";
}
location / {
   echo "规则 F";
}

那么产生的效果如下:

访问 http://localhost/category/id/1111 则最终匹配到规则 F ,因为以上规则都不匹配,这个时候应该是 Nginx 转发请求给后端应用服务器,比如 FastCGI(php),tomcat(jsp),Nginx 作为反向代理服务器存在。

理解 Nginx 中 Server 和 Location 的匹配逻辑

1.3 nginx 日志

Nginx 日志主要有两种:access_log(访问日志) 和 error_log(错误日志)。

1.3.1 access_log 访问日志

access_log 主要记录客户端访问 Nginx 的每一个请求,格式可以自定义。通过 access_log 你可以得到用户地域来源、跳转来源、使用终端、某个 URL 访问量等相关信息。

nginx log 文件默认地址 /var/log/nginx/;

log_format 指令用于定义日志的格式,语法: log_format name string; 其中 name 表示格式名称,string 表示定义的格式字符串。log_format 有一个默认的无需设置的组合日志格式。

默认的无需设置的组合日志格式

log_format combined '$remote_addr - $remote_user  [$time_local]  '
                    ' "$request"  $status  $body_bytes_sent  '
                    ' "$http_referer"  "$http_user_agent" ';

access_log 指令用来指定访问日志文件的存放路径(包含日志文件名)、格式和缓存大小,语法:access_log path [format_name [buffer=size | off]]; 其中 path 表示访问日志存放路径,format_name 表示访问日志格式名称,buffer 表示缓存大小,off 表示关闭访问日志。

log_format 使用示例:在 access.log 中记录客户端 IP 地址、请求状态和请求时间

log_format myformat '$remote_addr  $status  $time_local';
access_log logs/access.log  myformat;

需要注意的是:log_format 配置必须放在 http 内,否则会出现警告。Nginx 进程设置的用户和组必须对日志路径有创建文件的权限,否则,会报错。

定义日志使用的字段及其作用:

字段 作用
$remote_addr 与 $http_x_forwarded_for 记录客户端 IP 地址
$remote_user 记录客户端用户名称
$request 记录请求的 URI 和 HTTP 协议
$status 记录请求状态
$body_bytes_sent 发送给客户端的字节数,不包括响应头的大小
$bytes_sent 发送给客户端的总字节数
$connection 连接的序列号
$connection_requests 当前通过一个连接获得的请求数量
$msec 日志写入时间。单位为秒,精度是毫秒
$pipe 如果请求是通过 HTTP 流水线 (pipelined) 发送,pipe 值为“p”,否则为“.”
$http_referer 记录从哪个页面链接访问过来的
$http_user_agent 记录客户端浏览器相关信息
$request_length 请求的长度(包括请求行,请求头和请求正文)
$request_time 请求处理时间,单位为秒,精度毫秒
$time_iso8601 ISO8601 标准格式下的本地时间
$time_local 记录访问时间与时区

1.3.2 error_log 错误日志

error_log 主要记录客户端访问 Nginx 出错时的日志,格式不支持自定义。通过查看错误日志,你可以得到系统某个服务或 server 的性能瓶颈等。因此,将日志利用好,你可以得到很多有价值的信息。

error_log 指令用来指定错误日志,语法: error_log path [level]; 其中 path 表示错误日志存放路径,level 表示错误日志等级,日志等级包括 debug、info、notice、warn、error、crit、alert、emerg,从左至右,日志详细程度逐级递减,即 debug 最详细,emerg 最少,默认为 error。

注意:error_log off 并不能关闭错误日志记录,此时日志信息会被写入到文件名为 off 的文件当中。如果要关闭错误日志记录,可以使用如下配置:

Linux 系统把存储位置设置为空设备

error_log /dev/null;
http {
    # ...
}

Windows 系统把存储位置设置为空设备

error_log nul;
http {
    # ...
}

另外 Linux 系统可以使用 tail 命令方便的查阅正在改变的文件, tail -f filename 会把 filename 里最尾部的内容显示在屏幕上, 并且不断刷新, 使你看到最新的文件内容。Windows 系统没有这个命令,你可以在网上找到动态查看文件的工具。

1.4 nginx 负载均衡

Upstream 指定后端服务器地址列表,在 server 中拦截响应请求,并将请求转发到 Upstream 中配置的服务器列表。

upstream balanceServer {
    server 10.1.22.33:12345;
    server 10.1.22.34:12345;
    server 10.1.22.35:12345;
}
server {
    server_name  fe.server.com;
    listen 80;
    location /api {
    	### 转发到指定服务器或url
        proxy_pass http://balanceServer;
    }
}

上面的配置只是指定了 nginx 需要转发的服务端列表,并没有指定分配策略。

默认情况下采用的是轮询策略,将所有客户端请求轮询分配给服务端。这种策略是可以正常工作的,但是如果其中某一台服务器压力太大,出现延迟,会影响所有分配在这台服务器下的用户。

1.5 nginx 常用命令

# 快速关闭 Nginx,可能不保存相关信息,并迅速终止 web 服务
nginx -s stop
# 平稳关闭 Nginx,保存相关信息,有安排的结束 web 服务
nginx -s quit
# 因改变了 Nginx 相关配置,需要重新加载配置而重载
nginx -s reload
# 重新打开日志文件
nginx -s reopen
# 为 Nginx 指定一个配置文件,来代替缺省的
nginx -c filename
# 不运行,而仅仅测试配置文件。nginx 将检查配置文件的语法的正确性,并尝试打开配置文件中所引用到的文件
nginx -t
#  显示 nginx 的版本
nginx -v
# 显示 nginx 的版本,编译器版本和配置参数
nginx -V
# 格式换显示 nginx 配置参数
2>&1 nginx -V | xargs -n1
2>&1 nginx -V | xargs -n1 | grep lua

2. 反向代理

location / {
    ### 反向代理的地址
    proxy_pass http://localhost:8080/web/;  
    #以下三个proxy_set_header配置项是重点  
    proxy_set_header Host $host;  
    proxy_set_header X-Real-IP $remote_addr;  
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  
}

proxy_set_header:让后端服务器能获取到前端用户真实IP,而不只是代理服务器的IP。配置示例如下(还需将后端Apache日志格式中的%h替换为%{X-Real-IP}i):

client_body_buffer_size:客户端请求主体缓冲区大小

proxy_connect_timeout:代理服务器和后端真实服务器握手连接超时时间

proxy_send_timeout:后端服务器回传数据给Nginx的时间,需要在设置的时间范围内发送完所有数据,否则Nginx将断开连接

proxy_read_timeout:代理服务器和后端服务器连接成功后,等待后端服务器响应时间

3. 负载均衡

3.1 常用参数

server:负载均衡后端服务器的IP或域名,不写端口的话默认是80。高并发场景用域名,再通过DNS进行负载均衡

weight:后端服务器权重,默认为1,权重越大接收的请求越多。例:weight=5

max_fails:检查节点的健康状态并允许请求失败的次数,达到该次数就将节点下线。默认为1,0表示禁止失败尝试。例:max_fails=2

fail_timeout:max_fails失败次数达到限制后暂停该节点服务的时间,默认是10秒。例:fail_timeout=10s

backup:热备配置,当服务池中所有服务器均出现问题后会自动上线backup服务器

d****own:标志服务器不可用,不参与负载均衡。这个参数通常配合IP_HASH使用

max_conns:限制最大连接数,通常对后端服务器硬件不一致的情况进行配置

upstream linuxe_backend {
  server 192.168.1.110 down;  #该节点不可用
  server 192.168.1.120 backup;  #其他节点挂了后该节点自动上线
  server 192.168.1.130 max_failes=1 fail_timeout=10s weight-5;
  server backend1.linuxe.cn 8080 weight=3
}

3.2 默认的调度算法

  1. 轮询(默认);
  2. 加权轮询;
  3. IP HASH;

3.3 实例

加权轮询:

http {
    upstream  myserver{        
        server 192.168.1.100 weight=3;        #指定后端服务器地址,权重为3
        server 192.168.1.110;      
    }
    server {
        listen 80;
        server name www.myserver.com;
        location / {
            proxy_pass http://myserver;        
        }
    }

IP HASH:

upstream myserver {
    ip_hash;        #采用IP HASH算法
    server 192.168.1.100;
    server 192.168.1.110;
    server 192.168.1.120;
}

URL HASH:


upstream myserver {
    hash $request_uri;    
    server 192.168.1.100;
    server 192.168.1.110;
    server 192.168.1.120;
}

连接数轮询:


http{ 
  upstream sampleapp { 
    least_conn; 
    server <<dns entry or IP Address(optional with port)>>; 
    server <<another dns entry or IP Address(optional with port)>>; 
  } 
  .... 
  server{ 
    listen 80; 
    ... 
    location / { 
     proxy_pass http://sampleapp; 
    }  
	}

4. Nginx location 和 proxy_pass路径配置详解

见文档 Nginx location 和 proxy_pass路径配置详解

proxy_pass,如果和location 都加了/,lcoation 里的前缀会被去掉,参考文档 proxy_pass详解;

  1. 当在后面的 upstram_name 后面出现了 /,相当于是绝对根路径,则 nginx 不会把 location 中匹配的路径部分代理走;
  2. 如果没有 /,则会把匹配的路径部分也给代理走;

参考文章

[1] nginx documentation

[2] 前端开发者必备的 nginx 知识

[3] 百万并发下 Nginx 的优化之道

[4] agentzh 的 Nginx 教程

[5] OpenResty 最佳实践

[6] Nginx 核心知识 100 讲

[7] 极客时间:nginx 核心知识 100 讲配置文件与代码分享

[8] OpenResty 从入门到实战

[9] Nginx 基础知识从小白到入门

[10] 【Nginx配置】使用upstream和proxy_pass实现反向代理与负载均衡

[11] Nginx location 和 proxy_pass路径配置详解

发表回复