Nginx基础配置实战

1. 概述

1.1 Nginx配置的重要性

Nginx配置是Nginx服务器的核心,合理的配置可以充分发挥Nginx的高性能特性,实现安全、稳定、高效的Web服务。掌握Nginx基础配置是运维人员的基本技能。

配置的价值

  • 性能优化:合理配置提升系统性能
  • 安全防护:通过配置实现访问控制和限制
  • 功能实现:实现虚拟主机、负载均衡等功能
  • 运维管理:通过配置实现监控和日志管理

1.2 本文内容结构

本文将从以下几个方面详细介绍Nginx基础配置:

  1. Nginx配置文件:配置文件结构和语法
  2. 日志配置:访问日志和错误日志配置
  3. 状态监控:Nginx状态监控配置
  4. 下载站点:目录浏览功能配置
  5. 访问限制:连接限制和请求限制
  6. 访问控制:基于IP和用户认证
  7. 虚拟主机:基于域名和端口的虚拟主机
  8. URL重写:域名跳转和URL重定向
  9. 慢请求日志:慢请求记录配置

2. Nginx配置文件

2.1 配置文件结构

2.1.1 配置文件位置

主配置文件

  • /etc/nginx/nginx.conf(YUM安装)
  • /application/nginx/conf/nginx.conf(源码编译)

配置文件特点

  • 纯文本类型文件
  • 以区块的形式组织
  • 每个区块以一对大括号{}表示开始与结束

2.1.2 配置文件层次结构

层次关系

1
2
3
4
5
6
7
8
9
10
11
Main(全局配置)

├── Events(事件模块)
└── HTTP(HTTP模块)

├── Server(虚拟主机1)
│ └── Location(路径配置1)
│ └── Location(路径配置2)
├── Server(虚拟主机2)
│ └── Location(路径配置)
└── Server(虚拟主机N)

层次说明

  1. Main层:位于nginx.conf配置文件的最高层
  2. Events层:Main层下的事件模块配置
  3. HTTP层:Main层下的HTTP模块配置
  4. Server层:HTTP层下可以有多个Server层,用于对不同的网站做不同的配置
  5. Location层:Server层下可以有多个Location,用于对不同的路径进行不同模块的配置

2.2 Main层配置

2.2.1 Main层配置语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 设置Nginx服务的系统使用用户
user nginx;

# 工作进程数,建议设置为CPU核心数
worker_processes auto;
# 或
worker_processes 4;

# 错误日志路径和级别
error_log /var/log/nginx/error.log warn;
# 日志级别:debug, info, notice, warn, error, crit, alert, emerg

# Nginx服务启动时的PID文件路径
pid /var/run/nginx.pid;

配置说明

指令 说明 示例值
user 运行Nginx的用户 nginx
worker_processes 工作进程数 auto(自动)或数字
error_log 错误日志路径和级别 /var/log/nginx/error.log warn
pid PID文件路径 /var/run/nginx.pid

2.3 Events层配置

2.3.1 Events配置语法

1
2
3
4
5
6
7
8
9
10
events {
# 每个worker进程支持的最大连接数
worker_connections 1024;

# 内核模型,select, poll, epoll(Linux推荐epoll)
use epoll;

# 允许一个worker同时接受多个新连接
multi_accept on;
}

配置说明

指令 说明 示例值
worker_connections 每个worker的最大连接数 102465535
use 事件模型 epoll(Linux)、kqueue(FreeBSD)
multi_accept 是否允许一个worker同时接受多个连接 onoff

最大连接数计算

  • 最大连接数 = worker_processes × worker_connections
  • 示例:4个worker,每个1024连接 = 4096个并发连接

2.4 HTTP层配置

2.4.1 HTTP基础配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
http {
# 包含MIME类型文件
include /etc/nginx/mime.types;

# 默认MIME类型
default_type application/octet-stream;

# 日志格式定义
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 /var/log/nginx/access.log main;

# 启用sendfile
sendfile on;
tcp_nopush on;
tcp_nodelay on;

# 保持连接超时时间
keepalive_timeout 65;

# Gzip压缩配置
gzip on;
gzip_vary on;
gzip_min_length 1000;
gzip_types text/plain text/css application/json application/javascript;
}

