Nginx 复习
Nginx 概述
Nginx(发音为”engine x”)是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP代理服务器。Nginx由Igor Sysoev于2004年首次公开发布,用于解决C10K问题(即服务器同时处理10,000个客户端连接的问题)。
- HTTP 服务器:它可以像 Apache、Tomcat 一样,直接把服务器上的静态文件(比如 HTML、图片、CSS、JS)返回给用户的浏览器。
- 反向代理服务器:这是它最重要、最常见的角色。它作为后端服务(比如你的 Java、Go、Python 应用)的“门户”,接收所有用户的请求,然后再把请求转发给后端的具体服务去处理。
Nginx 核心特性总结
1. 高并发、高性能 (High Concurrency & High Performance)
- 这是 Nginx 最广为人知的标签。它能以极低的内存和 CPU 资源消耗,轻松维持数万甚至数十万级别的并发连接。
- 核心原因:它从根本上解决了 C10K 问题,是为高并发场景而生的。
2. 事件驱动的异步非阻塞架构 (Event-Driven, Asynchronous Non-Blocking)
- 这是实现“高并发、高性能”的技术基石。
- 工作方式:Nginx 在处理网络连接和请求时,不会因为某个任务(如等待客户端发送数据或等待后端返回结果)而“傻等”(阻塞)。它会注册一个“事件”,然后立即去处理其他任务。当等待的任务完成后,它会接收到通知,再回来处理后续步骤。
- 结果:用极少数的工作进程就能“应付”海量的并发任务,大大节省了系统资源。
3. 强大的代理与网关层 (Robust Proxy and Gateway Layer)
- Nginx 不仅仅是简单的请求转发,它是一个功能丰富的应用网关。
- 体现在:
- 反向代理:隐藏和保护后端服务。
- 负载均衡:将请求压力分摊到多个后端服务器。
- 安全屏障:可配置访问控制、速率限制,抵御部分网络攻击。
- 性能优化:能执行 SSL 加密卸载、内容缓存、Gzip 压缩等,为后端减负。
4. 明确的职责分离 (Clear Separation of Concerns)
- Nginx 完美地将 网络连接管理 与 业务逻辑处理 这两个职责分离开。
- 职责划分:
- Nginx:专心处理所有与客户端之间的网络 I/O,无论连接是快是慢。
- 后端服务:从繁杂的网络问题中解脱出来,专心处理业务逻辑和数据 I/O(如数据库读写)。
- 结果:架构更清晰,使得各个部分可以独立优化和扩展。
5. 忠实的“问题报告者” (Faithful Problem Reporter)
- 当后端服务出现问题时,Nginx 不会隐藏问题,而是会明确地向客户端报告。
- 典型例子:
502 Bad Gateway
:后端服务不可达或已崩溃。504 Gateway Timeout
:后端服务处理请求太慢,超时了。
Nginx 的常见应用场景
- **静态资源服务器:**高效地提供静态文件如HTML、CSS、JavaScript、图片等。
- **反向代理服务器:**接收客户端请求并转发到后端服务器。
- **负载均衡器:**分发请求到多个后端服务器,提高系统整体性能和可靠性。
- **HTTP缓存:**缓存静态内容,减少后端服务器的负载。
- **API网关:**作为API请求的入口点,处理路由、认证、限流等功能。
与其他Web服务器的比较
相比Apache等传统Web服务器,Nginx在处理高并发连接方面表现更佳,资源消耗更低。与此同时,Nginx的配置相对简单,学习曲线较平缓。
Nginx 的工作模型
Nginx 的高性能秘密,就藏在它独特的工作模型里。这个模型可以拆分成两个层面来理解:
- 宏观的进程架构:它是如何组织自己的进程的?(Master-Worker 模型)
- 微观的工作方式:每个进程是如何处理海量连接的?(I/O 多路复用)
Master-Worker 多进程模型
当你在服务器上启动 Nginx 后,用 ps -ef | grep nginx
命令查看,通常会看到至少两个进程:一个 Master 进程和一个或多个 Worker 进程。
1. Master 进程 (主进程 / “管理者”)
Master 进程的角色是“领导”和“管理员”,它不直接处理任何用户的网络请求。它的主要工作是:
- 读取并验证配置:启动时,它会读取
nginx.conf
配置文件,检查语法是否正确。 - 创建和绑定端口:它会负责监听配置文件中指定的端口(如 80, 443)。
- 管理 Worker 进程:
- 根据配置(
worker_processes
指令)或者服务器的 CPU核心数,创建指定数量的 Worker 进程。 - 监控 Worker 进程的健康状态,如果某个 Worker 意外死掉了,Master 会立刻重新拉起一个新的。
- 接收来自管理员的控制信号,实现 Nginx 的平滑升级、优雅重启、停止服务等。例如,当你执行
nginx -s reload
来热加载配置时,就是 Master 进程在工作。
- 根据配置(
简单说,Master 进程就像一个“工头”,负责准备工作环境、招募并管理工人,但它自己不上一线干活。
2. Worker 进程 (工作进程 / “工人”)
Worker 进程才是真正处理用户请求的“一线员工”。
- 处理连接和请求:所有的用户连接和请求,都是由 Worker 进程来接收、处理和响应的。
- 相互独立:每个 Worker 进程都是一个独立的、单线程的进程。它们之间几乎没有共享数据,处理请求时互不干扰,这保证了高可靠性,一个 Worker 的崩溃不会影响其他 Worker。
- 共享监听端口:所有 Worker 进程都会共同监听由 Master 进程打开的端口。当一个新连接到来时,所有 Worker 会通过操作系统的机制(如
accept_mutex
锁)来“争抢”这个连接,最终只有一个 Worker 会成功接收并处理它。
这个 “一个管理者 + 多个高效工人” 的模型有几个巨大的好处:
- 稳定性:Master 作为守护进程,保证了 Worker 的稳定运行。Worker 之间相互隔离,一个出问题不影响全局。
- 高可用性:可以在不停止服务的情况下,通过向 Master 发送信号来平滑地升级程序、更新配置。
- 利用多核:可以配置与 CPU 核心数相等的 Worker 进程数,充分利用多核 CPU 的处理能力。
每个 Worker 进程都是单线程的,它凭什么能独自处理成千上万的并发连接呢?
I/O 多路复用 (以 epoll 为例)
Worker 进程高效的秘密武器,就是 I/O 多路复用 (I/O Multiplexing)。在 Linux 系统上,它具体的技术实现就是 **epoll,**应用程序可以通过调用 epoll_create
, epoll_ctl
, epoll_wait
这几个函数,来委托内核去帮它高效地管理大量的网络连接。
- 一个 Worker 进程把自己关心的所有连接(Socket)都注册到
epoll
系统中。 - 然后 Worker 进程就休眠了,调用
epoll_wait()
等待事件发生,几乎不占 CPU。 - 当某个连接上有数据传来、或可以发送数据时(即 I/O 事件就绪),操作系统会通知 Worker 进程,并把所有已就绪的连接列表告诉它。
- Worker 进程被唤醒,拿到这个“就绪列表”,然后依次处理这些连接上的请求。处理完后,继续回去“睡觉”,等待下一次的事件通知。
总结:
Nginx 的高性能模型 = Master-Worker 多进程架构 (充分利用多核、稳定可靠) + I/O 多路复用 epoll
(单个 Worker 进程高效处理海量连接的核心技术)。
Nginx 的配置与核心指令
Nginx 的安装与目录结构
通常,我们通过包管理器(如 yum
或 apt-get
)安装 Nginx。
记住以下几个核心位置至关重要:
- 主配置文件:
/etc/nginx/nginx.conf
- 这是 Nginx 的“大脑”,几乎所有的配置都从这里开始。
- 可拆分的配置目录:
/etc/nginx/conf.d/
- 在实践中,我们很少把所有配置都写在
nginx.conf
这一个文件里。通常,nginx.conf
会通过include /etc/nginx/conf.d/*.conf;
这样的指令,把这个目录下的所有.conf
文件都加载进来。 - 最佳实践:每为一个网站或一个服务做代理,就在
conf.d
目录下新建一个独立的配置文件(如my_app.conf
)。这让配置管理变得非常清晰。
- 在实践中,我们很少把所有配置都写在
- 日志文件目录:
/var/log/nginx/
access.log
: 访问日志。记录了每一个请求的详细信息(谁访问的、访问了什么、何时访问、响应状态等)。是排查业务问题和做数据分析的基础。error.log
: 错误日志。记录了 Nginx 启动、运行过程中的所有错误信息。当 Nginx 启动失败或者出现 5xx 错误时,第一时间就应该来这里找线索。
- 默认网站根目录:
/usr/share/nginx/html/
- 当你安装完 Nginx 第一次启动,在浏览器里访问服务器 IP,看到的那个“Welcome to Nginx!”页面,就是存放在这个目录下的
index.html
。
- 当你安装完 Nginx 第一次启动,在浏览器里访问服务器 IP,看到的那个“Welcome to Nginx!”页面,就是存放在这个目录下的
Nginx 的基本控制命令
我们通常使用 nginx
这个可执行文件(或者通过 systemctl
),配合不同的参数来控制它。
- 测试配置:
nginx -t
- 极其重要! 在你修改了任何
.conf
配置文件后,永远不要直接重启 Nginx。先执行nginx -t
,它会检查所有配置文件的语法。如果没问题,它会提示syntax is ok
和test is successful
。这能避免因为一个小小的语法错误(比如少个分号)导致整个网站宕机。
- 极其重要! 在你修改了任何
- 启动 Nginx:
nginx
或systemctl start nginx
- 直接执行
nginx
命令(或使用systemctl
)。
- 直接执行
- 停止 Nginx:
nginx -s stop
:快速停止,不管当前有无正在处理的请求,直接“一刀切”。nginx -s quit
:优雅停止 (graceful stop),会等待当前所有正在处理的请求完成后,再关闭进程。
- 重载配置 (热加载):
nginx -s reload
- 核心功能! 这也是 Master-Worker 模型优势的体现。当执行
reload
时:- Master 进程会先去检查配置(类似
nginx -t
)。 - 如果配置无误,Master 会启动新的 Worker 进程(使用新配置)。
- 同时,Master 会向老的 Worker 进程发送“优雅停止”的信号。
- 老的 Worker 进程不再接受新的连接,并在处理完手头所有请求后自行退出。
- Master 进程会先去检查配置(类似
- 整个过程服务不中断,用户的访问完全无感知,这是生产环境中更新配置的标准操作。
- 核心功能! 这也是 Master-Worker 模型优势的体现。当执行
Nginx 核心指令解析
#================ 全局块 (Global Block) ================
# 这部分没有花括号,是最高层级的指令。
user nginx;
worker_processes auto; # 通常设置为 auto 或 CPU 核心数
error_log /var/log/nginx/error.log warn;
#====================================================
#================ events 块 ================
# 配置与网络连接相关的参数
events {
worker_connections 1024; # 每个 worker 进程能处理的最大连接数
use epoll; # 在 Linux 上使用 epoll 模型,性能最高
}
#===========================================
#================ http 块 ================
# 这是配置 Web 服务和代理功能最核心的块
http {
# --- http 全局配置 ---
# 定义了可以在 http 块下所有 server 块中使用的公共配置
include /etc/nginx/mime.types;
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 on;
keepalive_timeout 65;
# --- server 块 (定义一个虚拟主机) ---
server {
listen 80; # 监听 80 端口
server_name www.example.com; # 对应的域名
# --- location 块 (定义请求路由规则) ---
location / {
root /usr/share/nginx/html; # 网站根目录
index index.html index.htm; # 默认首页文件
}
location /api/ {
# 这里的规则会匹配所有 "www.example.com/api/..." 的请求
# 比如,可以把请求转发给后端服务
proxy_pass http://backend_server_address;
}
}
# --- 可以定义第二个 server 块 ---
server {
listen 80;
server_name another.example.com;
# ... 针对 another.example.com 的配置 ...
}
}
#===========================================
全局块 (Global Block)
*user**
指定 Nginx 的 Worker 进程以哪个用户和用户组的身份运行。出于安全考虑,通常会指定为一个权限较低的专用用户(如nginx
或www-data
)。*worker_processes**
设置 Worker 进程的数量。这是性能调优的关键,最佳实践是设置为auto
,Nginx 会自动检测服务器的 CPU 核心数并以此作为 Worker 数量。*error_log**
定义全局的错误日志文件路径和记录级别。当 Nginx 遇到问题时(如配置错误、启动失败),这里是寻找线索的首要地点。*pid**
指定存放 Master 进程 ID 的文件路径。这个文件主要用于脚本自动化控制 Nginx。
events
块
*worker_connections**
设置每一个 Worker 进程能够同时处理的最大连接数。这是 Nginx 并发能力的核心指标。服务器的总并发能力理论上等于worker_processes * worker_connections
。*use**
指定 Nginx 使用的 I/O 多路复用模型。如我们所讨论的,在 Linux 上 Nginx 会自动选择最高效的epoll
,所以此项一般无需配置。
http
块
*include**
用于引入其他的配置文件,是保持主配置文件nginx.conf
简洁的最佳实践。include /etc/nginx/conf.d/*.conf;
就是一个典型的例子。mime.types
这个文件里定义了文件扩展名和MIME类型(Content-Type)之间的对应关系。比如,它里面有这样的内容:text/html html;
、image/jpeg jpg jpeg;
。浏览器需要根据服务器返回的Content-Type
头来决定如何展示一个文件(是当成网页渲染,还是当成图片显示)。*access_log**
设置访问日志的存放路径和使用的格式。可以设置off
来关闭日志记录。*log_format**
自定义访问日志的格式。可以添加更多变量(如$request_time
,$upstream_response_time
)来记录请求耗时等信息,对于性能分析非常有用。*sendfile**
一个性能优化指令。设置为on
会启用操作系统高效的文件传输模式(零拷贝),可以让 Nginx 在传输静态文件时更快、更节省资源。*keepalive_timeout**
设置 HTTP 长连接的超时时间。合理的设置可以减少客户端与服务器之间频繁建立和断开 TCP 连接的开销,提升性能。*client_max_body_size**
限制客户端请求体(Request Body)的最大尺寸。当用户需要上传文件时,如果文件大小超过这个值,Nginx 会返回413 Request Entity Too Large
错误。这是控制资源滥用的重要指令。
server
块
*listen**
指定虚拟主机监听的端口号。可以附加ssl
参数来表示此端口用于 HTTPS 通信。例如:listen 443 ssl;
。*server_name**
指定虚拟主机的域名。Nginx 通过请求头中的Host
字段来匹配对应的server_name
,从而决定由哪个server
块来处理该请求。这是实现虚拟主机的关键。
location
块
这是 Nginx 配置中最核心、最灵活的部分,决定了如何处理具体的请求 URI。
*root**
指定静态文件的根目录。当请求匹配到这个location
时,Nginx 会将请求的 URI 拼接到root
指定的路径后,去硬盘上寻找对应的文件。server { listen 80; server_name example.com; # 示例: 访问 http://example.com/images/logo.png location /images/ { root /var/www/app; # Nginx 寻找的物理路径是: # /var/www/app + /images/logo.png # 结果: /var/www/app/images/logo.png } }
*index**
当请求的 URI 是一个目录时,指定默认去查找的文件名。例如,访问http://example.com/
时,Nginx 会依次尝试查找root
目录下的index.html
和index.htm
文件。- 访问
http://example.com/
:Nginx 会先寻找/var/www/app/index.html
,如果找不到,再寻找/var/www/app/index.php
。
location / { root /var/www/app; index index.html index.php; # 优先找 index.html, 找不到再找 index.php }
- 访问
*proxy_pass**
反向代理的核心指令。它指定了要将请求转发到的后端服务器地址。地址可以是 IP:Port、域名,或者是一个通过upstream
块定义的服务器组。- 访问
http://example.com/api/users
: - 注意:
proxy_pass
后面地址的/
非常关键:- 带
/
(http://.../
):表示将原始 URI 中匹配location
的部分(/api/
)去掉后再拼接;Nginx 会将请求转发到http://127.0.0.1:8080/users
。 - 不带
/
(http://...
):表示将原始 URI 原封不动地拼接到后面;Nginx 会将请求转发到http://127.0.0.1:8080/api/users
。
- 带
location /api/ { # 将所有 /api/ 开头的请求转发给运行在 8080 端口的后端应用 proxy_pass http://127.0.0.1:8080/; }
- 访问
*try_files**
按顺序检查指定的文件或目录是否存在。如果存在,就返回该文件;如果都不存在,就执行最后一个参数指定的操作(通常是内部重定向)。在配置单页应用(SPA)的路由时非常有用,例如try_files $uri $uri/ /index.html;
。- 访问
http://example.com/user/profile
:$uri
:Nginx 尝试寻找文件/var/www/spa-app/user/profile
。失败。$uri/
:Nginx 尝试寻找目录/var/www/spa-app/user/profile/
下的index
文件(即index.html
)。失败。/index.html
:前面都失败后,Nginx 会发起一个内部重定向,去请求并返回/index.html
。
- 效果:无论用户访问哪个路径,最终都会返回
/index.html
,浏览器 URL 保持不变,后续的路由交由前端 JS 来处理。
location / { root /var/www/spa-app; index index.html; try_files $uri $uri/ /index.html; }
- 访问
*alias**
与root
类似,也是用来指定文件路径,但它的路径拼接行为不同。alias
会用指定的路径替换掉location
匹配到的 URI 部分。root
vsalias
关键区别:root
是拼接完整 URI,alias
是替换 location URI。使用alias
时,路径末尾的/
通常很重要。
server { # 示例: 访问 http://example.com/assets/logo.png # 注意,/assets/ 目录可能在项目目录之外 location /assets/ { alias /var/www/other_static_files/; # Nginx 寻找的物理路径是: # /var/www/other_static_files/ + logo.png (注意 /assets/ 被替换掉了) # 结果: /var/www/other_static_files/logo.png } }
Nginx核心功能三大支柱
1. 静态资源服务器 (Static Resource Server)
虽然我们现在更多地将 Nginx 用作反向代理,但它最初就是作为一个超高性能的 Web 服务器而设计的,其处理静态文件(图片、CSS、JS、HTML文件等)的能力至今仍然是业界标杆。
我们之前已经知道,通过 root
和 index
指令就可以让它工作起来。但面试中,面试官更想知道的是:
- 为什么 Nginx 处理静态文件那么快?
- 有哪些优化的手段?
A. Nginx 高性能的背后原理
Nginx 的性能优势源于它的架构设计,主要体现在两点:
- I/O 多路复用 (
epoll
): 我们在第一站已经深入探讨过。它让 Nginx 能用极少的进程处理海量的并发连接,避免了为每个连接创建新进程/线程的巨大开销。 - sendfile 系统调用: 这是一个关键的性能“黑科技”。
- 传统方式:一个程序(如 Web 服务器)想把一个文件发送出去,需要先把文件内容从硬盘读到内核缓冲区,然后再从内核缓冲区复制到应用程序的内存中,最后再从应用程序内存复制回内核的 Socket 缓冲区,才能通过网卡发送。这个过程有两次不必要的数据拷贝,浪费 CPU 和内存。
- sendfile 方式:Nginx 使用
sendfile
系统调用,它告诉内核:“请把这个文件的内容直接从你的内核缓冲区发送到那个网络连接的 Socket 缓冲区去”。数据完全在内核空间内进行传输,不需要拷贝到应用程序(Nginx)的内存中。这个过程被称为**“零拷贝” (Zero-copy)**,极大地提升了文件传输效率,降低了 CPU 消耗。
正是因为 epoll
+ sendfile
这对组合拳,Nginx 才成为了处理静态文件的王者。
B. 静态资源服务的优化配置
让 Nginx 工作起来很简单,但要把它配置到最优,还需要一些额外的指令。这些优化手段主要围绕两个目标:减轻服务器压力和加速客户端访问。
开启高效传输模式
这些指令通常放在 http
块中,它们能进一步发挥 Nginx 和操作系统的性能。
http {
# 启用 sendfile "零拷贝" 模式
sendfile on;
# 在 sendfile 开启的情况下,优化网络包的发送。
# 它会将响应头和文件内容一次性发送出去,而不是先发头再发内容。
tcp_nopush on;
}
2. 配置浏览器缓存 (expires
)
这是最重要的静态资源优化手段。它通过设置 HTTP 响应头,告诉浏览器这个文件可以在本地缓存多久,下次请求时就无需再从服务器下载了。
# 匹配所有图片、CSS、JS 等静态资源
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
root /path/to/your/assets;
# 设置缓存过期时间为 30 天
expires 30d;
}
- 对于不常变化、且文件名唯一的静态资源(如带 hash 的 JS 文件
main.a4b8c1.js
),可以设置非常长的缓存时间,如expires 1y;
(一年)。 - 对于像
index.html
这样可能随时更新的文件,通常不设置强缓存,或者设置为expires -1;
,让浏览器每次都来服务器验证。
3. 开启 Gzip 压缩
对于文本类文件(HTML, CSS, JS, JSON),在传输前进行压缩,可以极大地减小文件体积,加快传输速度。图片(JPG/PNG)和视频本身已经是压缩格式,不需要再用 Gzip。
http {
# 开启 Gzip
gzip on;
# 指定哪些类型的文件需要被压缩
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# 其他优化,比如设置最小压缩文件大小,避免压缩过小的文件
gzip_min_length 1k;
}
gzip
指令通常放在 http
块中,对所有网站生效。
总结一下:
一个优化良好的静态资源服务器配置,会充分利用 Nginx 的 sendfile
机制,并通过 expires
和 gzip
指令,最大化地减少网络传输量和请求次数。
反向代理与负载均衡
A. 负载均衡 (Load Balancing)
是什么?
负载均衡是将网络请求分发到多个后端服务器上去处理的机制。它是构建高可用、可扩展服务的基石。
为什么?
- 分担压力 (Scalability):单台服务器性能有上限,通过增加服务器数量来线性提升处理能力。
- 提高可用性 (High Availability):当某台后端服务器宕机时,Nginx 会自动将其从分发列表中剔除,将请求发往其他健康的服务器,保证服务不中断。
怎么配?
通过 upstream
和 proxy_pass
两个指令配合完成。
upstream
块:用来定义一组后端服务器。这个块必须写在http
块中。proxy_pass
:在location
块中,将其指向upstream
定义的组名。
示例:
http {
# 1. 定义一个名为 "backend_servers" 的后端服务器集群
upstream backend_servers {
server 192.168.1.100:8080; # 服务器1
server 192.168.1.101:8080; # 服务器2
}
server {
listen 80;
server_name example.com;
location / {
# 2. 将所有请求转发到 "backend_servers" 集群
proxy_pass http://backend_servers;
}
}
}
B. 负载均衡核心策略
Nginx 提供了多种策略来决定请求到底该发给哪台服务器。
- 轮询 (Round Robin) - 默认策略
- 行为:按顺序,一人一次。第一个请求给服务器1,第二个给服务器2,第三个再给服务器1…
- 配置:无需任何额外配置。
- 权重 (Weight)
- 行为:根据指定的权重比例来分配请求。权重越高的服务器,被分配到的请求就越多。适用于服务器性能不一的场景。
- 配置:
server 192.168.1.100:8080 weight=3;
- IP 哈希 (ip_hash)
- 行为:根据客户端的 IP 地址进行哈希计算,确保同一个客户端的请求,总是被转发到同一台后端服务器。
- 为什么:解决 Session 共享问题。如果用户在服务器A登录了,下一个请求被分到了服务器B,服务器B没有它的登录信息,就会导致用户需要重新登录。
ip_hash
可以避免这种情况。 - 配置:在
upstream
块里加上ip_hash;
即可。
- 最少连接 (least_conn)
- 行为:将请求优先分配给当前活跃连接数最少的后端服务器。适用于请求处理时间长短不一的场景,能者多劳。
- 配置:在
upstream
块里加上least_conn;
。
C. 健康检查
upstream
块可以配置简单的健康检查机制。
max_fails=3
:在fail_timeout
时间内,请求后端失败达到3次,则认为该服务器宕机。fail_timeout=10s
:暂停向该服务器转发请求10秒,10秒后会再次尝试。
进阶与优化专题
A. HTTPS 配置
是什么:为网站启用 SSL/TLS 加密,使 HTTP 协议变为更安全的 HTTPS。
怎么配:
- 准备好你的域名证书(
.crt
文件)和私钥(.key
文件)。 - 修改
server
块的配置。
示例:
server {
# 1. 监听 443 端口,并开启 ssl
listen 443 ssl http2; # http2 可以顺便开启,提升性能
server_name example.com;
# 2. 指定证书和私钥的路径
ssl_certificate /path/to/your/certificate.crt;
ssl_certificate_key /path/to/your/private.key;
# 可选:配置 SSL 协议和加密套件,增强安全性
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:...';
# ... 其他 location 配置 ...
}
# 可选但强烈推荐:将所有 HTTP 请求强制重定向到 HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
B. Nginx 缓存
是什么:将后端服务器返回的内容在 Nginx 上缓存一份。对于不常变化的内容,Nginx 可以直接从缓存中返回,不必再请求后端,极大减轻后端压力。
怎么配:
proxy_cache_path
: 在http
块中,定义一块缓存区域的物理路径和规则。proxy_cache
: 在location
块中,启用上面定义好的缓存。
示例:
http {
# 1. 定义一个名为 "my_cache" 的缓存区
# 路径在 /var/nginx/cache, 占用100m磁盘空间, 1天内未被访问则自动清除
proxy_cache_path /var/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=100m inactive=1d;
server {
# ...
location /some/path/ {
# 2. 在这个 location 启用名为 "my_cache" 的缓存
proxy_cache my_cache;
proxy_pass http://backend_servers;
}
}
}
C. 跨域问题处理(CORS)
当前端应用和后端 API 不在同一个域名下时,浏览器会出于安全策略阻止请求。可以通过 Nginx 在响应中添加特定的头信息来解决。
location /api/ {
# 允许来自任何源的请求
add_header 'Access-Control-Allow-Origin' '*';
# 允许的请求方法
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
# 允许的请求头
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,Content-Type';
# ... proxy_pass 等指令 ...
}
D. 快速排错
- 第一步:修改配置后,永远先执行
nginx -t
检查语法。 - 第二步:遇到问题(如页面打不开),立刻查看日志:
error.log
: 查看 Nginx 自身是否有错误,比如无法连接后端、权限问题等。access.log
: 查看请求是否到达 Nginx,以及 Nginx 返回的状态码是什么。
- 理解关键状态码:
- 502 Bad Gateway: 网关坏了。Nginx 无法连接到后端服务,或者后端服务挂了、返回了无效响应。问题在后端应用本身。
- 504 Gateway Timeout: 网关超时。Nginx 成功连接到了后端,但后端处理请求太慢,超过了 Nginx 的等待时间。问题是后端应用性能低下或卡死。