ARTICLE DETAIL

资讯详情

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

Java 项目实战: 外卖平台优化-项目部署架构与三台服务器环境

Java 项目实战: 外卖平台优化-项目部署架构与三台服务器环境 平台部署: 整体架构设计与服务器环境规划纲要「部署架构」与「部署环境说明」是项目上线的蓝图两端用户后台管理端餐厅内部人员与微信端C端消费者完整链路用户 →Nginx前端 反向代理→Spring BootTomcat→MySQL主从 Redis三台服务器服务器 A.100、服务器 B.101、服务器 CRedis每台装什么NginxMySQL主库 /JDKGitMavenMySQL从库 /Redis为什么 B 服务器需要Git与Maven要从仓库拉源码并就地打包为什么后期要跑rewrite前端请求带/api前缀后端接口没有用户端HTTPHTTP静态资源直接返回/api/** 反向代理后台管理用户餐厅内部人员浏览器C 端消费者微信小程序/公众号服务器 A 192.168.138.100Nginx :80前端静态资源 反向代理html/distHTML/CSS/JS/图片服务器 B 192.168.138.101Spring Boot :8080内嵌 Tomcat服务器 AMySQL 主库服务器 BMySQL 从库binlog 复制服务器 CRedis缓存一、整体部署架构两个用户端项目分为两端端使用者形态功能后台管理端餐厅内部人员浏览器访问维护菜品、套餐、分类、订单、员工微信端C端消费者小程序 / 公众号浏览菜品、加购物车、下单、支付、查订单课程只开发了后台管理端。微信端本质属于前端开发小程序/公众号页面由专门的前端人员做后端接口是同一套——移动端的/dish/list、/shopping-cart/add、/order/submit等接口在前面的开发章节都已实现。这也印证了前后端分离的价值同一套后端接口服务多个前端形态后台Web、移动H5、小程序、App。请求链路第一步到Nginx两端用户都通过网络请求到前端服务器这是一台Nginx。它承担两件事部署前端页面静态资源配置反向代理把动态请求转发到后端第二步Nginx转发到后端服务后端服务基于Tomcat运行。项目打成jar后因为是Spring Boot项目用的是内嵌Tomcat不需要单独安装Tomcat服务器。第三步后端访问数据层业务处理过程中会操作MySQL主从复制结构与Redis缓存。架构分层接入层Nginx静态资源 / 反向代理 / 负载均衡应用层Spring Boot业务逻辑缓存层Redis验证码 / 菜品 / 套餐数据层MySQL 主从写主读从每一层的职责层组件职责前面章节接入层Nginx静态资源、反向代理、负载均衡62–69 篇应用层Spring Boot业务处理、事务控制18–46 篇缓存层Redis验证码、菜品缓存、套餐缓存47–55 篇数据层MySQL主从持久化、读写分离56–61 篇这就是整个优化章节的成果汇总——前面每篇讲的改造最终都在这个架构里各就各位。二、服务器规划由于虚拟机数量有限课程用三台机器承载全部组件代号IP安装的软件角色服务器 A192.168.138.100Nginx、MySQL主库前端服务器 数据库主库服务器 B192.168.138.101JDK、Git、Maven、MySQL从库后端应用服务器 数据库从库服务器 C172.17.2.94Redis缓存中间件服务器 ANginxMySQL主库Nginx的两个作用部署前端项目html/dist目录配置反向代理把/api/**请求转发到服务器 BMySQL主库承载全部写操作binlog自动复制到服务器 B 的从库。安装过程在前面的Linux章节第 1–6 篇与Nginx章节第 62 篇已讲过此处不再重复。服务器 BJDKGitMavenMySQL从库这四个组件各有明确用途组件用途JDK运行Java程序Spring Boot需要Git代码托管在远程Git仓库部署时要从仓库把最新代码拉下来Maven拉下来的是源码需要打包成jar才能运行MySQL作为主从复制结构中的从库为什么需要Git和Maven——这是很多初学者的疑问。答案在于部署流程git pullmvn clean packagejava -jarGit 仓库源码服务器 B本地源码target/*.jar运行中的服务服务器 B 上不写代码只做拉取 → 打包 → 运行这三件事。所以它需要Git拉代码和Maven打包。另一种思路在开发者本机打包好jar直接上传到服务器 B 运行就不需要装Git和Maven。但那样每次改代码都要手工打包上传在服务器上一键执行脚本完成全流程要高效得多——这也是第 6 篇讲的Shell自动部署脚本的价值。MySQL从库的配置在第 58 篇讲过此处复用。服务器 CRedis单独一台跑Redis作为缓存中间件。课程使用的是已有的172.17.2.94。生产环境Redis也应该做高可用主从 哨兵或Cluster课程为简化起见用单机。生产环境的调整建议课程受限于虚拟机数量做了合并部署生产上应当按角色拆分角色生产建议原因Nginx独立至少两台 Keepalived避免接入层单点应用服务器至少两台 负载均衡避免应用层单点前面第 68 篇讲过MySQL主库独立高配写压力大不与Nginx抢资源MySQL从库独立可多台读压力大Redis主从 哨兵 /Cluster缓存挂了会导致流量全打数据库特别提醒把Nginx和MySQL主库装在同一台机器课程做法在生产上不合适——MySQL的IO和内存占用会严重影响Nginx的响应。三、前后端分离部署的落地回看第 70 篇讲的部署变化后端工程 → 打成 jar → 部署到服务器 B内嵌 Tomcat 前端工程 → Webpack 打包成 dist → 部署到服务器 ANginx这里完全对应上了服务器 A 的Nginx承载前端dist服务器 B 的Spring Boot承载后端jar用户在浏览器输入http://192.168.138.100服务器 A看到的是前端页面页面上的Ajax请求发到/api/**被Nginx反向代理到服务器 B 的8080端口。对用户而言只有一个入口服务器 A 的80端口后端的IP、端口、甚至有几台机器用户完全不知道——这正是第 67 篇讲的反向代理无感知。四、部署前的检查清单项检查内容命令Nginx已安装、能启动nginx -v、nginx -tJDK版本 ≥ 8java -versionGit已安装能访问仓库git --versionMaven已安装配置了镜像mvn -versionMySQL主库已启动已建reggie库并导入表systemctl status mysqldMySQL从库已启动复制正常SHOW SLAVE STATUS\GRedis已启动可远程连接redis-cli -h ip ping防火墙放行80、8080、3306、6379firewall-cmd --list-ports网络各服务器之间互通ping、telnet ip port防火墙是最常见的部署完访问不了的原因。需要放行的端口# 服务器 Afirewall-cmd--zonepublic --add-port80/tcp--permanentfirewall-cmd--zonepublic --add-port3306/tcp--permanentfirewall-cmd--reload# 服务器 Bfirewall-cmd--zonepublic --add-port8080/tcp--permanentfirewall-cmd--zonepublic --add-port3306/tcp--permanentfirewall-cmd--reload# 服务器 Cfirewall-cmd--zonepublic --add-port6379/tcp--permanentfirewall-cmd--reloadMySQL的3306与Redis的6379只对内网放行绝不能暴露到公网。生产上应当用firewall-cmd --add-rich-rule限定来源IPfirewall-cmd--permanent--add-rich-rule rule familyipv4 source address192.168.138.101 port protocoltcp port3306 acceptfirewall-cmd--reload五、配置项核对部署前确认后端application.yml中的地址指向正确server:port:8080spring:application:name:reggie_take_outshardingsphere:datasource:names:master,slavemaster:type:com.alibaba.druid.pool.DruidDataSourcedriver-class-name:com.mysql.cj.jdbc.Driverurl:jdbc:mysql://192.168.138.100:3306/reggie?characterEncodingutf-8# 服务器 Ausername:rootpassword:rootslave:type:com.alibaba.druid.pool.DruidDataSourcedriver-class-name:com.mysql.cj.jdbc.Driverurl:jdbc:mysql://192.168.138.101:3306/reggie?characterEncodingutf-8# 服务器 Busername:rootpassword:rootmasterslave:load-balance-algorithm-type:round_robinname:dataSourcemaster-data-source-name:masterslave-data-source-names:slaveredis:host:172.17.2.94# 服务器 Cport:6379password:root123456database:0cache:redis:time-to-live:1800000reggie:path:/usr/local/img/# 注意Linux 路径不是 D:\img\最后一行reggie.path是本篇的伏笔开发时是D:\img\Windows本地路径部署到Linux后必须改成Linux路径否则图片全部找不到。这是第 76 篇要解决的核心问题。六、部署流程总览否是准备三台服务器安装软件服务器 A上传 dist 到/usr/local/nginx/html/服务器 A配置 nginx.conf静态资源 反向代理服务器 Bgit clone 拉取源码服务器 B上传 reggieStart.shchmod 777执行脚本拉代码 打包 启动访问 192.168.138.100 验证图片能否显示?修改 reggie.path 为 Linux 路径上传图片 重新执行脚本部署完成API 速览命令作用java -version确认JDK已安装mvn -version确认Maven已安装git --version确认Git已安装nginx -v/nginx -t确认Nginx版本 / 检查配置redis-cli -h ip ping测试Redis连通性systemctl status mysqld查看MySQL状态SHOW SLAVE STATUS\G查看从库复制状态firewall-cmd --list-ports查看已放行端口firewall-cmd --add-port80/tcp --permanent永久放行端口firewall-cmd --add-rich-rulerule ...限定来源IP的放行规则更安全ping ip/telnet ip port测试网络连通性官方文档Nginx部署指南https://nginx.org/en/docs/beginners_guide.htmlSpring Boot部署文档https://docs.spring.io/spring-boot/docs/2.7.x/reference/html/deployment.htmlMySQL主从复制https://dev.mysql.com/doc/refman/8.0/en/replication.htmlRedis复制与高可用https://redis.io/docs/management/replication/Maven生命周期https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html总结整体架构是前面所有优化的汇总之地Nginx在接入层做静态资源、反向代理、负载均衡Spring Boot在应用层处理业务Redis做缓存MySQL主从做读写分离。每一层都是前面某个章节的成果。三台服务器的分工要记清服务器 A.100装NginxMySQL主库服务器 B.101装JDKGitMavenMySQL从库服务器 C 装Redis。服务器 B 上装Git和Maven的原因值得理解部署流程是从Git拉源码 →Maven打包 →java -jar运行三步装这两个工具是为了能在服务器上一键完成全流程。替代方案是本机打包上传但那样每次改代码都要手工操作。课程受限于虚拟机做了合并部署Nginx与MySQL主库同机、应用与MySQL从库同机生产上必须按角色拆分——MySQL的IO与内存占用会严重影响同机其他服务的响应。部署前务必核对防火墙与application.yml中的地址。尤其是reggie.path开发时是D:\img\Linux上没有D盘必须改成/usr/local/img/一类的Linux路径——这是下一篇要解决的图片展示问题的根因。下一篇进入实际操作把前端dist目录部署到Nginx并配置rewriteproxy_pass完成反向代理。
返回列表