2.5 Server层配置

2.5.1 Server基础配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
http {
# 虚拟主机配置
server {
# 监听端口
listen 80;

# 服务器名称(域名)
server_name localhost;

# 网站根目录
root /usr/share/nginx/html;

# 默认首页文件
index index.html index.htm;

# 控制网站访问路径
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}

# 错误页面配置
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}

配置说明

指令 说明 示例值
listen 监听端口 804438000
server_name 服务器名称(域名) localhostexample.com
root 网站根目录 /usr/share/nginx/html
index 默认首页文件 index.html index.htm
error_page 错误页面配置 500 502 503 504 /50x.html

2.6 Location层配置

2.6.1 Location匹配规则

Location语法

1
2
3
location [=|~|~*|^~] /uri/ {
# 配置内容
}

匹配规则

匹配符 说明 优先级
= 精确匹配 最高
^~ 前缀匹配,如果匹配则不再检查正则
~ 区分大小写的正则匹配
~* 不区分大小写的正则匹配
无符号 前缀匹配

匹配优先级

  1. = 精确匹配
  2. ^~ 前缀匹配
  3. ~~* 正则匹配(按配置顺序)
  4. 普通前缀匹配

配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
location = / {
# 精确匹配根路径
}

location ^~ /images/ {
# 前缀匹配/images/,不检查正则
}

location ~ \.(gif|jpg|jpeg)$ {
# 正则匹配图片文件
}

location / {
# 普通前缀匹配
}

3. Nginx日志配置

3.1 HTTP请求和响应

3.1.1 理解HTTP请求

查看HTTP请求

1
2
# 使用curl查看HTTP请求和响应
curl -v http://www.baidu.com

HTTP请求组成

  • 请求行:方法、URI、协议版本
  • 请求头:Host、User-Agent、Referer等
  • 请求体:POST数据等

HTTP响应组成

  • 状态行:协议版本、状态码、状态描述
  • 响应头:Content-Type、Content-Length等
  • 响应体:实际内容

3.2 日志格式配置

3.2.1 log_format语法

1
2
3
Syntax: log_format name [escape=default|json] string …;
Default: log_format combined "...";
Context: http

3.2.2 Nginx默认日志格式

1
2
3
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

3.2.3 自定义日志格式

1
2
3
4
5
6
7
8
9
10
11
12
13
# JSON格式日志
log_format json escape=json '{"time":"$time_iso8601",'
'"remote_addr":"$remote_addr",'
'"request":"$request",'
'"status":"$status",'
'"body_bytes_sent":"$body_bytes_sent"}';

# 详细日志格式
log_format detailed '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'"$request_time" "$upstream_response_time" '
'"$upstream_addr" "$upstream_status"';

3.3 Nginx日志变量

3.3.1 常用日志变量

变量 说明 示例值
$remote_addr 客户端IP地址 192.168.1.100
$remote_user HTTP客户端请求Nginx认证用户名 admin
$time_local Nginx的时间(通用日志格式) 26/Mar/2019:10:15:30 +0800
$time_iso8601 ISO8601格式时间 2019-03-26T10:15:30+08:00
$request Request请求行(方法、URI、协议版本) GET /index.html HTTP/1.1
$status 响应状态码 200404500
$body_bytes_sent 从服务端响应给客户端的body信息大小 1234
$bytes_sent 发送给客户端的字节数(包括响应头) 1500
$http_referer HTTP上一级页面,用于防盗链、用户行为分析 http://example.com
$http_user_agent HTTP头部信息,客户端访问设备 Mozilla/5.0...
$http_x_forwarded_for HTTP请求携带的X-Forwarded-For信息 192.168.1.100
$request_time 请求处理时间(秒) 0.123
$upstream_response_time 上游服务器响应时间 0.100
$upstream_addr 上游服务器地址 192.168.1.100:8080
$upstream_status 上游服务器状态码 200

3.3.2 日志格式应用

1
2
3
4
5
6
7
8
9
10
11
12
http {
# 定义日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

# 在server中使用
server {
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
}
}

3.4 日志文件管理

