尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

【Linux从入门到精通】第32篇:Nginx入门——高性能Web服务器搭建

【Linux从入门到精通】第32篇:Nginx入门——高性能Web服务器搭建 目录一、引言Nginx为什么这么流行二、安装与基础管理2.1 安装Nginx2.2 启动、停止、重载2.3 配置文件结构三、虚拟主机一台服务器跑多个网站3.1 什么是虚拟主机3.2 实战配置两个虚拟主机3.3 server_name的通配符匹配四、反向代理Nginx的第二重身份4.1 什么是反向代理4.2 实战用Nginx反向代理Node.js应用五、nginx -s reload平滑重启的秘密5.1 为什么需要平滑重启5.2 reload的完整流程5.3 reload vs restart vs stop5.4 可能遇到的问题六、本篇小结动手练习排错小技巧七、下篇预告一、引言Nginx为什么这么流行如果你去问后端开发或运维工程师“用什么部署Web应用”答案十有八九是Nginx。它凭什么成为事实标准几个关键数字可以说明问题C10k问题的终结者Nginx采用事件驱动架构一台服务器就能轻松处理上万个并发连接而传统Apache在几百个连接时已经吃力内存占用极低空闲状态下仅占用几MB内存即使在高并发场景下也远低于同类产品功能三合一既是Web服务器托管静态文件、又是反向代理转发请求到后端、还是负载均衡器分发流量到多台服务器简单说一个软件解决三个问题而且全部免费开源。二、安装与基础管理2.1 安装NginxUbuntu/Debian系统默认仓库已经包含Nginx一条命令即可安装bashsudo apt update sudo apt install nginx -yCentOS/RHEL需要先启用EPEL仓库bashsudo dnf install epel-release -y # CentOS 8 / Fedora sudo dnf install nginx -y安装完成后验证版本bashnginx -v2.2 启动、停止、重载Nginx作为systemd服务运行用我们第15篇学过的systemctl管理bashsudo systemctl start nginx # 启动 sudo systemctl stop nginx # 停止 sudo systemctl restart nginx # 重启会中断服务 sudo systemctl reload nginx # 平滑重载不中断服务 sudo systemctl status nginx # 查看状态 sudo systemctl enable nginx # 开机自启2.3 配置文件结构Nginx配置文件的默认位置是/etc/nginx/核心文件是nginx.conf。现代Nginx采用模块化设计主配置文件通过include引入子目录中的配置片段bash/etc/nginx/ ├── nginx.conf # 主配置文件 ├── sites-available/ # 所有可用的站点配置 │ ├── default │ └── example.com └── sites-enabled/ # 已启用的站点软链接到sites-available └── example.com - ../sites-available/example.com约定把每个站点的配置单独放在sites-available/下需要启用时创建一个软链接到sites-enabled/。这样需要下线某个站点时只删除软链接即可原配置文件保留备用。每次修改配置后先测试语法再重载bashsudo nginx -t # 测试配置语法 sudo systemctl reload nginx # 确认无误后平滑重载三、虚拟主机一台服务器跑多个网站3.1 什么是虚拟主机在Nginx出现之前一个域名对应一个IP、一台服务器只能跑一个网站。Nginx的虚拟主机Server Block打破了这种绑定一台服务器可以托管多个域名每个域名对应不同的网站目录。Nginx通过server_name指令来判断当前请求的域名然后匹配到对应的server块处理。3.2 实战配置两个虚拟主机假设你有一台服务器需要托管两个网站blog.example.com对应博客shop.example.com对应商城。第一步创建网站目录和首页bashsudo mkdir -p /var/www/blog.example.com sudo mkdir -p /var/www/shop.example.com # 创建示例首页 echo h1Welcome to Blog/h1 | sudo tee /var/www/blog.example.com/index.html echo h1Welcome to Shop/h1 | sudo tee /var/www/shop.example.com/index.html # 设置权限 sudo chown -R www-data:www-data /var/www/blog.example.com sudo chown -R www-data:www-data /var/www/shop.example.com第二步创建虚拟主机配置文件/etc/nginx/sites-available/blog.example.comnginxserver { listen 80; server_name blog.example.com; root /var/www/blog.example.com; index index.html; location / { try_files $uri $uri/ 404; } }/etc/nginx/sites-available/shop.example.comnginxserver { listen 80; server_name shop.example.com; root /var/www/shop.example.com; index index.html; location / { try_files $uri $uri/ 404; } }关键指令解释listen 80监听HTTP的默认80端口server_name blog.example.com这个server块只处理域名匹配的请求root /var/www/blog.example.com网站文件的根目录index index.html默认首页文件名try_files $uri $uri/ 404先尝试匹配请求的文件路径找不到返回404第三步启用站点并重载bash# 创建软链接启用站点 sudo ln -s /etc/nginx/sites-available/blog.example.com /etc/nginx/sites-enabled/ sudo ln -s /etc/nginx/sites-available/shop.example.com /etc/nginx/sites-enabled/ # 测试语法 sudo nginx -t # 平滑重载 sudo systemctl reload nginx现在访问http://blog.example.com和http://shop.example.com会看到不同的网站内容。3.3 server_name的通配符匹配server_name支持通配符这在管理大量子域名时非常方便nginx# 匹配所有 example.com 的子域名 server { listen 80; server_name *.example.com; ... } # 精确匹配多个域名 server { listen 80; server_name example.com www.example.com; ... }匹配优先级精确名称 *开头的通配符 *结尾的通配符 正则表达式。四、反向代理Nginx的第二重身份4.1 什么是反向代理先理解正向代理你的浏览器 → 代理服务器 → 目标网站。你主动找代理让它帮你访问外界。反向代理正好反过来用户的请求 → Nginx → 内部应用服务器。用户根本不知道后面还有谁他只和Nginx对话。反向代理的好处隐藏后端内部应用服务器不需要暴露公网IP统一入口多个应用Node.js/Python/Go通过同一个80端口对外服务SSL终结在Nginx处理HTTPS内部服务器只需处理HTTP4.2 实战用Nginx反向代理Node.js应用假设你有一个Node.js应用运行在本地3000端口想让外部用户通过app.example.com访问而用户不知道3000端口的存在。nginxserver { listen 80; server_name app.example.com; location / { proxy_pass http://127.0.0.1:3000; 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_pass http://127.0.0.1:3000核心指令——把匹配到的请求全部转发到本机的3000端口proxy_set_header Host $host把原始请求的域名传给后端否则后端收到的Host是127.0.0.1proxy_set_header X-Real-IP $remote_addr把用户的真实IP传给后端否则后端只能看到127.0.0.1proxy_set_header X-Forwarded-For记录完整的代理链用户的真实IP会追加到这个头部proxy_set_header X-Forwarded-Proto $scheme告诉后端原始请求是HTTP还是HTTPSproxy_pass的斜杠陷阱proxy_pass中地址末尾有没有斜杠行为截然不同配置请求/api/users转发地址proxy_pass http://backend//api/usershttp://backend/usersproxy_pass http://backend/api/usershttp://backend/api/users加上末尾斜杠location中匹配到的路径会被移除不加斜杠完整URI原样追加。这个细节经常让人踩坑。五、nginx -s reload平滑重启的秘密5.1 为什么需要平滑重启传统的systemctl restart nginx会先停止所有worker进程再启动新的。这会导致一个短暂的“真空期”——此时Nginx无法处理任何请求。对于生产环境哪怕中断0.1秒都可能导致部分用户请求失败。nginx -s reload就是为解决这个问题设计的。5.2 reload的完整流程nginx -s reload向master进程发送SIGHUP信号master进程随后执行以下步骤第一步检查配置语法master进程首先对新配置文件做语法检查。如果检查失败继续使用旧配置运行服务不受任何影响。第二步打开新的监听端口如果新配置中增加了之前没有的监听端口比如新增了443的SSL配置master进程会打开这些新端口。所有worker进程作为master的子进程会继承这些端口。第三步启动新worker进程master用新配置启动一批新的worker进程。注意此时新老worker同时存在新连接由新worker处理老worker继续处理已建立的请求。第四步通知老worker优雅退出master向老worker发送SIGQUIT信号。老worker收到后关闭监听的端口句柄不再接收新连接处理完当前正在进行的请求主动退出示意图textreload前[老worker-1] [老worker-2] [老worker-3] [老worker-4] ↓ master收到reload信号 ↓ 过渡期 [老worker-1] [老worker-2] [老worker-3] [老worker-4] [新worker-1] [新worker-2] [新worker-3] [新worker-4] ↓ 老worker处理完已有请求后退出 ↓ reload后[新worker-1] [新worker-2] [新worker-3] [新worker-4]5.3 reload vs restart vs stop命令底层信号行为是否中断服务nginx -s reloadSIGHUP新配置启动新worker老worker优雅退出否nginx -s stopSIGTERM立即停止所有worker是nginx -s quitSIGQUIT优雅停止处理完当前请求后退出只处理完已有请求systemctl restart先stop再start完全停止再启动是日常修改配置后永远优先使用nginx -s reload或systemctl reload nginx。5.4 可能遇到的问题老worker长时间不退出某些请求可能处理得很慢如大文件上传导致老worker一直等待。新版本Nginx提供了worker_shutdown_timeout指令可以设置最长等待时间超时后强制退出。六、本篇小结安装与管理bashsudo apt install nginx sudo nginx -t # 测试配置 sudo systemctl reload nginx # 平滑重载虚拟主机核心配置nginxserver { listen 80; server_name example.com; # 域名匹配[citation:5] root /var/www/example.com; # 网站根目录 index index.html; # 默认首页 }反向代理核心配置nginxlocation / { proxy_pass http://127.0.0.1:3000; # 转发目标 proxy_set_header Host $host; # 传递域名 proxy_set_header X-Real-IP $remote_addr; # 传递真实IP }平滑重启原理master进程收到reload信号 → 检查语法 → 开新端口 → 启新worker → 老worker优雅退出 → 全程不中断服务动手练习bash# 1. 安装并启动Nginx sudo apt update sudo apt install nginx -y sudo systemctl start nginx # 2. 查看默认页面本机访问 curl http://localhost # 3. 创建自己的虚拟主机配置 sudo mkdir -p /var/www/test.local echo My Test Site | sudo tee /var/www/test.local/index.html sudo vim /etc/nginx/sites-available/test.local # 填入server块配置listen 80; server_name test.local; root /var/www/test.local sudo ln -s /etc/nginx/sites-available/test.local /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx # 4. 本机测试修改hosts或直接用curl指定Host头 curl -H Host: test.local http://localhost # 5. 观察worker进程变化 ps aux | grep nginx # 修改个配置执行reload再次查看worker进程PID应该变化排错小技巧502 Bad Gateway后端服务挂了或proxy_pass地址写错了检查后端是否在运行、端口是否匹配。404 Not Foundroot路径不对或文件不存在确认网站目录下有首页文件。403 Forbidden权限问题chown -R www-data:www-data改属主。七、下篇预告Nginx常常搭配数据库一起工作。下一篇我们将进入数据库MySQL/MariaDB的安装与基础调优学习数据库的安全初始化流程、创建用户和授权、以及my.cnf中几个必须调整的内存参数。这是完整Web应用栈的第二块基石。延伸思考nginx -s reload为什么比restart更优雅打个比方restart相当于饭店关门装修——新客旧客全请出去。reload相当于厨师换菜单——已经在用餐的顾客不受影响新来的顾客按新菜单点菜。这就是生产环境的“零停机更新”。
返回列表