前言
还记得我第一次接触Nginx的时候,完全是一头雾水。满屏幕的配置文件、各种指令,让我望而生畏。折腾了好久才搞明白这个被称为"高性能HTTP和反向代理服务器"的家伙到底是怎么用的。
今天就把我踩过的坑和积累的经验分享给大家,希望能帮助更多的新手快速上手Nginx。不说废话,直接开干!
一、Nginx是什么?为什么要用它?
简单来说,Nginx(发音为"engine x")是一个开源的高性能Web服务器和反向代理服务器。它因其稳定性、丰富的功能、简单的配置和低资源消耗而闻名。
为什么要用Nginx?看看这些应用场景:
- 静态资源服务器:高效地提供HTML、CSS、JavaScript、图片等静态文件
- 反向代理服务器:将客户端请求转发到后端服务器
- 负载均衡:分发请求到多个服务器,提高系统可用性
- API网关:统一管理API请求
- HTTPS支持:轻松配置SSL证书
二、安装Nginx
Ubuntu/Debian系统
# 更新软件包列表
sudo apt update
# 安装Nginx
sudo apt install nginx
# 启动Nginx
sudo systemctl start nginx
# 设置开机自启
sudo systemctl enable nginx
# 查看状态
sudo systemctl status nginx
CentOS/RHEL系统
# 安装EPEL仓库
sudo yum install epel-release
# 安装Nginx
sudo yum install nginx
# 启动Nginx
sudo systemctl start nginx
# 设置开机自启
sudo systemctl enable nginx
# 查看状态
sudo systemctl status nginx
Windows系统
- 访问Nginx官方下载页面
- 下载稳定版本的Windows版本
- 解压到任意目录,如
C:\nginx
- 双击
nginx.exe
启动服务
安装完成后,在浏览器输入http://localhost
或http://服务器IP
,如果看到"Welcome to nginx!"页面,说明安装成功了!
三、Nginx目录结构和配置文件
Nginx的配置文件可能位于不同位置,取决于你的安装方式和操作系统:
- Linux系统通常在:
/etc/nginx/
- Windows系统通常在安装目录下,如:
C:\nginx\conf\
先来看下主要目录和文件:
/etc/nginx/
├── nginx.conf # 主配置文件
├── conf.d/ # 包含其他配置文件的目录
├── sites-available/ # 可用站点配置
├── sites-enabled/ # 已启用站点配置(通常是软链接)
├── modules-available/ # 可用模块
├── modules-enabled/ # 已启用模块
└── mime.types # MIME类型映射
小贴士:刚开始不要被这么多文件吓到,我们主要关注
nginx.conf
和sites-available
目录下的配置文件。
主配置文件结构
Nginx的配置采用简单直观的结构,主要由以下几部分组成:
# 全局块:这部分的设置会影响整个Nginx服务器
user nginx; # 设定Nginx工作进程的用户,说白了就是谁来运行Nginx,权限问题经常在这里栽跟头
worker_processes auto; # 工作进程数量,auto让Nginx自己根据CPU核心数决定,一般够用了
error_log /var/log/nginx/error.log; # 错误日志放哪,出问题可以查看这个文件进行排查错误
pid /run/nginx.pid; # 进程ID存哪,系统用来跟踪Nginx主进程的
# events块:这里控制Nginx如何处理连接,与性能直接挂钩
events {
worker_connections 1024; # 每个工作进程最多能同时处理多少连接,太小了高峰期扛不住,太大了浪费资源
}
# http块:这里是重头戏,几乎所有HTTP相关的设置都在这
http {
include /etc/nginx/mime.types; # 导入文件类型映射表,这样Nginx才知道.jpg文件应该用image/jpeg头发送
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; # 开启零拷贝传输模式,文件传输更快,不懂原理也没关系,开着就对了
tcp_nopush on; # 积攒一些数据再发,避免频繁发小包,省网络资源
tcp_nodelay on; # 不延迟,有数据立马发,和上面有点矛盾但配合更好,小文件传输爽的飞起
# 保持连接的时间,单位秒,太短频繁建连接浪费资源,太长一堆空连接占着茅坑
keepalive_timeout 65;
# 导入其他配置文件,实际工作中多网站管理就靠这个,每个网站一个配置文件,清爽
include /etc/nginx/conf.d/*.conf;
# server块:每个网站一个,这是默认的站点配置
server {
listen 80; # 监听80端口,标准HTTP端口,改了记得防火墙也要改
server_name localhost; # 域名,多域名用空格分隔,这里配localhost意思是本机访问
# location块:处理特定URL请求的规则
location / {
root /usr/share/nginx/html; # 网站文件根目录,首页和静态文件都放这
index index.html index.htm; # 默认首页文件名,按顺序找,找到就用,全找不到就404
}
# 错误页配置,5xx系列错误都显示这个页面
error_page 500 502 503 504 /50x.html;
# 专门处理/50x.html这个特殊请求的location
location = /50x.html {
root /usr/share/nginx/html; # 错误页面的位置,跟网站根目录一样
}
}
}
四、Nginx基本使用
基本操作命令
# 启动Nginx
sudo systemctl start nginx # 系统服务方式
sudo nginx # 直接命令方式
# 停止Nginx
sudo systemctl stop nginx
sudo nginx -s stop
# 重载配置
sudo systemctl reload nginx
sudo nginx -s reload
# 检查配置文件语法
sudo nginx -t
# 查看Nginx状态
sudo systemctl status nginx
曾经踩过的坑:修改配置文件后忘记reload,然后傻傻地不知道为什么修改没生效…所以记住:修改配置后一定要重载配置!
案例1:配置一个简单的静态网站
假设我们有一个静态网站,文件放在/var/www/mysite
目录下。创建一个新的配置文件:
sudo nano /etc/nginx/sites-available/mysite.conf
添加以下内容:
server {
listen 80; # 监听80端口,也就是标准HTTP端口,访问网站时不用加端口号
server_name mysite.com www.mysite.com; # 设置域名,这样输入这两个域名都能访问到这个网站
root /var/www/mysite; # 网站文件根目录,所有HTML、图片等文件都放在这个文件夹下
index index.html; # 默认首页文件名,访问域名根目录时自动加载这个文件
location / {
try_files $uri $uri/ =404; # 处理请求的顺序:先找完整路径文件,再找同名目录,都没有就返回404错误
}
# 设置图片缓存
location ~* \.(jpg|jpeg|png|gif|ico)$ { # 匹配所有图片类型的文件,~*表示不区分大小写
expires 30d; # 缓存30天,这样用户再次访问网站时不用重新下载图片,加载更快
add_header Cache-Control "public, no-transform"; # 允许所有缓存服务器存储,且不要压缩或转换图片
}
# CSS和JS文件缓存
location ~* \.(css|js)$ { # 匹配所有CSS和JS文件
expires 7d; # 缓存7天,比图片短是因为这些文件更新较频繁
add_header Cache-Control "public, no-transform"; # 同样允许公共缓存,保持原始格式
}
}
然后创建软链接启用配置并重载:
sudo ln -s /etc/nginx/sites-available/mysite.conf /etc/nginx/sites-enabled/
sudo nginx -t # 检查配置是否有错误
sudo systemctl reload nginx
案例2:配置反向代理
假设我们有一个Node.js应用运行在3000端口,我们希望通过Nginx代理访问:
server {
listen 80; # 监听80端口,这是HTTP的标准端口
server_name api.mysite.com; # 域名设置,只有访问这个域名的请求才会使用这个配置
location / { # 处理所有路径的请求
proxy_pass http://localhost:3000; # 将请求转发给本地3000端口的服务
proxy_http_version 1.1; # 使用HTTP 1.1协议与后端服务通信
proxy_set_header Upgrade $http_upgrade; # 支持WebSocket协议需要这个,否则聊天室、实时应用等会断连
proxy_set_header Connection 'upgrade'; # 配合上面的Upgrade使用,保持长连接不断开
proxy_set_header Host $host; # 把原始请求的域名发给后端,没这个后端不知道是谁在请求它
proxy_set_header X-Real-IP $remote_addr; # 告诉后端真实的客户IP,否则后端看到的都是Nginx的IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 完整的请求路径,包含多层代理信息
proxy_set_header X-Forwarded-Proto $scheme; # 告诉后端用的是什么协议(http还是https),安全检查需要用
proxy_cache_bypass $http_upgrade; # 有特殊请求头时绕过缓存,确保实时数据不会被缓存误事
}
}
这个配置做了一件核心的事:当用户访问api.mysite.com时,Nginx不会自己处理请求,而是把请求转发给本地3000端口运行的服务(可能是Node.js、Python等写的API服务)。
转发过程中保留了原始请求的所有重要信息(IP、域名、协议等),并支持WebSocket等高级功能。这就是"反向代理"——用户感觉是在访问api.mysite.com,实际上请求被偷偷转给了内部服务处理。
这样做有很多好处:
- 保护内部服务不直接暴露
- 可以在前面做SSL加密、流量控制
- 可以把多个内部服务整合成一个对外的地址
- 方便随时切换或升级后端服务
- 这是现代Web架构中最常见的配置之一,几乎所有专业网站都会用类似的方式部署。
实战经验:以前配置反向代理时,遇到过前端页面路径错乱的问题,检查了很久才发现是没有设置
proxy_set_header Host $host;
这个头信息导致的。
案例3:负载均衡配置
假设我们有多个应用实例需要进行负载均衡:
# 定义上游服务器组
upstream backend_servers {
server 192.168.1.101:8080;
server 192.168.1.102:8080;
server 192.168.1.103:8080;
}
server {
listen 80;
server_name app.mysite.com;
location / {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Nginx默认使用轮询算法进行负载均衡,还支持其他几种算法:
upstream backend_servers {
# 加权轮询
server 192.168.1.101:8080 weight=3;
server 192.168.1.102:8080 weight=1;
# 最少连接
# least_conn;
# IP哈希(相同IP的请求发送到同一服务器)
# ip_hash;
# 标记服务器为备份,只有主服务器不可用时才使用
# server 192.168.1.103:8080 backup;
}
五、HTTPS配置
现在几乎所有网站都需要HTTPS,配置其实很简单:
server {
listen 80;
server_name secure.mysite.com;
# 将HTTP请求重定向到HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name secure.mysite.com;
# SSL证书配置
ssl_certificate /etc/letsencrypt/live/secure.mysite.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/secure.mysite.com/privkey.pem;
# 优化SSL设置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
# HSTS(HTTP严格传输安全)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 其他安全相关头信息
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
location / {
root /var/www/secure-site;
index index.html;
}
}
实用建议:可以使用Let’s Encrypt免费申请SSL证书,配合certbot工具可以自动更新证书。
六、常见问题及解决方案
1. 403 Forbidden错误
最常见的原因是Nginx进程没有访问文件的权限:
# 检查Nginx运行用户
grep user /etc/nginx/nginx.conf
# 调整目录权限
sudo chmod 755 /var/www/mysite
sudo chown -R nginx:nginx /var/www/mysite # 根据实际Nginx用户调整
2. 502 Bad Gateway错误
通常是因为后端服务未运行或无法连接:
# 检查后端服务是否运行
ps aux | grep node
# 检查网络连接
sudo netstat -tulpn | grep 3000
# 检查Nginx错误日志
sudo tail -f /var/log/nginx/error.log
3. 大文件上传限制
默认Nginx限制上传文件大小为1MB,修改配置:
http {
# 在http块中添加
client_max_body_size 20M;
}
server {
# 或在特定server块中添加
client_max_body_size 20M;
}
4. 启用Gzip压缩
减少传输数据大小,提高页面加载速度:
http {
# 开启gzip压缩
gzip on;
# 压缩级别,1-9,数字越大压缩率越高,CPU占用也越高
gzip_comp_level 5;
# 压缩的最小文件大小
gzip_min_length 256;
# 压缩http协议版本
gzip_http_version 1.1;
# 压缩类型
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# 增加响应头Vary: Accept-Encoding
gzip_vary on;
# 禁用IE6的gzip
gzip_disable "MSIE [1-6]\.";
}
七、实际案例:前后端分离项目配置
假设我们有一个典型的前后端分离项目,前端是Vue.js应用,后端是Node.js API:
server {
listen 80;
server_name myproject.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name myproject.com;
# SSL配置省略...
# 前端静态文件
location / {
root /var/www/frontend/dist;
index index.html;
# 处理单页应用路由
try_files $uri $uri/ /index.html;
}
# API请求转发
location /api/ {
proxy_pass http://localhost:3000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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_cache_bypass $http_upgrade;
}
# 静态资源缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
root /var/www/frontend/dist;
expires 7d;
add_header Cache-Control "public, no-transform";
}
}
实战心得:处理单页应用路由一定要加
try_files $uri $uri/ /index.html;
这行配置,否则刷新页面会404。这个问题困扰我半天才解决。
八、Nginx安全加固
1. 隐藏版本信息
http {
server_tokens off;
}
2. 限制连接数和请求率
http {
# 限制每个IP的连接数
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
# 限制每个IP的请求率
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=10r/s;
server {
# 应用连接限制
limit_conn conn_limit_per_ip 10;
# 应用请求限制
limit_req zone=req_limit_per_ip burst=20 nodelay;
}
}
3. 配置防盗链
location ~* \.(jpg|jpeg|png|gif)$ {
valid_referers none blocked server_names *.mysite.com mysite.com;
if ($invalid_referer) {
return 403;
}
}
九、进阶技巧
1. 配置浏览器缓存策略
# 静态资源强缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 7d;
add_header Cache-Control "public, max-age=604800, immutable";
}
# HTML文件不缓存
location ~* \.html$ {
expires -1;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate";
}
2. 开启HTTP/2支持
server {
listen 443 ssl http2;
server_name mysite.com;
# SSL配置省略...
}
3. 使用Nginx实现简单的URL重写
location /old-page/ {
rewrite ^/old-page/(.*) /new-page/$1 permanent;
}
# 带查询参数的重写
location /search {
rewrite ^/search/(.*)$ /find?query=$1 last;
}
十、总结
通过这篇文章,我们从安装、基础配置到实际案例,全面了解了Nginx的主要功能和配置方法。希望本文能为你扫除学习路上的障碍。
随着你对Nginx的逐渐深入,你会发现它的强大远不止于此,还有很多高级功能等待你去探索。比如:
- Nginx模块开发
- 动态模块加载
- OpenResty和Lua脚本
- 更复杂的负载均衡算法
- 流量控制和访问控制
记住,最好的学习方法就是实践。从一个简单的静态网站开始,慢慢尝试更复杂的配置,相信你很快就能成为Nginx高手!如果在实践中遇到问题,可以查阅Nginx官方文档或者在技术社区提问。