3.4.1 日志轮转配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 使用logrotate配置日志轮转
cat > /etc/logrotate.d/nginx << 'EOF'
/var/log/nginx/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 0640 nginx nginx
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}
EOF

4. Nginx状态监控

4.1 stub_status模块

4.1.1 模块说明

stub_status模块

  • 编译参数:--with-http_stub_status_module
  • 功能:记录Nginx客户端基本访问状态信息
  • 用途:监控Nginx运行状态

4.1.2 配置语法

1
2
3
Syntax: stub_status;
Default: —
Context: server, location

4.1.3 配置示例

1
2
3
4
5
6
7
location /mystatus {
stub_status;
access_log off; # 关闭访问日志,避免日志污染
allow 127.0.0.1; # 只允许本地访问
allow 192.168.1.0/24; # 允许内网访问
deny all; # 拒绝其他访问
}

4.2 状态信息说明

4.2.1 访问状态页面

1
2
# 访问状态页面
curl http://localhost/mystatus

输出示例

1
2
3
4
Active connections: 2
server accepts handled requests
16 16 19
Reading: 0 Writing: 1 Waiting: 1

4.2.2 状态信息解读

Active connections

  • Active connections: 2:Nginx当前活跃连接数

server accepts handled requests

  • server:Nginx处理接收握手总次数
  • accepts:Nginx处理接收总连接数
  • handled requests:总共处理的请求数
  • 请求丢失数 = accepts - handled(正常情况下应该为0)

连接状态

  • Reading:Nginx读取客户端请求数据
  • Writing:Nginx向客户端写数据
  • Waiting:Nginx开启keep-alive长连接情况下,既没有读也没有写,建立连接情况

4.3 状态监控脚本

4.3.1 监控脚本示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cat > /usr/local/bin/nginx_status.sh << 'EOF'
#!/bin/bash

STATUS_URL="http://localhost/mystatus"
STATUS=$(curl -s $STATUS_URL)

# 提取活跃连接数
ACTIVE=$(echo "$STATUS" | grep "Active connections" | awk '{print $3}')

# 提取请求数
REQUESTS=$(echo "$STATUS" | grep "requests" | awk '{print $3}')

echo "Active Connections: $ACTIVE"
echo "Total Requests: $REQUESTS"
EOF

chmod +x /usr/local/bin/nginx_status.sh

5. Nginx下载站点

5.1 目录浏览功能

5.1.1 autoindex指令

默认情况
Nginx默认是不允许列出整个目录浏览下载。

配置语法

1
2
3
Syntax: autoindex on | off;
Default: autoindex off;
Context: http, server, location

5.1.2 autoindex常用参数

autoindex_exact_size

1
2
3
Syntax: autoindex_exact_size on | off;
Default: autoindex_exact_size on;
Context: http, server, location
  • on:显示出文件的确切大小,单位是bytes
  • off:显示出文件的大概大小,单位是kB或者MB或者GB

autoindex_localtime

1
2
3
Syntax: autoindex_localtime on | off;
Default: autoindex_localtime off;
Context: http, server, location
  • off:显示的文件时间为GMT时间
  • on:显示的文件时间为文件的服务器时间

charset

1
2
3
Syntax: charset charset | off;
Default: charset off;
Context: http, server, location, if in location
  • 默认中文目录乱码,添加charset utf-8,gbk;解决乱码

5.1.3 配置目录浏览

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
location /download {
root /usr/share/nginx/html;

# 开启目录浏览
autoindex on;

# 显示文件大小(KB/MB/GB)
autoindex_exact_size off;

# 显示服务器时间
autoindex_localtime on;

# 解决中文乱码
charset utf-8,gbk;
}

安全建议

  • 生产环境不建议开启目录浏览
  • 如果必须开启,限制访问IP
  • 隐藏敏感文件

6. Nginx访问限制

6.1 HTTP连接与请求

6.1.1 连接与请求的关系

HTTP协议基础

  • HTTP是建立在TCP之上
  • 完成HTTP请求需要先建立TCP三次握手(称为TCP连接)
  • 在连接的基础上再进行HTTP请求

