安装
使用源码安装nginx
1234 | wget https://nginx.org/download/nginx-1.12.2.tar.gzcd nginx-1.12.2 ./configure make && make install |
---|
安装非默认模块
启用 HTTPS 支持
12 | ./configure --prefix=/usr/local/nginx --with-http_ssl_module make && make install |
---|
获取用户真实IP支持
12 | ./configure --prefix=/usr/local/nginx --with-http_realip_modulemake && make install |
---|
配置
http块常用配置
与客户端有关的配置主要在 http 块中设置
指令 | 说明 |
---|---|
client_body_buffer_size | 设置读取客户端请求体的缓冲区大小。如果请求体的大小大于缓冲区的大小,则整个或一部分请求体会被写入临时文件。在默认情况下,会为 32 位系统、x86-64 系统设置8KB 的缓冲区,其他 64 位系统为 16KB 的缓冲区 |
client_body_temp_path | 定义存储客户端请求体的临时文件目录,最多可以定义 3 个子集目录 |
client_body_timeout | 定义读取客户端请求体的超时时间,即两个连续的读操作之间的时间间隔。如果超时HTTP 会抛出 408 错误 |
client_header_buffer_size | 设置客户端请求头的缓冲区大小,默认为 1KB |
client_max_body_size | 设置客户端请求的最大主体的大小,默认为 1MB |
client_header_timeout | 设置客户端请求头的超时时间 |
etag | 如果设置为 on,表示静态资源自动生成 ETag 响应头 |
large_client_header_buffers | 设置大型客户端请求头的缓冲区大小 |
keepalive_timeout | 设置连接超时时间。服务器将在超过超时时间后关闭 HTTP 连接 |
send_timeout | 指定客户端的响应超时时间 |
server_names_hash_bucket_size | 设置 server_names(Nginx 中配置的全部域名)散列表的桶的大小,默认值取决于处理器缓存行的大小 |
server_names_hash_max_size | 设置 server_names 散列表的最大值 |
server_tokens | 启用或禁用在错误页面和服务器响应头字段中标识的 Nginx 版本 |
tcp_nodelay | 启用或禁用 TCP_NODELAY 选项。只有当连接保持活动时,才会被启用 |
tcp_nopush | 仅当 sendfile 时使用,能够将响应头和正文的开始部分一起发送 |
location规则
分类 | 格式 | 说明 |
---|---|---|
精确匹配 | location = /uri | 优先级最高,匹配命中即退出,需完全匹配才算命中 |
一般匹配 | location /uri | 取最长的匹配,暂存结果并搜索正则匹配 |
location ^~ /uri | 取最长的匹配,之后不再搜索正则匹配 | |
location / | 通用匹配,即一定会被命中 | |
正则匹配 | location ~ uri | 用于正则uri前,表示uri里面包含正则,并且区分大小写 |
location ~* uri | 用于正则uri前,表示uri里面包含正则,不区分大小写 |
- 最先精确匹配,如果精确匹配到了就停止搜索。
- 精确匹配失败,进行一般匹配。一般匹配如有多个命中,按匹配的长度决定最终匹配,与
location
配置顺序无关。 - 如一般匹配带有前缀
^~
,则不再进行正则匹配,直接返回结果。 - 如一般匹配没有前缀
^~
,则继续进行正则匹配,如正则匹配未命中则返回暂存结果,否则返回正则匹配结果。 - 正则匹配与
location
配置顺序有关(从上往下),返回第一个命中的结果。
常用内置变量
变量名 | 说明 |
---|---|
$arg_name | 指 URL 请求中的参数,name 是参数的名字 |
$args | 代表 URL 中所有请求的参数 |
$binary_remote_addr | 客户端地址以二进制数据的形式出现,通常会和限速模块一起使用 |
$body_bytes_sent | 发送给客户端的字节数,不包含响应头 |
$bytes_sent | 发送给客户端的总字节数 |
$document_uri | 设置$uri 的别名 |
$hostname | 运行 Nginx 的服务器名 |
$http_referer | 表示请求是从哪个页面链接过来的 |
$http_user_agent | 客户端浏览器的相关信息 |
$remote_addr | 客户端 IP 地址 |
$remote_port | 客户端端口号 |
$remote_user | 客户端用户名,通常在 Auth Basic 模块中使用 |
$request_filename | 请求的文件路径,基于 root alias 指令和 URI 请求生成 |
$request_time | 请求被 Nginx 接收后,一直到响应数据返回给客户端所用的时间 |
$request_uri | 请求的 URI,带参数 |
$request | 记录请求的 URL 和 HTTP |
$request_length | 请求的长度,包括请求行、请求头和请求正文 |
$server_name | 虚拟主机的 server_name 的值,通常是域名 |
$server_port | 服务器端口号 |
$server_addr | 服务器的 IP 地址 |
$request_method | 请求的方式,如 POST 或 GET |
$scheme | 请求协议,如 HTTP 或 HTTPS |
$sent_http_name | 任意响应头,name 为响应头的名字,注意 name 要小写 |
$realip_remote_addr | 保留原来的客户地址,在 real_ip 模块中使用 |
$server_protocol | 请求采用的协议名称和版本号,常为 HTTP/1.0 或 HTTP/1.1 |
$uri | 当前请求的 URI,在请求过程中 URI 可能会被改变,例如在内部重定向或使用索引文件时 |
$nginx_version | Nginx 的版本号 |
$pid | worker 进程的 PID |
$pipe | 如果请求是 HTTP 流水线(pipelined)发送的,pipe 值为”p”,否则为”.” |
$connection_requests | 当前通过一个连接获得的请求数量 |
$cookie_name | name 即 Cookie 的名字,可得到 Cookie 的信息 |
$status | HTTP 请求状态 |
$msec | 日志写入时间。单位为秒,精度是毫秒 |
$time_local | 在通用日志格式下的本地时间 |
$upstream_addr | 请求反向代理到后端服务器的 IP 地址 |
$upstream_port | 请求反向代理到后端服务器的端口号请求反向代理到后端服务器的端口号 |
$upstream_response_time | 请求在后端服务器消耗的时间 |
$upstream_status | 请求在后端服务器的 HTTP 响应状态 |
$geoip_city | 城市名称,在 geoip 模块中使用 |
根据参数名跳转不同URL
123456 | location / { #请求默认路径是 http://a,如果 URL 中的参数是 at=5,则路径变为 http://b if ($arg_at= '5') { proxy_pass http://b; } proxy_pass http://a; } |
---|
http跳转到https
123 | if ($scheme = 'http') { rewrite ^/(.*)$ https://$host/$1 redirect; } |
---|
应用
限制ip访问
使用模块ngx_http_access_module
123456 | location / { deny 192.168.1.1; # 禁止 192.168.1.1 访问 allow 192.168.1.0/24; # 允许 192.168.1.0/24 访问 allow 17.1.1.2; # 允许 17.1.1.2 访问 deny all; # 除 allow 的 IP 地址外,其他的 IP 地址都禁止访问} |
---|
auth身份验证
使用模块ngx_http_auth_basic_module
12345678 | server { listen 80; server_name localhost; location / { auth_basic "Nginx Basic"; # 浏览器访问是时的弹框显示内容 auth_basic_user_file conf.d/passwd; # 存放密码的文件地址 } } |
---|
密码文件生成语法:
1 | printf "yourusername:$(openssl passwd -crypt yourpassword)n" >> /etc/nginx/conf.d/passwd |
---|
访问控制
使用模块ngx_http_core_module
1234567 | location / { satisfy any; allow 192.168.1.0/32; deny all; auth_basic "closed site"; auth_basic_user_file conf/htpasswd;} |
---|
- satisfy all:当这个请求能够被
access
、auth_basic
、auth_request
这三个模块都放行,该才能够继续往下走。若被任意一个模块拒绝,就会返回400或者500系列的状态码。 - satisfy any:只要这个请求被任意一个
access
阶段的模块放行,就可以继续被执行。
Syntax | Default | Content | |
---|---|---|---|
auth_basic string | off; | auth_basic off; | http, server, location |
satisfy all | any; | satisfy all; | http, server, location |
后端获取客户端真实ip
123456789101112131415 | location / { #保留代理之前的host 包含客户端真实的域名和端口号 proxy_set_header Host $host; #保留代理之前的真实客户端ip proxy_set_header X-Real-IP $remote_addr; #这个Header和X-Real-IP类似,但它在多级代理时会包含真实客户端及中间每个代理服务器的IP proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #表示客户端真实的协议(http还是https) proxy_set_header X-Forwarded-Proto $scheme; #指定修改被代理服务器返回的响应头中的location头域跟refresh头域数值 #如果使用"default"参数,将根据location和proxy_pass参数的设置来决定。 #proxy_redirect [ default|off|redirect replacement ]; proxy_redirect off; proxy_pass http://IP:PORT;} |
---|
反向代理
Nginx 使用ngx_http_proxy_module
来完成对后端服务的代理。
12345678910111213141516171819 | # http://nginx:80/eureka/js/1.js 等于 http://10.129.20.36:8761//js/1.jslocation /eureka { proxy_pass http://10.129.20.36:8761/;} # http://nginx:80/eureka/js/1.js 等于 http://10.129.20.36:8761/eureka/js/1.jslocation /eureka { proxy_pass http://10.129.20.36:8761;}# http://nginx:80/eureka/js/1.js 等于 http://10.129.20.36:8761/eureka/js/1.jslocation /eureka/ { proxy_pass http://10.129.20.36:8761;}# http://nginx:80/eureka/js/1.js 等于 http://10.129.20.36:8761/js/1.jslocation /eureka/ { proxy_pass http://10.129.20.36:8761/;} |
---|
控制请求头和请求体:
- proxy_hide_header:禁止某个请求头被转发到后端服务器;
- proxy_pass_header:允许已被禁止转发的请求头继续转发;
- proxy_set_header:添加获修改请求头信息;
- proxy_set_body:对请求体进行覆盖,如
proxy_set_body 'b=123xxx'
;
控制请求和后端服务器的交互时间:
- proxy_connect_timeout:设置请求和后端服务器建立连接的超时时间;
- proxy_read_timeout:等待real server响应数据的超时时间,超时只在两次连续的读操作之间设置, 而不是用于传输整个响应。如果real server在此时间内没有传输任何内容,则连接将关闭;
- proxy_send_timeout:向real server发送请求的超时时间,超时只在两次连续写入操作之间设置, 而不是用于传输整个请求,如果real server在此时间内没有收到任何内容,则连接将关闭;
Syntax | Default | Content |
---|---|---|
proxy_connect_timeout; | proxy_connect_timeout 60s; | http, server, location |
proxy_read_timeout time; | proxy_read_timeout 60s; | http, server, location |
proxy_send_timeout time; | proxy_send_timeout 60s; | http, server, location |
代理多台服务器
如果需要指向多台服务器就要用到ngx_http_upstream_module模块,它为反向代理提供了负载均衡及故障转移等重要功能。
123456789101112131415 | # 定义一个 HTTP 服务组upstream test_servers { # 用 server 定义 HTTP 地址 server 127.0.0.1:81 max_fails=5 fail_timeout=10s weight=10; server 127.0.0.1:82 max_fails=5 fail_timeout=10s weight=5; server test.123.com backup; server 127.0.0.1:82 down; } server { listen 80; location / { # 通过代理将请求发送给 upstream 命名的 HTTP 服务 proxy_pass http://test_servers; } } |
---|
参数说明:
- weight:设置请求分发到后端服务器的权重,即每台后端服务器能够响应的请求数量的比例;
- max_fails:请求最大失败次数,在指定时间内请求失败的最大次数,默认是 1。如果设置为 0,代表禁用这个设置;
- fail_timeout:在指定时间内请求失败的次数,超过这个次数则认为服务器不可用;
- down:标记服务不可用;
- backup:当 upstream 中所有的后端服务器都被设置为不可用时(如全都超过了请求最大失败次数),upstream 会对backup 的服务器进行分流
故障转移
- proxy_next_upstream:定义转发条件,当请求返回Nginx时,如果HTTP状态满足
proxy_next_upstream
设置的条件,就会触发 Nginx 将请求重新转发到下一台后端服务器,并累加出现此状态的服务器的失败次数(当超过max_fails
和fail_timeout
的值时就会设置此服务器为不可用)。如果设置为off
,则表示关闭此功能。 - proxy_next_upstream_tries:定义尝试请求的次数,达到次数上限后就停止转发,并将请求内容返回客户端。若设置为 0,则表示无次数限制。
- proxy_next_upstream_timeout:限制尝试请求的超时时间,如果第一次请求失败,下一次请求就会被此参数值控制。若设置为 0,则表示无超时时间。
Syntax | Default | Content | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | http_429 | non_idempotent | off…; | proxy_next_upstream error timeout; | http, server, location |
proxy_next_upstream_tries number; | proxy_next_upstream_tries 0; | http, server, location | |||||||||||
proxy_next_upstream_timeout time; | proxy_next_upstream_timeout 0; | http, server, location |
负载均衡
相同的 URL(包含参数)会进入相同的后端缓存系统:
12345 | upstream test_servers { hash $request_uri; server 127.0.0.1:81 max_fails=5 fail_timeout=10s weight=10; server 127.0.0.1:82 max_fails=5 fail_timeout=10s weight=5; } |
---|
- hash:按照指定的 key 将请求分布到后端服务器上,key 可以是变量、文本或它们的组合,key 相同的请求会被代理到同一台后端服务器上;
- ip_hash:根据 IP 地址将请求分流到后端服务器上,同一个 IP 地址的请求会被代理到同一台后端服务器上;
- least_conn:当将请求分流到后端服务器时,请求量最小的服务器会优先获得分流;
- sticky:根据 Cookie 将请求分布到后端服务器上,同一个 Cookie 的请求只会进入同一台服务器。如果请求被分布到某台服务器上,但是在请求时这台服务器已经无法提供服务,那么会重新选择一台服务器进行“捆绑”,并且下次会直接进入重新“捆绑”的服务器;
Syntax | Default | Content |
---|---|---|
hash key | - | upstream |
ip_hash; | - | upstream |
least_conn; | - | upstream |
sticky cookie name … | - | upstream |
长连接
在Nginx 中,使用 upstream 进行后端访问默认用的是短连接,但这会增加网络资源的消耗。可以通过配置长连接,来减少因建立连接产生的开销、提升性能:
123456789101112131415161718 | upstream test_servers { server 127.0.0.1:81 max_fails=5 fail_timeout=10s weight=10; server 127.0.0.1:82 max_fails=5 fail_timeout=10s weight=5; keepalive 100; keepalive_requests 1000; keepalive_timeout 1h; } server { listen 80; proxy_set_header Host $Host; proxy_set_header x-forwarded-for $remote_addr; proxy_set_header X-Real-IP $remote_addr; proxy_http_version 1.1; # 设置 HTTP 请求协议,要确保是 HTTP 1.1 的长连接协议 proxy_set_header Connection ""; # 清空 Connection 请求头,避免客户端传递短连接的请求头信息 location / { proxy_pass http://test_servers; } } |
---|
- keepalive:设置 worker 进程和后端服务器之间保持空闲连接的最大值,如果空闲连接数大于这个值,将会关闭使用最少的连接;
- keepalive_requests:设置每个连接的最大请求次数,超过这个次数就会关闭该连接建立新的连接;
- keepalive_timeout:设置 keep-alive 客户端连接在服务器端保持开启的超时时间;
Syntax | Default | Content |
---|---|---|
keepalive connections; | - | upstream |
keepalive_requests number; | keepalive_requests 1000; | upstream |
keepalive_timeout time; | keepalive_timeout 1h; | upstream |
rewrite
使用模块ngx_http_rewrite_module
跳转规则
配置在server
块
请求/1.html
,最终返回3.html
123456 | server{ listen 80; rewrite /1.html /2.html ; rewrite /2.html /3.html ; } |
---|
请求/1.html
,最终返回2.html
123456 | server{ listen 80; rewrite /1.html /2.html break; rewrite /2.html /3.html ; } |
---|
请求/1.html
,最终返回403状态码(绕过后续rewrite
或return
,但会继续匹配location
)
123456789 | server{ listen 80; rewrite /1.html /2.html break; rewrite /2.html /3.html ; location /2.html { return 403; }} |
---|
此时,break
和last
实现效果一致。
配置在location
块
请求/1.html
,最终返回b.html
12345678910111213141516 | server{ listen 80; location / { rewrite /1.html /2.html; rewrite /2.html /3.html; } location /2.html { rewrite /2.html /a.html; } location /3.html { rewrite /3.html /b.html; }} |
---|
请求/1.html
,最终返回2.html
(本location
内的rewrite
以及其他location
都不再执行)
12345678910111213141516 | server{ listen 80; location / { rewrite /1.html /2.html break; rewrite /2.html /3.html; } location /2.html { rewrite /2.html /a.html; } location /3.html { rewrite /3.html /b.html; }} |
---|
请求/1.html
,最终返回a.html
(本location
内的rewrite
和return
不再执行,但会继续匹配location
,这是break
和last
的区别)
12345678910111213141516 | server{ listen 80; location / { rewrite /1.html /2.html last; rewrite /2.html /3.html; } location /2.html { rewrite /2.html /a.html; } location /3.html { rewrite /3.html /b.html; }} |
---|
总结:
rewrite
配置在server块中,会一直向下执行本区块内的rewrite
,直到结束或碰到break
或last
(break
和last
在server块中实现效果一致),但仍然会匹配location。rewrite
配置在location块中,碰到break
或last
都会结束当前块,但last
会继续匹配location,break
则不会。
应用
内部重定向:
12345 | # 匹配以/a/开头的请求,并将/a/后面的 URI 全部捕获,# 然后重定向成 /b/$1 ,其中$1 就是前面捕获到的 URI。# 匹配成功后将其修改成/b 的 URI,并停止 rewrite 阶段,执行下一个阶段,即 proxy_passrewrite ^/a/(.*) /b/$1 break;proxy_pass http://test_servers; |
---|
域名跳转:
123456 | # permanent 参数表示永久重定向,将所有的请求全部跳转到指定域名上# 通过(.*)将 URL 保留下来,跳转过程中参数不会丢失。HTTP 状态码为 301 rewrite ^/(.*)$ http://www.zhe800.com/$1 permanent; # redirect 参数表示临时重定向,将所有的请求全部跳转到指定域名上# 通过(.*)将 URL 保留下来,跳转过程中参数不会丢失。HTTP 状态码 302 rewrite ^/(.*)$ http://www.zhe800.com/$1 redirect; |
---|
返回任意http状态码:
12 | return 307 http://www.test.com/$request_uri; # 临时重定向return 308 http://www.test.com/$request_uri; # 永久重定向 |
---|
307和308为HTTP1.1支持的状态码,用于告知客户端跳转过程中请求的方法不变,并保留请求体,用于跳转POST请求。
Syntax | Default | Content |
---|---|---|
return code [text]return code URL;return URL; | - | server,location,if |
图片防盗链
为了阻止盗链的情况出现,可以使用ngx_http_referer_module模块。此模块是 Nginx 的内置模块,不需要重新编译。
123456 | location ~* .(gif|jpg|png|webp)$ { valid_referers none blocked server_names *.testnginx.com ~.baidu. .google.; if ($invalid_referer) { return 403; } } |
---|
如果referer不是示例中的这些域名,则会返回403错误。
日志
使用模块ngx_http_log_module
自定义日志格式:
12345 | log_format json_log escape=json '{"ip":"$remote_addr","timestamp": "$time_iso8601",' '"host":"$http_host","request":"$request",' '"cookie":"$http_cookie","req_time":"$request_time", "uri":"$uri","referer":"$http_referer" }'; |
---|
使用escape=json
则日志内容不会被转义,中文字符可以直接在日志里面显示。
Syntax | Default | Content | ||
---|---|---|---|---|
log_format name [escape=default | json | none] string …; | log_format combined “…” | http |
日志存储方式:
12345678910111213 | # json_log 定义了日志格式access_log /data1/access.log json_log; # 日志压缩记录,每缓存 5MB 的数据就进行日志压缩access_log /data1/access_1.log combined gzip flush=5m; # 根据条件进行记录,当 if 等于 0 或为空时日志不会被记录# 下面代码的意思是当 HTTP 状态码以 4 开头时,日志不会被记录map $status $loggable { ~^[4] 0; default 1; } access_log /path/to/access.log combined if=$loggable; |
---|
指令access_log
只记录访问日志,关于错误信息的日志记录在error_log
上。
Syntax | Default | Content |
---|---|---|
access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];access_log off; | access_log logs/access.log combined; | http, server, location, if in location, limit_except |