ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Mac下Nginx部署前后端分离项目实战:以黑马苍穹外卖为例

Mac下Nginx部署前后端分离项目实战:以黑马苍穹外卖为例 开头最近在Mac上帮朋友部署黑马苍穹外卖这个项目时发现很多人在nginx这一步卡住了。明明后端服务都启动正常前端的dist包也打包好了但页面就是出不来或者接口请求报错。其实这些问题的根源多半是对nginx在这个前后端分离项目里扮演的角色没理解透。这篇文章我会围绕Mac环境下部署nginx结合黑马苍穹外卖的实际场景讲清楚nginx到底做了什么、为什么需要它、配置文件的每一行是什么意思、以及我在实际部署中踩过的坑和排查思路。不管你是刚学完Spring Boot的初学者还是准备把项目部署到服务器上的求职者这套流程都能直接照着操作。先交代一下背景。黑马苍穹外卖是一个典型的前后端分离微服务项目前端是Vue构建的静态页面后端由Gateway网关、Nacos注册中心、多个微服务模块组成。nginx在这里干三件事托管前端静态资源、反向代理后端接口、负载均衡多个服务实例。理解了这三件事下面的所有配置你就都能看懂了。1. 整体架构与Nginx选型思路1.1 苍穹外卖项目的部署链路在动手配置nginx之前我建议你先在脑子里把这个项目的完整请求链路捋一遍。苍穹外卖的典型请求流程是这样的用户在浏览器输入地址请求先到达nginx。nginx看到请求路径里带/api/就知道这是要访问后端接口于是把请求转发给后端的网关服务Gateway网关再根据路由规则把请求分发到具体的微服务模块比如用户服务、订单服务、商品服务等。如果请求路径不带/api/nginx就直接去磁盘上找前端打包好的静态文件返回给浏览器。这一步想清楚了nginx配置里最关键的两个指令就呼之欲出了root 指令负责告诉nginx前端文件放在哪里proxy_pass 指令负责告诉nginx后端接口要转发到什么地址。这两个指令就是整个部署的骨架其余都是在这个骨架上做细节补充。1.2 为什么非要nginx不用Spring Boot直接跑前端很多人第一次部署这个项目都会有一个疑问前端不是能打包成静态文件吗我直接用Vite或者Webpack的dev server跑起来不也能看页面吗为什么非要nginx这里涉及一个前后端分离项目里非常现实的问题跨域。如果你用Vite的dev server启动前端默认端口5173然后用fetch请求后端接口比如localhost:8080浏览器会因为跨域策略直接拦截请求。解决跨域的办法有很多比如在后端加CORS配置、在前端配代理但最正统的生产环境方案就是nginx反向代理。nginx把前端静态页面和后端接口放在同一个域名、同一个端口下通过路径前缀区分不同来源的请求。浏览器看到的请求是同源的自然就不存在跨域问题了。这是生产环境的标准做法也是苍穹外卖项目里nginx存在的真正意义。所以不要在这里省事好好把nginx配起来这才是接近真实工作的方式。1.3 Mac上部署nginx的三种方案对比Mac上装nginx主流有三条路Homebrew安装、源码编译安装、直接下载nginx.org提供的macOS二进制包。我个人最推荐的是Homebrew安装。原因很简单Mac的/usr/local目录或者/opt/homebrew目录常有权限限制源码编译安装时你得手动处理路径和权限问题一不小心就把系统搞乱。Homebrew会帮你把所有文件放到它自己的目录里配置文件、日志文件、临时文件都分工明确后续重启、自启动、卸载也方便。源码编译安装适合有定制化需求的场景比如你需要编译第三方模块或者要打特定的补丁。但在Mac上日常部署苍穹外卖项目完全没必要走到这一步。二进制包的问题是更新麻烦且有时会依赖系统的某些第三方库版本对不上也会出问题。下面的实操步骤我统一以Homebrew方式为准来讲。如果你还没装Homebrew也先花两分钟装一下后面会省很多事。2. 环境准备Mac上安装Nginx的前置工作2.1 确认Mac芯片架构与路径差异Mac的芯片架构会影响Homebrew的安装路径进而影响nginx配置文件的位置这一步建议先确认清楚。在终端执行 uname -m输出是arm64说明是M系列芯片M1、M2、M3等Homebrew默认装在/opt/homebrew目录下。输出是x86_64说明是Intel芯片Homebrew默认装在/usr/local目录下。这个差异很重要因为后续你找nginx.conf文件和日志文件都要基于这个路径去找。以M系列芯片的Mac为例nginx安装后的关键路径如下nginx可执行文件/opt/homebrew/bin/nginx配置文件目录/opt/homebrew/etc/nginx/主配置文件/opt/homebrew/etc/nginx/nginx.conf日志目录/opt/homebrew/var/log/nginx/默认网页根目录/opt/homebrew/var/www/记住这几个路径后面你用nginx -t检查配置、用nginx -s reload重载配置、查看错误日志都离不开它们。2.2 安装Homebrew及常见报错处理如果你还没有Homebrew先安装它。官方安装命令如下/bin/bash -c $(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)但这条命令在实际执行时经常卡在下载阶段。原因不用多说了网络环境大家都懂。我的建议是安装过程中如果长时间停留在Downloading或Updating可以直接按CtrlC中断然后用国内镜像源重新安装。比如使用清华大学的Homebrew镜像源操作方式是这样的export HOMEBREW_BREW_GIT_REMOTEhttps://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git export HOMEBREW_CORE_GIT_REMOTEhttps://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git export HOMEBREW_BOTTLE_DOMAINhttps://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles设置完这3个环境变量后再执行安装命令顺利程度会明显提升。这里有个细节是M系列芯片的Mac还需要根据Homebrew的提示把/opt/homebrew/bin加入PATH环境变量。你在终端执行echo $PATH检查一下是否包含这个路径没有的话就编辑~/.zshrc文件在末尾加上一行export PATH/opt/homebrew/bin:$PATH然后执行source ~/.zshrc使配置生效。2.3 安装JDK8与Maven苍穹外卖的环境基础这里多说一步因为很多人在Mac上部署苍穹外卖时栽在JDK版本上。苍穹外卖后端项目要求JDK8但新版MacOS上只装JDK17或更高版本的话项目会直接编译报错。检查JDK版本执行java -version输出中包含1.8字样的就是JDK8。如果没有先通过Homebrew安装brew install --cask temurin8安装完确认路径然后同样在~/.zshrc里配置JAVA_HOMEexport JAVA_HOME/Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home export PATH$JAVA_HOME/bin:$PATHMaven也是一样brew install maven装的是最新版如果和JDK8配合不好建议直接用压缩包方式装一个Maven 3.6.3左右的版本然后配置MAVEN_HOME。这一步虽然在nginx部署正文之外但确实是我在Mac上跑苍穹外卖时最先遇到的问题顺手写出来帮你避个雷。2.4 后端服务的启动顺序nginx是最后接入的前面的准备工作要保证后端服务正常启动。苍穹外卖的启动顺序很重要顺序错了会导致服务注册失败或者接口不通。建议按下面的顺序启动启动MySQL数据库启动Redis数据库启动Nacos注册中心进入bin目录执行sh startup.sh -m standalone启动Gateway网关服务默认端口8080启动用户端api服务、管理端api服务等微服务模块你可以用一个简单的方式确认服务是否就绪浏览器访问http://localhost:8080如果返回的是网关的提示信息或者404页面说明网关活着就表示后端链路基本正常。如果这里都不通后面nginx配置得再好也没用。3. 安装与启动Nginx从Homebrew到配置文件解读3.1 安装Nginx并验证版本现在正式安装nginx。在终端执行brew install nginx安装完成后执行nginx -v验证是否装好。能看到nginx version: nginx/1.27.x这样的输出就说明安装成功。Homebrew默认安装的已经是比较新的稳定版不需要额外指定版本。启动nginx有两种方式这里要区分清楚方式一手动启动。执行nginx进程在前台还是后台取决于是否加-daemon参数默认是后台运行。这种方式的缺点是Mac重启后nginx不会自动启动。方式二注册为系统服务通过brew services管理。执行brew services start nginx这样Mac开机后nginx会自动启动。对于需要长期跑项目的开发者来说我推荐用方式二省心。启动后浏览器访问http://localhost看到Welcome to nginx!页面就说明安装成功。3.2 理解nginx.conf的目录结构nginx安装完成后先别急着改配置花几分钟看一下nginx.conf的整体结构。用文本编辑器打开/opt/homebrew/etc/nginx/nginx.conf你会看到这个文件其实是一层套一层搭起来的worker_processes 指令控制nginx进程数量events块是连接相关的全局配置http块内部最常见的就是server块一个server块就代表一个虚拟主机。http块末尾通常会有一行include /opt/homebrew/etc/nginx/servers/*;意思是加载servers目录下的所有配置文件。这种分层结构的优势在维护多个项目时特别明显。比如你之后要部署苍穹外卖的前台、后台管理端还想同时部署一个个人博客站点你不需要把所有配置都堆在nginx.conf一个文件里而是可以为每个项目单独写一个conf文件扔进servers目录nginx启动时会自动加载。对于苍穹外卖项目我们后续就在servers目录下新建一个sky.conf单独存放这个项目的所有配置。这样主配置文件保持干净项目配置也方便迁移和备份。3.3 编译安装方案的简要对比这里再补充说一下源码编译安装虽然我不推荐Mac上这么干但如果你确实有定制需求可以参考下面的思路。源码编译安装nginx一般分三步下载nginx源码包、解压、configure make make install。关键点在于configure时需要显式指定你要的模块以及安装路径。比如要支持SSL就得加上--with-http_ssl_module。这种方式的灵活性最高但带来的问题是升级和卸载都比较麻烦对Mac用户来说性价比不高。如果你将来在Linux服务器上部署源码编译则更常见因为服务器环境更可控。但在Mac上做日常开发调试Homebrew方式明显更顺手。4. 苍穹外卖Nginx配置实操从静态页面到反向代理4.1 部署前端静态资源苍穹外卖项目一般包含两个前端用户端sky-take-out-front和管理后台sky-take-out-admin。我们用对应的前端构建命令通常是npm run build打包后会生成dist目录。我的习惯是把两个前端dist目录复制到统一的项目部署目录下比如~/Projects/sky-deploy/下。目录结构如下sky-deploy/ ├── sky-front/ # 用户端前端dist内容 └── sky-admin/ # 管理后台dist内容复制完成后关键一步是给目录设置权限。nginx是独立进程它的访问权限依赖于对目录是否有进入权限x和读取权限r。我在Mac上遇到过403多半就是目录权限不对。建议在终端执行chmod 755 ~/Projects chmod -R 755 ~/Projects/sky-deploy这一步做完再改nginx配置就能避免不少权限坑。4.2 完整配置示例与关键项讲解下面是我在Mac上为苍穹外卖项目准备的nginx配置放在/opt/homebrew/etc/nginx/servers/sky.conf里server { listen 80; server_name localhost; # 用户端前端静态资源 location / { root /Users/你的用户名/Projects/sky-deploy/sky-front; index index.html; try_files $uri $uri/ /index.html; } # 管理后台前端静态资源 location /admin/ { alias /Users/你的用户名/Projects/sky-deploy/sky-admin/; index index.html; try_files $uri $uri/ /admin/index.html; } # 后端接口反向代理 location /api/ { proxy_pass http://localhost:8080; 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; } }逐个讲一下关键配置项的含义和你可能遇到的问题。location / 匹配所有不满足其他location的请求这里指向用户端前端页面。try_files $uri $uri/ /index.html; 是前端路由history模式必需的配置。Vue Router默认使用history模式刷新页面时浏览器会请求一个真实不存在的路径nginx这里通过try_files把这类请求全部回退到index.html交由前端路由接管避免刷新页面后出现404。location /admin/ 这里使用的是alias而不是root两者区别很关键。root会把location后面的路径追加到根路径后面而alias则是将请求路径直接映射到指定目录。如果用root来配管理后台nginx实际找的路径会变成/Users/你的用户名/Projects/sky-deploy/sky-front/admin/这明显不对。用alias之后nginx访问/admin/xxx的时候实际去的是/Users/你的用户名/Projects/sky-deploy/sky-admin/xxx这才是我们想要的效果。这个区别是我踩过坑之后才彻底搞明白的现在分享给你。location /api/ 的proxy_pass就是反向代理的核心了。所有以/api/开头的请求都会被转发到http://localhost:8080。为什么是8080因为苍穹外卖的Gateway网关默认端口就是8080。如果你在项目的application.yml里改过端口这里要对应修改。proxy_set_header里的几个Header比较常见Host和X-Forwarded开头的都是为了把客户端原始请求信息透传给后端服务保证后端能正确获取到真实IP和域名尤其在后续用Nacos做微服务调用时这些Header信息会被用到。4.3 多项目部署一台Mac跑多个前端服务上面的配置已经演示了怎么在一个nginx实例里同时托管用户端和管理后台。如果你还想在Mac上同时运行其他项目完全可以继续在servers目录下新建配置文件用不同端口区分。举个例子再新建一个文件myblog.conf监听8081端口把博客前端指向另一个dist目录配置逻辑完全一样server { listen 8081; server_name localhost; location / { root /Users/你的用户名/Projects/my-blog/dist; index index.html; try_files $uri $uri/ /index.html; } }这种做法本质上就是nginx的虚拟主机特性。你在同一台Mac上用不同的端口或者不同的域名就能同时跑起多个互不干扰的Web服务。对于前端开发者来说这是我推荐的“多项目本地联调”方案比频繁切换启动端口要顺手得多。4.4 配置语法检查与重载配置文件写好后一定先做语法检查别直接重启服务。在终端执行nginx -t如果输出syntax is ok和test is successful说明配置没问题。然后执行nginx -s reloadnginx会平滑重载配置不会中断当前正在进行的请求。之后再用浏览器访问http://localhost页面应该能正常显示了。这里有个容易忽略的点修改配置后一定要reload只修改文件不reload是不会生效的。如果你改了好几遍配置页面始终没变先检查这一步。4.5 验证整个链路的连通性配置生效后打开浏览器开发者工具F12的Network面板刷新页面观察请求列表。最关键的是看两类请求一类是静态资源请求应该返回200并且状态是from disk cache或者from memory cache另一类是接口请求路径应该以/api/开头返回200。如果接口请求状态是502基本可以断定是后端网关服务没启动或者proxy_pass指向的地址有误。如果静态资源404优先检查root或alias路径是否正确。如果页面能出来但样式错乱检查静态资源的Content-Type响应头是不是text/css有时候权限或者路径不对会导致nginx用错误的方式返回文件。5. 常见问题与排查技巧实录5.1 我在Mac上踩过的6个高频坑部署过程中我踩过不少坑有些错误信息在网上搜半天都不一定能直接搜到这里整理成表格方便你对照排查。问题现象可能原因解决办法nginx -t报错nginx: [emerg] bind() to 0.0.0.0:80 failed (48: Address already in use)80端口被占用lsof -i :80查看占用进程杀掉或者改nginx监听端口浏览器访问页面404root路径配错检查root后面必须是dist目录的绝对路径并用ls验证目录存在前端静态资源403 Forbiddendist目录没有读取权限把dist所在目录权限设置为755或者chmod -R 755 dist接口请求失败Network显示502 Bad Gateway后端Gateway服务没启动或proxy_pass地址错误确认网关服务端口、确认proxy_pass的地址和端口修改配置文件后不生效忘了reload执行nginx -t检查后nginx -s reloadbrew services start nginx后页面打不开nginx服务其实没起来执行brew services list查看状态再查看/opt/homebrew/var/log/nginx/error.log这些坑里80端口被占用是最常见的。尤其在Mac上系统自带的Apache也会占用80端口还有AirPlay接收器也会监听80和443端口。我在macOS上就遇到过一次AirPlay接收器占用了80端口nginx死活起不来最后在系统设置里把“隔空播放接收器”关掉才解决。这种问题很隐蔽如果你排查其他的都没效果可以把系统层面的端口占用因素也考虑进去。5.2 日志排查的正确姿势nginx的日志是排查问题的第一手资料比任何猜测都有用。Mac上通过Homebrew安装的nginx日志默认在/opt/homebrew/var/log/nginx/目录下Intel Mac是/usr/local/var/log/nginx/。error.log记录的是错误信息比如配置错误、端口冲突、权限问题都会在这里留下痕迹。access.log记录的是所有访问请求包括请求路径、状态码、响应时间通过它可以看到哪些请求打到了nginx哪些没打到。处理问题的时候我习惯先tail -f error.log然后重新触发一次请求观察新增的日志记录。比如出现connect() failed while connecting to upstream就说明nginx连接不上后端服务优先检查后端服务是否启动出现Permission denied就优先检查文件权限。只要看懂这两类报错大部分问题就有一半的解决思路了。5.3 一个真实的排查案例403 Forbidden我在部署苍穹外卖前端页面时遇到过这样的情况nginx -t通过了端口也通了但浏览器访问一直403。当时第一反应是看日志error.log里显示directory index of /Users/xxx/Projects/sky-deploy/sky-front/ is forbidden。看到这行日志我就有数了。dist目录存在但nginx没有读取权限原因是dist目录所在的父级目录权限不够nginx进程无法进入。解决方案是给目录加上执行和读取权限chmod 755 /Users/xxx/Projects改完权限再刷新页面直接就能出来了。这个案例说明Mac上部署nginx时权限是最容易被忽略的一环。部署完先在终端执行ls -l核对该目录的权限通常能省去很多折腾。5.4 扩展nginx可视化配置工具值得用吗聊到nginx配置顺便提一下nginx可视化配置工具。现在网上有不少nginx Web管理面板可以在浏览器界面里点选配置自动生成nginx.conf。我的看法是作为新手学习可以用可视化工具快速生成一份基础配置然后对照界面上的选项去看生成的配置文件这样能帮助理解配置项。但真正生产环境或者正式项目里我不建议依赖这些工具。原因一是可视化工具生成的配置往往偏通用缺少针对具体项目的优化二是配置文件的版本管理、代码审查在纯文本模式下才能实现可视化工具在这块天然劣势。你最终还是要能直接读懂和修改nginx.conf这是基本功。6. 从Mac到云服务器部署思路的平移6.1 服务器部署时的差异点当你在Mac上已经把苍穹外卖的nginx部署捋顺后后面要部署到云服务器比如CentOS、Ubuntu时整体思路可以平移但有几个差异点要注意。第一是安装方式。服务器上一般用apt install nginx或yum install nginx和Mac上用Homebrew不同但核心配置语法完全一致。第二是路径。服务器上的nginx.conf默认在/etc/nginx/nginx.confdist目录要放到服务器的项目目录比如/var/www/sky-front。第三是防火墙。云服务器需要同时在系统防火墙和云控制台的安全组里放行80端口否则外部访问不到。配置文件本身的内容绝大部分可以直接复用。这就是为什么我前面强调要理解配置语义而不是背诵配置内容——你换一台机器配置文件的逻辑不变变的只是路径和安装方式。6.2 模块化配置的小技巧最后分享一个维护多个项目时的技巧。我会在nginx配置目录下为每个项目单独创建一个conf文件比如sky.conf、sky-admin.conf而不是堆在一个文件里。这样每个项目的配置互相独立改一个不影响另一个出了问题也容易定位。对于Mac上Homebrew安装的nginx这个目录就是/opt/homebrew/etc/nginx/servers/。主配置文件nginx.conf里已经通过include指令加载了这个目录下的所有conf文件所以你只需要在这里新建文件然后nginx -t nginx -s reload项目就能跑起来。这个模块化的思路对于后续维护、备份、迁移项目配置都特别有用。6.3 我个人在部署这件事上的体会部署nginx这件事表面上是配置一个反向代理服务实际上它考验的是你对整个项目架构的理解程度。我在拿到一个前后端分离项目时如果能把nginx配置顺利写出来通常意味着我对这个项目的请求链路、服务划分、静态资源位置都有了清晰的认知。反过来如果你配置nginx时一脸茫然大概率是对项目整体结构还没吃透。我在Mac上完整部署过几次苍穹外卖项目后最大的收获不是记住了几条nginx指令而是建立起了一套自己的排查套路先确认端口通不通再确认后端服务活没活再看nginx日志报什么错最后才动配置。按照这个顺序大部分部署问题都能在几分钟内定位到具体层次。如果你在部署过程中遇到其他奇怪的问题建议先把nginx的error.log贴出来很多时候日志里的关键信息就是答案。希望这份经验贴能帮你少走几个弯路也欢迎在评论区留言交流一起把nginx这块硬骨头啃下来。
返回列表