关系说明

  • 一次TCP连接可以产生多次HTTP请求
  • HTTP/1.0:一个连接一个请求
  • HTTP/1.1:一个连接多个请求(keep-alive)

示意图

1
2
3
4
5
6
7
8
9
TCP连接(三次握手)

HTTP请求1

HTTP请求2

HTTP请求N

TCP连接关闭

6.2 连接频率限制

6.2.1 limit_conn_module模块

模块功能
限制同一时刻的并发连接数

配置语法

1
2
3
4
5
6
7
8
9
# 定义连接限制区域
Syntax: limit_conn_zone key zone=name:size;
Default: —
Context: http

# 应用连接限制
Syntax: limit_conn zone number;
Default: —
Context: http, server, location

6.2.2 配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
http {
# 定义连接限制区域
# $binary_remote_addr:客户端IP(二进制格式,节省内存)
# zone=conn_zone:10m:区域名称和大小(10MB可以存储约16万个IP)
limit_conn_zone $binary_remote_addr zone=conn_zone:10m;

server {
location / {
# 同一时刻只允许一个客户端IP连接
limit_conn conn_zone 1;

root /usr/share/nginx/html;
index index.html;
}
}
}

6.2.3 压力测试

1
2
3
4
5
# 安装压力测试工具
yum install -y httpd-tools

# 压力测试(50个请求,20个并发)
ab -n 50 -c 20 http://127.0.0.1/index.html

测试结果分析

  • 连接限制生效时,部分请求会返回503错误
  • 查看错误日志:tail -f /var/log/nginx/error.log

6.3 请求频率限制

6.3.1 limit_req_module模块

模块功能
限制请求的速率

配置语法

1
2
3
4
5
6
7
8
9
# 定义请求限制区域
Syntax: limit_req_zone key zone=name:size rate=rate;
Default: —
Context: http

# 应用请求限制
Syntax: limit_req zone name [burst=number] [nodelay];
Default: —
Context: http, server, location

6.3.2 配置示例

基础配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
http {
# 定义请求限制区域
# rate=1r/s:限制速率为每秒1个请求
limit_req_zone $binary_remote_addr zone=req_zone:10m rate=1r/s;

server {
location / {
# 1r/s只接收一个请求,其余请求拒绝处理并返回错误码
limit_req zone=req_zone;

root /usr/share/nginx/html;
index index.html;
}
}
}

带burst配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
http {
limit_req_zone $binary_remote_addr zone=req_zone:10m rate=1r/s;

server {
location / {
# burst=3:允许突发3个请求
# nodelay:不延迟处理突发请求
limit_req zone=req_zone burst=3 nodelay;

root /usr/share/nginx/html;
index index.html;
}
}
}

配置说明

  • rate=1r/s:限制速率为每秒1个请求
  • burst=3:允许突发3个请求,超过的请求返回503
  • nodelay:不延迟处理突发请求,立即处理

6.3.3 压力测试

1
2
3
4
5
# 压力测试
ab -n 50 -c 20 http://127.0.0.1/index.html

# 查看访问日志
tail -f /var/log/nginx/access.log

6.4 连接限制 vs 请求限制

6.4.1 区别说明

连接限制

  • 限制同一时刻的并发连接数
  • 多个请求可以建立在一次TCP连接之上
  • 精度较低

请求限制

  • 限制请求的速率
  • 对请求的精度限制更有效
  • 推荐使用请求限制

为什么请求限制更有效

  • 同一时刻只允许一个连接请求进入
  • 但是同一时刻多个请求可以通过一个连接进入
  • 所以请求限制才是比较优的解决方案

7. Nginx访问控制

7.1 基于IP的访问控制

7.1.1 http_access_module模块

模块功能
基于客户端IP地址进行访问控制

配置语法

1
2
3
4
5
6
7
8
9
# 允许访问
Syntax: allow address | CIDR | unix: | all;
Default: —
Context: http, server, location, limit_except

# 拒绝访问
Syntax: deny address | CIDR | unix: | all;
Default: —
Context: http, server, location, limit_except

7.1.2 配置示例

拒绝特定IP,其他全部允许

