使用两台虚拟机分别部署前端和后端项目
1 部署方案
使用虚拟机模拟服务器,完成前后端项目的部署,我们使用两台虚拟机分别部署前端和后端项目,具体的部署方案如下图所示。
上述方案中,server-01
用于部署移动端和后台管理系统的两个后端服务。server-02
部署Nginx,作为移动端和后台管理系统两个前端项目的web服务器,同时也作为两个后端服务的反向代理。也就是说Nginx作为所有请求的入口,若请求内容是静态资源,Nginx便直接返回;若请求的内容为动态资源(后端服务接口),Nginx便代理请求后端服务,然后将结果响应给客户端。
2 准备两台虚拟机,并配置网络环境
虚拟机的安装及网络环境的配置,可参考我的博客
虚拟机安装
虚拟机克隆
这里我准备了2台虚拟机:
server-01 服务器对应的ip为 192.168.10.13 --用于部署web-app.jar移动端和web-admin.jar后台管理系统的两个后端服务 server-02 服务器对应的ip为 192.168.10.12 --用于部署Nginx,作为app移动端和admin后台管理系统两个前端项目的web服务器,同时也作为两个后端服务的反向代理
注意,这里省略在虚拟机上安装jdk,mysql,nginx,redis…服务器步骤,安装详情可参考我的博客
Linux系统安装JDK1.8-源码版
虚拟机CentOS服务器-安装 部署Nginx
Centos7.x上安装与卸载mysql8与5.7版本
Linux环境安装Redis6
3 部署后端项目
3.1 打包服务
使用IDEA的maven插件对项目进行打包,完成后,在web-admin和web-app模块的target
目录下找到web-admin-1.0-SNAPSHOT.jar
和web-app-1.0-SNAPSHOT.jar
。
web-app-1.0-SNAPSHOT.jar 移动端后端jar包,对应端口8081 web-admin-1.0-SNAPSHOT.jar 后台管理系统后端jar包,对应端口8080
3.2 上传jar包到服务器
将后端项目的两个jar包上传到server-01
服务器的/opt/lease
目录下,若目录不存在,自行创建即可。
直接使用 java -jar 命令启动这两个后端服务,然后访问接口文档,看看能否正常访问
3.3 集成Systemd
为方便项目的启动、停止或者重启,我们同样使用Systemd来管理后端服务的进程。
3.3.1 移动端服务集成Systemd
创建lease-app.service
文件
vim /etc/systemd/system/lease-app.service
内容如下
[Unit] Description=lease-app After=syslog.target [Service] User=root # 注意:这里要使用jdk安装的绝对路径 ExecStart=/usr/local/software/jdk/jdk17/bin/java -jar /opt/lease/web-app-1.0-SNAPSHOT.jar 1>/opt/lease/app.log 2>&1 SuccessExitStatus=143 [Install] WantedBy=multi-user.target
启动项目
一旦编辑并保存了lease-app.service文件,你需要重新加载Systemd的配置,然后启动你的服务。这可以通过下面的命令完成:
# 重新加载Systemd配置 systemctl daemon-reload # 启动 systemctl start lease-app.service # 查看状态 systemctl status lease-app.service # 停止 systemctl stop lease-app.service # 设置服务在系统启动时自动启动 ystemctl enable lease-app.service
3.3.2 后台管理系统集成Systemd
创建lease-admin.service
文件
vim /etc/systemd/system/lease-admin.service
内容如下
[Unit] Description=lease-admin After=syslog.target [Service] User=root # 注意:这里要使用jdk安装的绝对路径 ExecStart=/usr/local/software/jdk/jdk17/bin/java -jar /opt/lease/web-admin-1.0-SNAPSHOT.jar 1>/opt/lease/admin.log 2>&1 SuccessExitStatus=143 [Install] WantedBy=multi-user.target
启动项目
一旦编辑并保存了lease-admin.service文件,你需要重新加载Systemd的配置,然后启动你的服务。这可以通过下面的命令完成:
# 重新加载Systemd配置 systemctl daemon-reload # 启动 systemctl start lease-admin.service # 查看状态 systemctl status lease-admin.service # 停止 systemctl stop lease-admin.service # 设置服务在系统启动时自动启动 ystemctl enable lease-admin.service
查看后端两个服务是否成功启动:
这里留了一个bug,就是,后端两个服务都成功启动了,但是输出的日志文件在服务器上并没有找到,奇了怪了,等后续再来处理吧
4 配置域名映射
现实生活中,几乎所有的网站都是通过域名去访问。真正的域名需要付费购买,此处在宿主机本地配置一下域名映射,模拟一下域名的效果即可。
我们准备两个域名lease.wusong.com
和admin.lease.wusong.com
,前者用于访问移动端网站,后者用于访问后台管理系统。由于两个前端项目都部署在server-02
上,所以两个域名均指向server-02
的IP 192.168.10.12
Windows的域名映射配置文件位于C:\Windows\System32\drivers\etc\hosts
,需要使用管理员身份修改。使用管理员身份运行任意文本编辑器,然后使用其打开hosts
文件,并增加如下内容:
192.168.10.12 lease.wusong.com admin.lease.wusong.com
修改完毕记得保存。不需要重启电脑。
5 部署前端项目
移动端和后台管理系统的前端项目均部署在server-02
的Nginx中,Nginx的配置思路如下图所示
5.1 移动端
5.1.1 打包
明确前端请求的后端接口地址
打包之前需要明确前端请求的后台接口地址,根据前文的部署规划,前端请求后台接口时走的是Ngxin反向代理,也就是请求的地址为
http://lease.wusong.com:80
。这里的80是nginx配置的端口号,根据自身情况配置。
❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗注意注意注意!!!:移动端请求的后端接口地址按理说应该是192.168.10.13:8081,但是按照我们的部署方案,移动端是不会直接去请求后端服务的接口地址的,也就是说是不会直接请求192.168.10.13:8081,而是这里我们是通过nginx的反向代理去请求的,也就是说我们得让这个移动端客户端把请求后端接口数据的请求发送给虚拟主机,然后我们在虚拟主机 通过location把这些请求转发给真正的后端服务
❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗
所以我们需要修改.env.production
文件中VITE_APP_BASE_URL
环境变量的值,修改结果如下
VITE_APP_BASE_URL='http://lease.wusong.com:80'
构建项目
在项目的根目录执行以下命令
npm run build
查看打包结果
观察项目的根目录是否出现
dist
目录,我们将dist目录直接重命名为app
5.1.2 部署
上传dist文件
将
rentHouseH5
前端项目编译得到app
目录上传至server-02
服务器的/usr/local/software/nginx/html/
目录下。
注意此 /usr/local/software/nginx/目录是nginx的安装目录
- 编辑Nginx配置文件
添加以下server块,内容如下
server { # 表示Nginx将监听标准的HTTP端口80。这意味着所有发往该服务器80端口的HTTP请求都将由这个服务器块处理 listen 80; # 定义了这个服务器块将响应哪些域名的请求。在这里,只有当请求的Host头部字段为lease.wusong.com时,Nginx才会使用这个服务器块来处理请求 server_name lease.wusong.com; # 处理app移动端静态资源请求 location / { # 表示当请求的URL以/开始时,Nginx将使用这个location块中的指令来处理请求 # 指定了Nginx在接收到请求时应该从哪个目录下查找文件。在这里,Nginx会从/usr/local/software/nginx/html/app目录下查找请求的资源 root /usr/local/software/nginx/html/app; # 如果请求的URL指向一个目录,Nginx会尝试返回这个目录下的index.html或index.htm文件作为主页 index index.html index.htm; } # 后端服务代理 location /app { # 表示当请求的URL以/app开始时,Nginx将使用这个location块中的指令来处理请求 # 移动端后端服务地址 # 将所有匹配/app的请求转发到位于192.168.10.13:8081的后端服务器。这通常用于负载均衡、微服务架构或API网关场景,其中Nginx充当反向代理角色 proxy_pass http://192.168.10.13:8081; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
有一个问题需要思考一下:
就是这个 / 它会匹配所有的请求,它也包括 /app,假如客户端来了一个以/app为前缀的请求,那么nginx会使用哪一个location来处理这个请求呢?
nginx的处理方法是:当一个请求可以匹配到多个location的时候,那么nginx会让匹配程度最高的location来处理这个请求
所以,以/app为前缀的所有请求都是由这个location /app {…}来处理,因为它的匹配度最高,而这个,location / {…}会处理除了location /app {…}处理之外的请求,说白了就是静态资源的请求了
❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️扩展始❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️
这里说一下这个server block
和location block
例如:
server blockserver block
位于http block
,用于配置虚拟主机,一个Nginx服务可包含多个虚拟主机,每个虚拟主机都可以独立的提供服务,因此借助Nginx,我们可以在一台服务器部署多个独立的网站,如下图所示
每个虚拟主机使用一个server block
进行配置,配置的内容包括
listen
:虚拟主机监听的端口号。server_name
:指定虚拟主机的域名或者IP。
location block
location block
位于server block
,用于配置请求的处理逻辑,一个server block
中可以包含多个location block
,例如
server { listen 80; server_name www.wusong.com; location /index { root /var/www/html; } location /api { proxy_pass http://backend-api; } }
❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️扩展终❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️
- 重新加载Nginx配置文件
执行以下命令重新加载配置文件
注意:在nginx的安装目录下的sbin目录下执行 # 停止 ./nginx -s stop # 开启 ./nginx # 重新加载 当修改了Nginx配置文件后,需要重新加载才能生效,可以使用下面命令重新加载配置文件: ./nginx -s reload
- 访问项目
http://lease.wusong.com:80
5.2 后台管理系统
5.2.1 打包
明确前端请求的后端接口地址
后台管理系统的前端请求后端接口时,同样会走Nginx反向代理,故其请求的接口地址为
http://admin.lease.wusong.com:80
。确保rentHouseAdmin项目中的
.env.production
文件中的VITE_APP_BASE_URL
环境变量配置为如下内容VITE_APP_BASE_URL='http://admin.lease.wusong.com:80'
打包
在项目根目录执行以下命令
npm run build
查看打包结果
观察项目的根目录是否出现
dist
目录,我们将dist目录直接重命名为admin
5.2.2 部署
上传dist文件
将
rentHouseAdmin
项目编译得到admin
文件上传至server-02
服务器的/usr/local/software/nginx/html/
目录下。
注意此 /usr/local/software/nginx/目录是nginx的安装目录
- 编辑Nginx配置文件
添加以下server块,内容如下
server { # 表示Nginx将监听标准的HTTP端口80。这意味着所有发往该服务器80端口的HTTP请求都将由这个服务器块处理 listen 80; # 定义了这个服务器块将响应哪些域名的请求。在这里,只有当请求的Host头部字段为admin.lease.wusong.com时,Nginx才会使用这个服务器块来处理请求 server_name admin.lease.wusong.com; # 处理admin后台管理系统静态资源请求 location / { # 表示当请求的URL以/开始时,Nginx将使用这个location块中的指令来处理请求 # 指定了Nginx在接收到请求时应该从哪个目录下查找文件。在这里,Nginx会从/usr/local/software/nginx/html/admin目录下查找请求的资源 root /usr/local/software/nginx/html/admin; # 如果请求的URL指向一个目录,Nginx会尝试返回这个目录下的index.html或index.htm文件作为主页 index index.html index.htm; } # 后端服务代理 location /admin { # 表示当请求的URL以/admin开始时,Nginx将使用这个location块中的指令来处理请求 # 后台管理系统后端服务地址 # 将所有匹配/app的请求转发到位于192.168.10.13:8080的后端服务器。这通常用于负载均衡、微服务架构或API网关场景,其中Nginx充当反向代理角色 proxy_pass http://192.168.10.13:8080; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
- 重新加载Nginx配置文件
执行以下命令重新加载配置文件
注意:在nginx的安装目录下的sbin目录下执行 # 停止 ./nginx -s stop # 重新加载 当修改了Nginx配置文件后,需要重新加载才能生效,可以使用下面命令重新加载配置文件: ./nginx -s reload
- 访问项目
http://admin.lease.wusong.com:80
最终的nginx配置如下:
#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; 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 logs/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 80; server_name admin.lease.wusong.com; # 处理admin后台管理系统静态资源请求 location / { root /usr/local/software/nginx/html/admin; index index.html index.htm; } location /admin { # 后台管理系统后端服务地址 proxy_pass http://192.168.10.13:8080; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } server { listen 80; server_name lease.wusong.com; # 处理app移动端静态资源请求 location / { root /usr/local/software/nginx/html/app; index index.html index.htm; } location /app { # 移动端后端服务地址 proxy_pass http://192.168.10.13:8081; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }