Nginx从入门到实战:小白也能轻松驾驭的Web服务器

前言

还记得我第一次接触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系统

  1. 访问Nginx官方下载页面
  2. 下载稳定版本的Windows版本
  3. 解压到任意目录,如C:\nginx
  4. 双击nginx.exe启动服务

安装完成后,在浏览器输入http://localhosthttp://服务器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.confsites-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,实际上请求被偷偷转给了内部服务处理。
这样做有很多好处:

  1. 保护内部服务不直接暴露
  2. 可以在前面做SSL加密、流量控制
  3. 可以把多个内部服务整合成一个对外的地址
  4. 方便随时切换或升级后端服务
  5. 这是现代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官方文档或者在技术社区提问。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Luck_ff0810

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值