1
2
3
4
5
6
7
8
9
10
location ~ ^/admin {
root /usr/share/nginx/html;
index index.html;

# 拒绝特定IP
deny 192.168.56.1;

# 其他全部允许
allow all;
}

只允许特定网段,其他全部拒绝

1
2
3
4
5
6
7
8
9
10
location / {
root /usr/share/nginx/html;
index index.html;

# 只允许特定网段
allow 192.168.56.0/24;

# 其他全部拒绝
deny all;
}

配置说明

  • 配置按顺序执行,匹配到规则后停止
  • 建议先配置允许规则,最后配置拒绝规则

7.1.3 http_access_module局限性

问题
当Nginx作为反向代理时,$remote_addr获取的是代理服务器的IP,而不是真实客户端IP。

示意图

1
2
3
4
5
客户端(192.168.1.100)

代理服务器(10.0.0.1) → $remote_addr = 10.0.0.1

Nginx服务器

解决方式

  1. 采用HTTP头信息控制访问
1
2
3
4
5
6
7
# 在代理服务器设置X-Forwarded-For
proxy_set_header X-Forwarded-For $remote_addr;

# 在Nginx使用X-Forwarded-For
set_real_ip_from 10.0.0.0/8;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
  1. 结合geo模块
1
2
3
4
5
6
7
8
9
geo $remote_addr $allowed {
default 0;
192.168.1.0/24 1;
10.0.0.0/8 1;
}

if ($allowed = 0) {
return 403;
}
  1. 通过HTTP自定义变量传递
1
2
3
4
5
6
7
# 在代理层传递真实IP
proxy_set_header X-Real-IP $remote_addr;

# 在Nginx使用真实IP
if ($http_x_real_ip != "192.168.1.100") {
return 403;
}

7.2 基于用户登录认证

7.2.1 http_auth_basic_module模块

模块功能
基于HTTP基本认证进行访问控制

配置语法

1
2
3
4
5
6
7
8
9
# 启用认证
Syntax: auth_basic string | off;
Default: auth_basic off;
Context: http, server, location, limit_except

# 用户密码文件
Syntax: auth_basic_user_file file;
Default: —
Context: http, server, location, limit_except

7.2.2 创建用户密码文件

1
2
3
4
5
6
7
8
# 安装htpasswd工具
yum install -y httpd-tools

# 创建用户密码文件(-c创建新文件)
htpasswd -c /etc/nginx/auth_conf xuliangwei

# 添加更多用户(不使用-c参数)
htpasswd /etc/nginx/auth_conf user2

htpasswd参数

  • -c:创建新文件
  • -b:从命令行输入密码
  • -D:删除用户

7.2.3 配置示例

1
2
3
4
5
6
7
8
9
10
location /admin {
root /usr/share/nginx/html;
index index.html;

# 启用认证
auth_basic "Auth access Blog Input your Passwd!";

# 用户密码文件
auth_basic_user_file /etc/nginx/auth_conf;
}

配置说明

  • auth_basic:认证提示信息
  • auth_basic_user_file:用户密码文件路径

7.2.4 用户认证局限性

局限性

  1. 用户信息依赖文件方式:管理不方便
  2. 用户管理文件过多,无法联动:无法统一管理
  3. 操作管理机械,效率低下:需要手动编辑文件

解决办法

  1. Nginx结合LUA实现高效验证
1
2
3
4
5
6
# 使用OpenResty的Lua模块
location /admin {
access_by_lua_block {
-- Lua认证逻辑
}
}
  1. Nginx结合LDAP利用nginx-auth-ldap模块
1
2
3
# 使用LDAP认证模块
auth_ldap "Forbidden";
auth_ldap_servers ldapserver;

8. Nginx虚拟主机

8.1 虚拟主机概述

8.1.1 什么是虚拟主机

虚拟主机
在Web服务器里是一个独立的网站站点,这个站点对应独立的域名(也可能是IP或端口),具有独立的程序及资源目录,可以独立地对外提供服务供用户访问。

虚拟主机类型

  1. 基于域名:不同域名访问不同网站
  2. 基于端口:不同端口访问不同网站
  3. 基于IP:不同IP访问不同网站(不常用)

