nginx 基础入门实战
之前一直在用hexo +Vercel部署博客,但最近突然想着在vps上部署自己的博客,再有域名加持,让简单的事变得没有那么简单。这个时候就想到了nginx反向代理。因此写一篇文章梳理一下
作用
- 反向代理: 隐藏后端服务器,提高安全性,实现负载均衡。
- 负载均衡: 将请求分发到多个后端服务器,提高系统吞吐量和可用性。
- 静态资源缓存: 缓存图片、CSS、JavaScript 等静态文件,减轻后端服务器压力,加快访问速度。
- SSL/TLS 加密: 提供 HTTPS 支持,保护数据传输安全。
- WebSockets 支持: 实现实时双向通信。
原理
事件驱动(Event-driven)架构:
- 传统服务器(如 Apache)通常采用多进程或多线程模型。每个连接都需要一个独立的进程或线程来处理,当连接数很多时,会消耗大量系统资源。
- Nginx 采用事件驱动模型。想象一下,一个服务员(Nginx 工作进程)可以同时服务多个餐桌(连接)。他不会一直站在一个餐桌旁等待,而是哪个餐桌有需要(事件发生,如顾客点餐、上菜)就去处理哪个。这种方式大大减少了资源消耗。
- Nginx 使用像 epoll (Linux)、kqueue (FreeBSD) 和 select/poll 这样的 I/O 多路复用技术来实现事件驱动。这些技术允许一个进程监控多个连接上的事件,并在事件发生时进行处理。
异步非阻塞(Asynchronous Non-blocking)I/O:
- 异步: 服务员(Nginx)告诉厨房(后端服务器)做菜后,不会傻傻地站在那里等,而是去服务其他餐桌。厨房做好菜后会通知服务员。
- 非阻塞: 服务员在等待厨房做菜的过程中,不会被“阻塞”住,可以处理其他事务。
- 传统的同步阻塞 I/O 模型中,一个进程在等待 I/O 操作完成时会被阻塞,无法做其他事情。而 Nginx 的异步非阻塞 I/O 模型则允许进程在等待 I/O 操作时,可以继续处理其他请求。
Master-Worker 进程模型:
- Nginx 启动时,会创建一个 Master 进程和多个 Worker 进程。
- Master 进程: 像餐厅老板,负责管理(如加载配置、启动/停止 Worker 进程、监控 Worker 进程状态)。
- Worker 进程: 真正的服务员,负责处理客户端请求。
- Master进程不处理客户端的请求。它只负责管理工作进程。比如当Master进程收到reload配置文件的命令以后,会先检查配置文件的正确性。然后通知worker进程。worker进程收到以后,会继续处理未完成的请求,处理完成以后,退出进程,根据新的配置文件启动新的worker进程。
- Nginx 启动时,会创建一个 Master 进程和多个 Worker 进程。
高效的内存管理:
- Nginx 使用内存池(memory pool)来管理内存。这样可以减少内存碎片,提高内存分配和释放的效率。
3. Nginx 的核心组件
- 核心模块(Core Module): 提供 Nginx 的基本功能,如进程管理、配置解析、错误处理等。
- 事件模块(Event Module): 实现事件驱动机制,处理网络连接和事件。
- HTTP 模块: 处理 HTTP 请求和响应。
- 邮件模块(Mail Module): 处理邮件代理相关功能。
- 流模块(Stream Module): 提供 TCP 和 UDP 流量的反向代理和负载均衡功能。
反向代理
这是nginx最常见的功能,那么为什么需要反向代理。它不只是隐藏后端服务器这么简单,还能防止攻击,过滤恶意请求。同时他还能处理SSL/TLS加密解密。
假设你有一个在线购物网站,有多个后端服务器分别处理商品展示、用户登录、购物车、订单支付等功能。
- 如果没有反向代理,客户端需要分别与这些服务器通信,配置复杂,而且每个服务器都需要直接暴露在公网上,安全风险高。
- 有了反向代理,客户端只需要与反向代理通信,反向代理根据请求的 URL 或其他规则,将请求转发到相应的后端服务器。反向代理还可以缓存静态资源,处理 SSL 加密,实现负载均衡,提高系统的安全性、性能和可用性。
实现
1. 目标
假设你有一个 Web 应用(比如一个 Node.js 应用)运行在本地的 3000 端口。你希望通过 Nginx 将对你的域名(例如 example.com
)的访问转发到这个应用。
2. 基础配置
步骤 1: 找到 Nginx 的配置文件。通常位于以下路径之一:
/etc/nginx/nginx.conf
/usr/local/nginx/conf/nginx.conf
/usr/local/etc/nginx/nginx.conf
步骤 2: 使用文本编辑器打开配置文件。
步骤 3: 找到 http
块,在其中添加一个 server
块。如果已经有 server
块,你可以直接修改它,或者添加一个新的。
1 | http { |
步骤 4: 保存配置文件。
步骤 5: 检查配置文件的语法是否正确:
1 | sudo nginx -t |
如果配置正确,你会看到类似这样的输出:
1 | nginx: the configuration file /etc/nginx/nginx.conf syntax is ok |
步骤 6: 重新加载 Nginx 配置,使更改生效:
1 | sudo nginx -s reload |
3. 配置解读
listen 80;
: Nginx 将监听 80 端口,处理 HTTP 请求。server_name example.com;
: 设置你的域名或服务器 IP。客户端通过这个域名或 IP 访问时,Nginx 会处理请求。location / { ... }
: 定义如何处理匹配的请求。/
表示匹配所有请求。proxy_pass http://localhost:3000;
: 这是反向代理的核心!它告诉 Nginx 将请求转发到http://localhost:3000
。
4. 常见问题排查
- 无法访问网站:
- 确保你的域名已正确解析到服务器 IP。
- 检查服务器防火墙是否允许 80 端口的流量。
- 确保你的后端应用正在运行,并且监听正确的端口(本例中是 3000)。
- Nginx 报错:
- 仔细检查
nginx -t
命令的输出,它会告诉你配置文件的哪一行有错误。 - 查看 Nginx 的错误日志(通常位于
/var/log/nginx/error.log
),可能会有更详细的错误信息。
- 仔细检查
6. 常用高级配置
6.1. proxy_set_header
:传递请求头
默认情况下,Nginx 转发请求时会修改一些请求头。proxy_set_header
指令可以让你控制传递给后端服务器的请求头。
1 | location / { |
X-Forwarded-For
假如客户端请求到达服务器之前,中间经过了 3 个代理服务器,那么每一个代理服务器都会把其的 IP 地址追加到 X-Forwarded-For
中,像这样:
1 | X-Forwarded-For: client, proxy1, proxy2 |
$proxy_add_x_forwarded_for
变量会自动添加当前服务器的 IP 地址到 X-Forwarded-For
头部。
6.2. proxy_redirect
:修改重定向
如果后端应用返回重定向响应(例如 302 Found),proxy_redirect
可以修改响应头中的 Location
字段。
1 | proxy_redirect off; # 通常设置为 off,除非你有特殊需求 |
6.3. 负载均衡(多个后端服务器)
如果有多个后端服务器,可以使用 upstream
块定义服务器组,实现负载均衡。
1 | upstream backend { |
负载均衡算法:
round_robin
(默认):轮询,依次将请求分发到每个服务器。least_conn
:最少连接,将请求分发到当前连接数最少的服务器。ip_hash
:根据客户端 IP 哈希,将同一个 IP 的请求分发到同一个服务器(用于会话保持)。
权重:
1 | upstream backend { |
6.4. 启用 HTTPS
获取 SSL/TLS 证书: 可以从 Let’s Encrypt (免费) 或其他证书颁发机构获取。
配置 Nginx:
1 | server { |
重要提示:
- 将
/path/to/your/
替换为你的证书和私钥的实际路径。 - 建议配置强密码和安全的密钥存储。
- 启用
ssl_protocols
,ssl_ciphers
和ssl_prefer_server_ciphers
。
常见命令
好的,在掌握了 Nginx 反向代理的配置之后,熟悉常用的 Nginx 命令对于日常管理和维护至关重要。下面列出了一些最常用的 Nginx 命令及其用法:
1. 启动、停止、重启 Nginx
启动 Nginx:
1
2
3sudo systemctl start nginx # 使用 systemd 管理的系统(如 Ubuntu 16.04+、Debian 8+、CentOS 7+)
sudo service nginx start # 使用 SysVinit 管理的系统(如 Ubuntu 14.04、Debian 7)
sudo nginx # 直接启动(通常不推荐,除非你知道自己在做什么)停止 Nginx:
1
2
3sudo systemctl stop nginx
sudo service nginx stop
sudo nginx -s stop # 强制停止选项 描述 stop 快速关闭 quit 优雅的关闭 reload 重新加载配置文件,优雅的停止旧的进程,开启新的进程 reopen 重新打开日志文件 重启 Nginx:
1
2
3sudo systemctl restart nginx
sudo service nginx restart
sudo nginx -s reload # 平滑重启(推荐,不会中断现有连接)优雅地停止:
1
sudo nginx -s quit #等待工作进程处理完成当前连接后关闭
2. 检查 Nginx 状态
1 | sudo systemctl status nginx |
这些命令会显示 Nginx 的运行状态(是否正在运行、进程 ID、启动时间等)以及最近的日志。
3. 测试 Nginx 配置
1 | sudo nginx -t |
这个命令非常重要!它会检查你的 Nginx 配置文件(通常是 /etc/nginx/nginx.conf
或 /etc/nginx/conf.d/
下的文件)的语法是否正确。在每次修改配置文件后,都应该先运行这个命令进行检查,然后再重新加载配置。
如果配置有错误,Nginx 会给出错误提示,并指出错误所在的行号。
4. 重新加载 Nginx 配置
1 | sudo nginx -s reload |
这个命令会平滑地重新加载 Nginx 配置,而不会中断现有的连接。Nginx 会启动新的 worker 进程来处理新的请求,同时让旧的 worker 进程继续处理完已有的连接,直到处理完毕后退出。
5. 查看 Nginx 版本
1 | nginx -v # 显示简要版本信息 |
6. 查看 Nginx 进程
1 | ps aux | grep nginx |
这个命令会列出所有包含 “nginx” 关键字的进程,你可以看到 Nginx 的 master 进程和 worker 进程。
7. 查看 Nginx 日志
Nginx 有两种主要的日志:
- 访问日志 (access log): 记录每个客户端请求的详细信息(IP 地址、时间、请求的 URL、状态码、浏览器信息等)。
- 默认位置通常是
/var/log/nginx/access.log
,但可以在配置文件中自定义。
- 默认位置通常是
- 错误日志 (error log): 记录 Nginx 运行过程中的错误信息,以及一些警告和调试信息。
- 默认位置通常是
/var/log/nginx/error.log
,也可以在配置文件中自定义。
- 默认位置通常是
你可以使用 tail
、less
、cat
等命令查看这些日志:
1 | sudo tail -f /var/log/nginx/access.log # 实时查看访问日志的最新内容 |
8. 指定配置文件启动
1 | sudo nginx -c /path/to/your/nginx.conf # 指定配置文件 |
9. 帮助命令
1 | nginx -h # 或者 nginx -? |
显示 Nginx 的命令行选项帮助信息。
总结和提示
- 使用
sudo
: 大多数 Nginx 命令需要 root 权限才能执行,所以通常要加上sudo
。 systemctl
vsservice
: 根据你的操作系统使用systemctl
或service
命令。systemctl
是较新的系统管理工具,而service
是传统的 SysVinit 工具。- 先测试,再重载: 每次修改 Nginx 配置文件后,务必先使用
nginx -t
测试配置是否正确,然后再使用nginx -s reload
重新加载配置。 - 日志很重要: 经常查看 Nginx 的访问日志和错误日志,可以帮助你了解网站的运行情况,排查问题。