Nginx是什么
因为我之前没怎么接触过 nginx,个人配置 Web 服务器几乎全部使用 Apache,所以说我也是重新学习一下
Nginx是 lgor Sysoev 为俄罗斯访问量第二的 rambler.ru 站点设计开发的。从2004年发布至今,凭借开源的力量,已经接近成熟与完善。
Nginx 是一种代理服务器,代理服务器是一种位于客户端与服务器之间的中间层服务器,其主要功能是转发客户端的请求到目标服务器,并将目标服务器的响应返回给客户端,并在中间提供各种功能。在生产环境中,几乎所有现代 Web 应用架构都会将 Nginx 作为前端的第一道防线和流量入口。客户端直接连接的是 Nginx,而不是后端应用服务器,Nginx负责将流量转发给它们,这提升了性能和并发能力的同时,而且保护了后端应用服务器。
Nginx功能丰富,而且轻量,可作为HTTP服务器,也可作为反向代理服务器,邮件服务器。支持FastCGI、SSL、Virtual Host、URL Rewrite、Gzip等功能。并且支持很多第三方的模块扩展。而且处理高并发能力是十分强大的。
Nginx支持热部署,启动简单,可以做到7*24不间断运行。几个月都不需要重新启动。
一个典型的使用 Nginx 的架构通常是这样的:
1 | [客户端浏览器/搜索引擎爬虫] <---> [Nginx服务器] <---> [后端应用服务器集群] |
在这个架构中:
- Nginx:处理所有客户端请求,负责反向代理、负载均衡、SSL 终止和缓存。
- 后端应用服务器:运行实际的业务逻辑。它们通常是无状态的,可以水平扩展。
而且 Nginx 是一个强大的多面手 Web 服务器,主要功能包括:
- HTTP 服务器:这是最基本的功能,用于直接提供 HTML、CSS、JavaScript、图片等静态文件
- 反向代理:这是 Nginx 最核心和最常用的功能之一。它接收客户端(如浏览器)的请求,然后将请求转发到后端的其他服务器。客户端只与 Nginx 交互,完全不知道后端服务器的存在。
- 负载均衡:当有多个后端服务器时,Nginx 可以将客户端的请求智能地分发到不同的服务器上,从而避免单个服务器过载,提高整个应用的可用性和处理能力。
- 缓存:Nginx 可以缓存从后端服务器获取的内容(如 API 响应、图片),对于频繁访问但很少变化的内容,直接从 Nginx 缓存中返回,大大减轻后端服务器的压力并提升响应速度。
- SSL/TLS 终止:Nginx 可以处理 SSL/TLS 握手和加密 / 解密过程,即 “终止” SSL 连接。这意味着后端应用服务器不需要处理复杂的加密逻辑,只需要处理普通的 HTTP 请求,从而简化了应用代码并提高了安全性。
- URL 重写与重定向:可以根据规则重写 URL 路径,或者将请求重定向到其他地址,实现更灵活的路由控制。
- 健康检查:在负载均衡模式下,Nginx 可以定期检查后端服务器的健康状态,自动将故障的服务器从服务列表中剔除,保证服务的高可用。
什么是代理和反向代理
Nginx 代理分为两类:
- 正向代理:客户端通过 Nginx 访问外部资源,外部服务器认为请求来自 Nginx。
- 反向代理:客户端访问 Nginx,Nginx根据配置将请求转发到后端服务器,客户端并不知道后端服务器的真实地址。
Nginx 最常用于 反向代理
正向代理
什么是正向代理
我们都学习过代理设计模式,都知道代理模式中有代理角色和被代理角色
正向代理就是你去主动连接一个中间服务器,让它帮你访问目标网站,在这个过程中,目标服务器并不知道真正的客户端是谁,它只知道是代理服务器在请求它。
例如:你想进山姆买点东西,但你没有会员资格。于是你找了一个有会员资格的朋友(代理服务器),让他把会员卡借你刷卡进门(代表你访问目标服务器)。山姆(目标服务器)只认识你的朋友,而不认识你。
这种情况对应我们日常生活中很多访问国外网站的情况,在这个时候如果不使用代理,访问速度会非常慢,通常这时候我们会通过给浏览器配置一个网速快的、可以访问国外网站内容的代理来解决我们的问题
我们首先请求代理服务器,然后代理服务器帮我们去快速访问国外的网站,对于这种代理方式,我们就称之为正向代理。
此时,我们当前的角色为 被代理者,正向代理的本质是我们去请求外部的资源,是客户端(如你的浏览器)主动决定要访问哪个目标服务器
如果以生产者、消费者模式来区分,我们属于消费者。而且正向代理中,我们不对外提供服务,反而是对外消费服务,属于消费者。
不止访问国外网站,代理服务器在缓存加速,过滤内容上也很重要(扫码dmm就是通过正向代理隔绝非日本用户的)
反向代理
很明显,就是和正向代理相反
其中客户端(如浏览器)的请求首先到达一个代理服务器(Nginx),然后由代理服务器根据配置将请求转发到后端的一个或多个应用服务器
在这个过程中,客户端只知道代理服务器的存在,而不知道后端应用服务器的存在。
去饭馆吃饭就是很明显的例子,你去一家餐厅吃饭。你(客户端)只需要和门口的迎宾员(Nginx)打交道,告诉他你要吃什么。迎宾员(Nginx)会把你的需求(请求)传达给厨房的厨师(后端应用服务器),然后把做好的菜(响应)端给你。你从头到尾都没有见过厨师。
反向代理就是客户端主动发起请求,但请求首先到达代理服务器。客户端只与代理服务器交互,完全不知道后端有哪些应用服务器。因为代理服务器知道后端所有应用服务器的地址和状态。
最典型的用处就是负载均衡和隐藏后端
如何编写 Nginx 配置
Nginx配置文件结构
Nginx 的配置文件几乎管理了 Nginx 几乎全部的配置
而且Nginx
的配置由主配置文件**(nginx.conf)和模块化配置文件(如conf.d/*.conf)组成,整体遵循层级嵌套的结构
- 主配置文件
/etc/nginx/nginx.conf(Linux)是入口,主配置中通常通过include指令引入其他配置文件 - 建议将不同域名 / 服务的配置拆分到
conf.d目录下的独立文件,便于维护
其中配置文件的结构如下
1 | ... #全局块 |
graph TD
A[全局块] --> B[events块]
A --> C[http块]
C --> D[upstream块]
C --> E[server块]
E --> F[location块]
其中
全局块是配置文件的最顶部,用于设置影响 Nginx 整体运行的全局参数
1
2
3
4
5
6
7
8
9
10
11# 运行Nginx的用户和用户组(Linux)
user nginx;
# Nginx工作进程数,建议设置为CPU核心数(如4核CPU设为4)
worker_processes auto; # auto会自动匹配CPU核心数
# 错误日志路径和级别(debug/info/notice/warn/error/crit)
error_log /var/log/nginx/error.log warn;
# 进程PID文件路径
pid /var/run/nginx.pid;全局块内的 events 块是用于配置 Nginx 与客户端连接相关的参数,影响 Nginx 的并发处理能力,仅能有一个 events 块。
1
2
3
4
5
6
7
8
9
10events {
# 每个工作进程的最大并发连接数
worker_connections 10240;
# 采用epoll模型(Linux下高性能的事件驱动模型)
use epoll;
# 允许一个连接同时被多个工作进程接受(提高连接效率)
multi_accept on;
}全局块内的http块是 Nginx 处理 HTTP/HTTPS 请求的核心配置块,包含所有与 HTTP 相关的全局配置,可嵌套多个
server和upstream块。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
35
36
37
38
39http {
# 引入MIME类型映射文件(决定不同文件的Content-Type响应头)
include /etc/nginx/mime.types;
default_type application/octet-stream; # 默认MIME类型
# 日志格式定义(main是自定义名称,可在server/location中引用)
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;
# 合并小数据包发送,减少网络IO
tcp_nopush on;
# 关闭TCP延迟确认,提高实时性
tcp_nodelay on;
# 连接超时时间(客户端与Nginx的连接保持时间)
keepalive_timeout 65;
# 开启gzip压缩,减小传输体积
gzip on;
gzip_types text/plain text/css application/json application/javascript;
# 引入后端服务器集群配置(可多个upstream)
upstream backend_api {
server 192.168.1.100:8080 weight=1 max_fails=3 fail_timeout=30s;
server 192.168.1.101:8080 weight=2 max_fails=3 fail_timeout=30s;
# weight:权重,数值越大接收请求越多
# max_fails:失败重试次数
# fail_timeout:失败后多久重新检测
}
# 引入虚拟主机配置(可多个server)
include /etc/nginx/conf.d/*.conf;
}http块内的 server 块对应一个虚拟主机,用于配置特定域名 / 端口的服务,是 HTTP 配置的核心单元,可嵌套多个
location块。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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58server {
# 监听的端口和协议(80=HTTP,443=HTTPS)
listen 80;
listen [::]:80; # 监听IPv6
# 匹配的域名(多个域名用空格分隔,*为通配符)
server_name your-domain.com www.your-domain.com;
# 重定向HTTP到HTTPS(常见场景)
return 301 https://$host$request_uri;
}
# HTTPS服务配置示例
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name your-domain.com www.your-domain.com;
# SSL证书配置
ssl_certificate /etc/nginx/ssl/your-domain.crt;
ssl_certificate_key /etc/nginx/ssl/your-domain.key;
# SSL优化配置
ssl_session_timeout 1d;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
# 静态资源根目录
root /usr/share/nginx/html;
index index.html index.htm; # 默认首页
# location块:匹配URL路径,处理不同请求
# 匹配静态资源(优先级高)
location ~* \.(jpg|jpeg|png|gif|css|js)$ {
expires 7d; # 浏览器缓存7天
add_header Cache-Control "public, max-age=604800";
}
# 匹配API请求,转发到后端集群
location /api/ {
proxy_pass http://backend_api/; # 末尾/表示转发时去掉/api/前缀
# 转发请求头,让后端获取真实客户端信息
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 X-Forwarded-Proto $scheme;
# 代理连接超时配置
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
}
# 匹配根路径,处理前端SPA应用
location / {
try_files $uri $uri/ /index.html; # 解决SPA路由刷新404问题
}
}server内的 location 块用于匹配请求的 URL 路径,并对匹配的请求进行个性化处理(如转发、静态资源、重定向等),是 Nginx 配置中最灵活的部分。
语法 匹配类型 示例 说明 location = /精确匹配 location = /login仅匹配 /login,不匹配/login/或/login?id=1location ^~ /path前缀匹配(优先) location ^~ /static/匹配以 /static/开头的路径,且终止后续正则匹配location ~ pattern正则匹配(区分大小写) location ~ \.php$匹配以 .php结尾的路径location ~* pattern正则匹配(不区分大小写) location ~* .(jpg | png)$匹配以 .jpg/.png结尾的路径,不区分大小写location /path普通前缀匹配 location /api/匹配以 /api/开头的路径,优先级最低
而且,Nginx 配置文件规则大约这样
- 指令格式:
指令名 参数;(末尾必须加;,否则配置报错) - 注释:以
#开头,注释内容不会被解析 - 块指令:指令名后加
{},内部嵌套子指令(如server {}、location {}) - 变量使用:以
$开头,如$host(请求域名)、$remote_addr(客户端 IP)、$request_uri(完整请求路径) - 包含文件:
include指令可引入其他配置文件,支持通配符(如include conf.d/*.conf;) - 配置生效:修改配置后需执行
nginx -s reload重载配置(不中断服务)
正向代理配置详解
nginx 以反向代理为主,实际上,nginx 可以去配置正向代理,但是情况比较少见
1 | # 全局块(如果是独立配置文件,无需重复写全局块,仅需写http/server部分) |
上面配置中正向代理特有的、最关键的配置项,单独拿出来说一下
DNS 解析配置
1 | resolver 8.8.8.8 114.114.114.114 valid=300s; |
正向代理需要解析客户端请求的目标域名,比如用户访问www.baidu.com,Nginx
需要知道这个域名的 IP,resolver指定 DNS 服务器地址。
8.8.8.8/114.114.114.114是常用的公共 DNS 服务器valid=300s是DNS 解析结果的缓存时间
反向代理不需要这个配置但是正向代理必须配,否则会报no resolver defined to resolve xxx错误。
转发指令如下
1 | proxy_pass http://$host$request_uri; |
这是正向代理的核心,将客户端的请求转发到目标服务器
$host是客户端请求的目标域名,$request_uri是客户端的完整请求路径,一般情况下反向代理的proxy_pass是固定地址,因为这是你的域名,而正向代理是动态的,他要通过变量获取目标地址。
关闭请求缓冲
1 | proxy_request_buffering off; |
默认情况下,Nginx 会先把客户端的请求全部接收完,再转发给目标服务器(缓冲模式)。关闭后,Nginx 会实时转发请求(流式),适合代理大文件上传 / 下载场景。
牢记 Nginx 这两条命令
1 | # 1. 验证配置语法是否正确 |
反向代理配置详解
偏静态资源代理
一般情况下,反向代理会 和 静态资源服务一起配置,下面是我实际网站的一个 nginx 偏向静态资源的配置,拆来说一下
基础监听与域名配置
1 | # HTTPS服务的server块 |
listen:指定 Nginx 监听的端口和协议,ssl参数表示该端口启用 HTTPS;[::]:443是 IPv6 监听,生产环境一般同时配置 IPv4 和 IPv6。http2 on:启用 HTTP/2,需配合 HTTPS,因为HTTP/2 仅支持 HTTPSserver_name:匹配请求的Host头,只有请求域名是zyplatform.xyz时,才会走这个server块的配置;- 而且一般情况下,有 HTTPS ,HTTP 端口(80)就仅做跳转了
然后是 SSL/TLS 安全配置
1 | # SSL证书文件路径(公钥,包含域名证书+CA证书链) |
静态资源基础配置
1 | # 默认首页文件,按顺序查找 |
root:指定静态文件的根目录,当请求https://zyplatform.xyz/index.html时,Nginx 会去/www/wwwroot/zyplatform.xyz/index.html找文件。index:访问域名根路径(/)时,默认查找的文件;适配前端应用的首页。
如果你是 Vue,注意,需要配置 Vue History 模式路由兼容
1 | location / { |
因为 Vue History
模式下,刷新https://zyplatform.xyz/user这类路由时,Nginx
会认为/user是文件 / 目录,找不到就返回
404;try_files解决思路是先尝试匹配真实文件 /
目录,匹配不到则转发到index.html,由 Vue
的前端路由接管,避免 404;
这是前端 SPA(单页应用)反向代理的必配项
一些静态资源缓存和日志
1 | # 匹配图片、JS、CSS等静态资源,缓存30天 |
偏向 Nginx 反向代理
然后这是偏向 Nginx
反向代理的到我后端的配置,因为一般情况下,主域名会分配给前端网站做访问,api.的二级域名回去对接后端,去做
API 代理
其中重复的 HTTPS ,HTTP 重定向,SSL 这些重复的就不说了,直接看 Nginx 核心的反向代理配置
1 | location / { |
其中,这个块就是将匹配location /的所有请求(即api.zyplatform.xyz的所有
API 请求)转发到http://127.0.0.1:9006(Spring Boot
应用的监听地址);
而且proxy_set_header等这些传递客户端真实信息的必须要配,不加这些配置的话,Spring
Boot 中通过request.getRemoteAddr()获取的是 Nginx 服务器的
IP(127.0.0.1),而非真实用户的
IP;通过request.getScheme()获取的是http而非https,会导致业务逻辑(比如生成回调
URL)出错。
其中文件大小上传配置是简易配置的,而且通常简易配的要比 Spring Boot 控制的文件大小限制要大一些
1 | client_max_body_size 100m; |
那么,Nginx 反向代理的经典配置和常用配置项如下
1 | # 全局块 |
其中,Nginx 反向代理的配置核心就是 location 块内的内容,这是反向代理的核心中的核心,通常所有对接后端的配置都集中在这里
单独拿出来说一下
| 配置项 | 作用 | 关键说明 |
|---|---|---|
proxy_pass http://backend_cluster/ |
转发请求到后端服务 | 末尾/:去掉location前缀(如/api/user→/user);无/:保留前缀(如/api/user→/api/user) |
proxy_set_header Host $host |
传递请求域名到后端 | 后端多租户、域名匹配逻辑依赖此头 |
proxy_set_header X-Real-IP $remote_addr |
传递真实客户端 IP | 后端获取真实 IP(而非 Nginx 的 IP) |
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for |
传递代理链 IP | 多层代理时,拼接所有代理节点 IP |
proxy_set_header X-Forwarded-Proto $scheme |
传递协议(http/https) | 后端生成链接时避免出现 http(HTTPS 场景必配) |
proxy_connect_timeout 30s |
与后端连接超时 | 网络正常时设 30s,内网可设 10s |
proxy_read_timeout 60s |
读取后端响应超时 | 关键!长业务(如报表生成)需调大(如 120s),否则返回 504 |
proxy_send_timeout 60s |
向后端发送数据超时 | 大请求体(如批量 JSON)需调大 |
proxy_http_version 1.1 |
启用 HTTP/1.1 | WebSocket、长连接场景必开 |
proxy_set_header Upgrade $http_upgrade |
传递 WebSocket 升级头 | 实时通信(如聊天、推送)必配 |
proxy_set_header Connection "upgrade" |
强制连接升级 | 配合上一项启用 WebSocket |
proxy_buffering on |
启用响应缓冲 | Nginx
先接收后端响应,再发给客户端(减少后端连接数);大文件下载可设off(流式传输) |
- 请求头必配原则:
Host、X-Real-IP、X-Forwarded-For、X-Forwarded-Proto这 4 个头是反向代理必须的,无论什么场景都必须配置,否则后端会获取不到真实客户端信息。 - 性能优化原则
- 静态资源必开
sendfile和gzip,关闭访问日志; - HTTPS 必开
ssl_session_cache,减少握手耗时; - 高并发场景调大
worker_connections,设worker_processes为 CPU 核心数。
- 静态资源必开
差不多这样就可以了
当然微服务和分布式集群这种配置没有上纲上线来说,因为这些问题说起来还是很麻烦的,对了,Nginx 默认是轮询,通常配成加权轮询