8.2 基于域名的虚拟主机

8.2.1 配置步骤

步骤1:创建Web站点目录

1
2
3
4
5
6
# 创建网站目录
mkdir -p /soft/code/{www,bbs}

# 创建测试页面
echo "www site" > /soft/code/www/index.html
echo "bbs site" > /soft/code/bbs/index.html

步骤2:配置虚拟主机

1
2
# 创建虚拟主机配置文件
vim /etc/nginx/conf.d/www.conf

www.conf配置

1
2
3
4
5
6
7
8
9
10
11
server {
listen 80;
server_name www.xuliangwei.com;

root /soft/code/www;
index index.html index.htm;

location / {
try_files $uri $uri/ =404;
}
}

bbs.conf配置

1
2
3
4
5
6
7
8
9
10
11
server {
listen 80;
server_name bbs.xuliangwei.com;

root /soft/code/bbs;
index index.html index.htm;

location / {
try_files $uri $uri/ =404;
}
}

步骤3:测试配置

1
2
3
4
5
6
7
8
9
# 测试配置
nginx -t

# 重新加载配置
nginx -s reload

# 测试访问(需要配置hosts或DNS)
curl -H "Host: www.xuliangwei.com" http://127.0.0.1
curl -H "Host: bbs.xuliangwei.com" http://127.0.0.1

8.3 基于端口的虚拟主机

8.3.1 配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 端口8001的虚拟主机
server {
listen 8001;
server_name localhost;

root /soft/code/www;
index index.html;
}

# 端口8002的虚拟主机
server {
listen 8002;
server_name localhost;

root /soft/code/bbs;
index index.html;
}

注意事项

  • 端口不能和系统端口冲突
  • 需要开放防火墙端口

8.4 配置虚拟主机别名

8.4.1 别名配置

虚拟主机别名
虚拟主机设置除了主域名以外的一个域名,实现用户访问的多个域名对应同一个虚拟主机网站的功能。

配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 默认配置(只有主域名)
server {
listen 80;
server_name www.sunrisenan.com;

root /soft/code/www;
index index.html;
}

# 别名配置(主域名+别名)
server {
listen 80;
server_name www.sunrisenan.com sunrisenan.com;

root /soft/code/www;
index index.html;
}

测试

1
2
3
# 访问带www和不带www是一样的
curl sunrisenan.com
curl www.sunrisenan.com

9. URL重写和域名跳转

9.1 域名跳转配置

9.1.1 不带www跳转到www

方法1:使用rewrite

1
2
3
4
5
6
7
server {
listen 80;
server_name sunrisenan.com;

# 永久重定向到www
rewrite ^(.*) $scheme://www.$server_name$1 permanent;
}

方法2:使用return

1
2
3
4
5
6
7
server {
listen 80;
server_name sunrisenan.com;

# 301永久重定向
return 301 http://www.sunrisenan.com$request_uri;
}

9.1.2 HTTP跳转HTTPS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# HTTP跳转HTTPS
server {
listen 80;
server_name jump.mcake.com;

# 告诉浏览器有效期内只准用https访问
add_header Strict-Transport-Security max-age=15768000;

# 永久重定向到https站点
return 301 https://$server_name$request_uri;
}

# HTTPS配置
server {
listen 443 ssl;
server_name jump.mcake.com;

ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;

# 其他配置
}

9.1.3 完整域名跳转案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# HTTPS非www跳转www
server {
listen 443;
server_name airknow.com;

return 301 https://www.airknow.com$request_uri;
}

# HTTPS www主站点
server {
listen 443 default_server ssl;
server_name www.airknow.com;

ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;

# 其他配置
}

# HTTP非www跳转www
server {
listen 80;
server_name airknow.com;

return 301 http://www.airknow.com$request_uri;
}

# HTTP www跳转HTTPS
server {
listen 80;
server_name www.airknow.com;

return 301 https://www.airknow.com$request_uri;
}

9.2 URL重写规则

9.2.1 rewrite语法

1
2
3
Syntax: rewrite regex replacement [flag];
Default: —
Context: server, location, if

flag标记

