一、环境准备
1.1. 购买一个云服务器,例如阿里云、腾讯云等等,操作系统为Linux centos7.x
1.2.远程连接工具xshell或finalshell
1.3. 在服务器上安装Jdk1.8+
1.3.1.yum安装 openjdk11
yum install -y java-11-openjdk
安装位置默认为/usr/lib/jvm/
,修改目录名
mv -v java-11-openjdk-11.0.12.0.7-0.el8_4.x86_64 jdk11
1.3.2.配置环境变量
修改配置文件
vim /etc/profile
将光标移动到最后,在后面添加
export JAVA_HOME=/usr/lib/jvm/jdk11
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
立即生效
source /etc/profile
检测是否安装成功
java -version
::: tip
openjdk version “11.0.12” 2021-07-20 LTS
OpenJDK Runtime Environment 18.9 (build 11.0.12+7-LTS)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.12+7-LTS, mixed mode, sharing)
:::
1.4.在服务器上安装Nginx
1.4.1.安装前环境配置
一般来说,这些环境服务器已经帮你配好了,但还是检测一下,有备无患嘛。
//安装gcc
yum install gcc-c++
//安装PCRE pcre-devel
yum install -y pcre pcre-devel
//安装zlib
yum install -y zlib zlib-devel
//安装Open SSL
yum install -y openssl openssl-devel
1.4.2.创建nginx目录并下载安装包
//进入usr/local目录
cd /usr/local
//创建nginx目录
mkdir nginx
//进入nginx目录
cd nginx
下载tar包(我下载的是1.22.0版本)
wget http://nginx.org/download/nginx-1.22.0.tar.gz
解压tar
tar -xvf nginx-1.22.0.tar.gz
1.4.3.安装nginx
//进入nginx目录
cd /usr/local/nginx/nginx-1.22.0
//执行命令
./configure
//执行make命令(要是执行不成功请检查最开始安装的四个有没有安装成功)
make
//执行make install命令
make install
1.4.4.启动nginx
//进入/usr/local/nginx/sbin目录,输入./nginx即可启动nginx
./nginx
//关闭nginx
./nginx -s quit 或者 ./nginx -s stop
//重启nginx
./nginx -s reload
//查看nginx进程
ps -ef|grep nginx
1.5.修改项目配置文件地址
由于我部署的这个项目默认集成了一些中间件,所以账号密码啥的都不用动。项目地址-->铱塔智联开源
如果是其他项目,可能要改动MySQL、Redis等的账号密码。
二、后端项目打包
因为不想在服务器上安装太多环境,所以选择在本地打包。
2.1.一般项目打包
在Terminal里执行mvn package (需要安装maven环境)
进入target目录就能看到打好的jar包
将jar包拷贝到上级目录,防止target目录清理导致jar包丢失
2.2.iot-iita项目打包
在配置好相应的jdk11环境后,推荐使用idea拉取代码,等待项目加载完成以后,先在Terminal里执行mvn clean install,然后在idea的maven操作框上点击下刷新
具体的项目可能有具体的打包方式,我这里把jar包上传到服务器 /www/ 新建的project目录下。
三、前端项目打包
3.1.Web项目打包
使用命令pnpm run build:prod
或yarn build:prod
,打包完成后会生成一个dist目录,然后将其压缩上传到 /www/wwwroot/ 目录下
然后用unzip dist.zip
解压
::: tip
这些命令需要安装node.js并配置相关环境,网上有很多安装教程,这里就不多做解释了。
:::
3.2.App项目打包
3.2.1.创建web文件夹
输入以下命令创建web文件
flutter create .
然后就会创建一系列web相关的文件,目录结构也会多一个web文件夹。如下图:
3.2.2.打包web版本
我们知道要给android手机用,需要打包apk出来,,要给iPhone手机用,需要打包ipa出来;同样的道理要给浏览器用,也需要打包web相关代码。
flutter build web --web-renderer html
这将生成包括资源的应用程序,并将文件放入项目的/build/web
目录中。
一般的应用程序的 release 版本具有以下结构:
/build/web
assets
AssetManifest.json
FontManifest.json
NOTICES
fonts
MaterialIcons-Regular.ttf
<other font files>
<image files>
index.html
main.dart.js
main.dart.js.map
然后将web目录压缩,重复3.1步骤
::: tip
flutter需要下载并配置相关环境,这里也不做解释了。
:::
四、部署后端项目
4.1.一般后端项目启动
进入对应目录下,后台启动jar包
nohup java -jar iot-starter-0.4.5-SNAPSHOT.jar &
4.2.iot-iita项目启动
官方的README文件中也有说明,直接执行start.sh就可以启动了。遗憾的是,事情并不能一帆风顺。
启动失败:
之后直接通过java -jar 启动才在打印的日志上发现是9200和6379端口被占用了。
查找被占用端口的进程
lsof -i :端口号
通过进程的PID杀死进程
kill -9 PID
但诡异的是,之后每次启动项目前都要手动杀死两个端口下的进程,才能成功启动。自然而然就会想到stop.sh里的脚本是不完整的。
改进后的脚本:
#!/bin/bash
# 项目名称
APPLICATION="iot-starter"
# 项目启动jar包名称
APPLICATION_JAR="iot-starter-0.4.5-SNAPSHOT.jar"
# 设置要检查的端口
ES_CHECK=9200
REDIS_CHECK=6379
# 通过项目名称查找到PI,然后kill -9 pid
PID=$(ps -ef | grep "${APPLICATION_JAR}" | grep -v grep | awk '{ print $2 }')
ES_PID=$(lsof -t -i:$ES_CHECK)
REDIS_PID=$(lsof -t -i:$REDIS_CHECK)
if [[ -z "$PID" ]]
then
echo ${APPLICATION} is already stopped
else
echo kill ${PID}
kill -9 ${PID}
echo ${APPLICATION} stopped successfully
fi
if [ -z "$ES_PID" ]; then
echo "端口 $ES_CHECK 未被占用"
else
kill -9 $ES_PID
echo "已杀死进程 $ES_PID 占用端口 $ES_CHECK."
fi
if [ -z "$REDIS_PID" ]; then
echo "端口 $REDIS_CHECK 未被占用"
else
kill -9 $REDIS_PID
echo "已杀死进程 $REDIS_PID 占用端口 $REDIS_CHECK."
fi
五、部署前端项目
进入到nginx的目录
cd /usr/local/nginx/
修改Nginx的配置文件(修改conf文件夹下的nginx.conf文件)
- 防止出现权限相关的问题,将文件开头的user修改为root
- 修改监听listen的端口号为8082,这个端口号取决于自己想从几号端口访问前端页面;server_name为你的服务器ip,如果你有域名且配置解析好了,也可以再在此添域名。
- 找到这些内容并将root 后跟的路径修改为刚才前端代码打包的dist文件夹的路径。
- 配置代理,将前端和后端的地址关联起来。
- 将server复制一份出来,然后修改端口号和root,用于监听不同的端口指向app的静态文件
nginx配置文件nginx.conf的整体代码
user root;
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;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
server {
listen 8082;
# listen somename:8080;
server_name ip地址;
location / {
root /www/wwwroot/dist;
index index.html index.htm;
}
location /prod-api/ {
rewrite /api(.*) $1 break;
proxy_pass http://ip地址:8086/;
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 REMOTE-HOST $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;
}
}
server {
listen 8084;
# listen somename:8080;
server_name ip地址;
location / {
root /www/wwwroot/build/web;
index index.html index.htm;
}
location /prod-api/ {
rewrite /api(.*) $1 break;
proxy_pass http://ip地址:8086/;
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 REMOTE-HOST $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;
}
}
}
- 端口配置好了后,每次修改了nginx的配置文件后一定要重新启动nginx,使新配置生效。如果重启失败,则先找到nginx的进程,然后将其kill掉,再重启nginx:
# 启动nginx
./nginx
# 如果已经将nginx配置到全局的环境变量中,就可以直接运行这个命令重启nginx
nginx -s reload
# 如果没有将其配置到全局的环境变量中,则需要进入安装的nginx/sbin/目录中,用如下命令:
./nginx -s reload
恭喜你项目部署完成,此时就可以在浏览器输入对应的ip和端口访问前端了
六、部署注意事项
6.1.开放防火墙相应端口
现在的服务器系统中的防火墙一般是关闭的,而由服务器的供应商帮你进行防火墙规则设置。这里以腾讯云为例,添加项目中用到的端口
添加规则
开放需要的端口即可
6.2.部署后端项目启动失败
查看是不是后端项目的端口号被占用了
netstat -anp | grep 端口号
6.3.节省服务器空间
前端和后端的项目打包都可以在本地完成,上传服务器可以最小化上传jar包和dist文件夹,这种方式最节省服务器空间资源。
后端项目只保留jar包即可
前端项目只保留dist文件夹即可
七、参考资源
- 云服务器部署前后端分离项目(若依)详细教程_prod-api_Karthus_冲冲冲的博客-CSDN博客
- SpringBoot前后端分离项目,打包、部署到服务器详细图文流程-阿里云开发者社区 (aliyun.com)
- flutter项目打包web访问-腾讯云开发者社区-腾讯云 (tencent.com)