flag 说明 作用
last 完成rewrite,重新匹配location 相当于Apache的[L]标记
break 终止匹配,不再匹配后面的规则 停止处理rewrite
redirect 返回302临时重定向 地址栏显示跳转后的地址
permanent 返回301永久重定向 地址栏显示跳转后的地址

9.2.2 常用重写规则

1. 将www.myweb.com/connect跳转到connect.myweb.com

1
2
rewrite ^/connect$ http://connect.myweb.com permanent;
rewrite ^/connect/(.*)$ http://connect.myweb.com/$1 permanent;

**2. 将connect.myweb.com 301跳转到www.myweb.com/connect/**:

1
2
3
if ($host = "connect.myweb.com") {
rewrite ^/(.*)$ http://www.myweb.com/connect/$1 permanent;
}

3. myweb.com跳转到www.myweb.com

1
2
3
if ($host != 'www.myweb.com') {
rewrite ^/(.*)$ http://www.myweb.com/$1 permanent;
}

4. www.myweb.com/category/123.html跳转为category/?cd=123

1
rewrite "^/category/(.*).html$" /category/?cd=$1 last;

**5. www.myweb.com/admin/下跳转为www.myweb.com/admin/index.php?s=**:

1
2
3
if (!-e $request_filename) {
rewrite ^/admin/(.*)$ /admin/index.php?s=/$1 last;
}

**6. 在后面添加/index.php?s=**:

1
2
3
if (!-e $request_filename) {
rewrite ^/(.*)$ /index.php?s=/$1 last;
}

7. www.myweb.com/xinwen/123.html等跳转为404

1
rewrite ^/xinwen/([0-9]+)\.html$ /404.html last;

8. http://www.myweb.com/news/radaier.html 301跳转

1
rewrite ^/news/radaier.html http://www.myweb.com/strategy/ permanent;

9. 重定向链接为404页面

1
rewrite http://www.myweb.com/123/456.php /404.html last;

10. 禁止.htaccess访问

1
2
3
location ~ /\.ht {
deny all;
}

11. 禁止/data/下多级目录下.log.txt等请求

1
2
3
location ~ ^/data {
deny all;
}

12. 禁止单个文件

1
2
3
location ~ /www/log/123.log {
deny all;
}

13. 日期格式跳转

1
2
rewrite ^/news/activies/2014\-([0-9]+)\-([0-9]+)/(.*)$ \
http://www.myweb.com/news/activies/$3 permanent;

14. 多条件重定向

1
2
3
4
5
6
7
8
9
10
# 如果需要打开带有play的链接就跳转到play,不过/admin/play这个不能跳转
if ($request_filename ~ (.*)/play) {
set $payvar '1';
}
if ($request_filename ~ (.*)/admin) {
set $payvar '0';
}
if ($payvar ~ '1') {
rewrite ^/ http://play.myweb.com/ break;
}

15. 参数跳转

1
2
3
if ($request_uri ~ "/\?gid\=6") {
return 301 http://www.myweb.com/123.html;
}

9.3 正则表达式和条件判断

9.3.1 正则表达式匹配

匹配符 说明
~ 区分大小写匹配
~* 不区分大小写匹配
!~ 区分大小写不匹配
!~* 不区分大小写不匹配

9.3.2 文件及目录判断

判断符 说明
-f 判断是否存在文件
!-f 判断是否不存在文件
-d 判断是否存在目录
!-d 判断是否不存在目录
-e 判断是否存在文件或目录
!-e 判断是否不存在文件或目录
-x 判断文件是否可执行
!-x 判断文件是否不可执行

10. Nginx慢请求日志记录

10.1 慢请求日志配置

10.1.1 配置慢请求日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
http {
# 定义慢请求日志格式
log_format slow '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time"';

# 记录慢请求(请求时间超过1秒)
server {
location / {
access_log /var/log/nginx/slow.log slow;
access_log /var/log/nginx/access.log main;

# 只记录慢请求
if ($request_time > 1) {
access_log /var/log/nginx/slow.log slow;
}
}
}
}

10.1.2 使用map记录慢请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
http {
# 定义慢请求阈值
map $request_time $slow_request {
default 0;
"~^[1-9]" 1; # 请求时间>=1秒
}

# 定义慢请求日志格式
log_format slow '$remote_addr [$time_local] "$request" '
'$status $body_bytes_sent $request_time';

server {
location / {
# 正常日志
access_log /var/log/nginx/access.log main;

# 慢请求日志
access_log /var/log/nginx/slow.log slow if=$slow_request;
}
}
}

10.2 慢请求分析

10.2.1 分析脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
cat > /usr/local/bin/nginx_slow_analysis.sh << 'EOF'
#!/bin/bash

SLOW_LOG="/var/log/nginx/slow.log"

if [ ! -f "$SLOW_LOG" ]; then
echo "Error: Slow log file not found: $SLOW_LOG"
exit 1
fi

echo "=== Nginx Slow Request Analysis ==="
echo ""

# 统计慢请求数量
TOTAL=$(wc -l < $SLOW_LOG)
echo "Total Slow Requests: $TOTAL"
echo ""

# 统计最慢的10个请求
echo "Top 10 Slowest Requests:"
awk '{print $NF}' $SLOW_LOG | sort -rn | head -10
echo ""

# 统计慢请求的URL
echo "Slow Request URLs:"
awk -F'"' '{print $2}' $SLOW_LOG | sort | uniq -c | sort -rn | head -10
EOF

chmod +x /usr/local/bin/nginx_slow_analysis.sh

11. 配置最佳实践

11.1 配置文件组织

11.1.1 配置文件结构

1
2
3
4
5
# 主配置文件:nginx.conf
http {
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}

11.1.2 配置文件分离

推荐结构

  • nginx.conf:主配置文件
  • conf.d/*.conf:虚拟主机配置
  • sites-enabled/*:启用的站点配置
  • sites-available/*:可用的站点配置

11.2 安全配置

11.2.1 隐藏版本信息

1
2
3
http {
server_tokens off;
}

11.2.2 限制请求大小

1
2
3
4
http {
client_max_body_size 10m;
client_body_buffer_size 128k;
}

11.3 性能配置

11.3.1 启用sendfile

1
2
3
4
5
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
}

11.3.2 启用压缩

1
2
3
4
5
6
http {
gzip on;
gzip_vary on;
gzip_min_length 1000;
gzip_types text/plain text/css application/json;
}

12. 故障排查

12.1 常见问题

12.1.1 配置语法错误

问题:配置文件语法错误

排查

1
2
3
4
5
# 测试配置文件
nginx -t

# 查看详细配置
nginx -T

12.1.2 虚拟主机不生效

问题:访问虚拟主机返回默认页面

排查

1
2
3
4
5
6
7
8
# 检查server_name配置
grep -r "server_name" /etc/nginx/

# 检查配置文件是否被包含
grep -r "include" /etc/nginx/nginx.conf

# 检查DNS解析
nslookup www.example.com

13. 总结

13.1 核心要点

  1. 配置文件结构:Main → Events → HTTP → Server → Location
  2. 日志配置:访问日志和错误日志的格式和变量
  3. 状态监控:stub_status模块的使用
  4. 访问限制:连接限制和请求限制
  5. 访问控制:基于IP和用户认证
  6. 虚拟主机:基于域名和端口的配置
  7. URL重写:域名跳转和URL重定向规则

13.2 架构师建议

  1. 配置管理

    • 配置文件分离,便于管理
    • 使用include包含配置文件
    • 版本控制配置文件
  2. 安全配置

    • 隐藏版本信息
    • 限制访问和请求
    • 使用HTTPS
  3. 性能优化

    • 启用sendfile
    • 启用gzip压缩
    • 合理设置worker进程数

13.3 最佳实践

  1. 标准化:统一配置标准和模板
  2. 模块化:配置文件分离,按功能组织
  3. 监控化:配置状态监控和日志分析
  4. 文档化:维护配置文档和变更记录

相关文章

  • 第448集 Nginx应用指南
  • [第447集 Apache select和Nginx epoll模型区别](./第447集Apache select和Nginx epoll模型区别.md)
  • [第446集 Nginx Cache缓存网站数据实践](./第446集Nginx Cache缓存网站数据实践.md)