Appearance
部署文档
部署准备
最低服务器配置
2核16G内存服务器一台(推荐使用 CentOS 7.6 64位)(如果基础中间件使用外部服务器的,则可以适量减少内存)
docker-compose环境安装
- 安装docker-compose环境(已经安装的可以略过)
#安装git
sudo yum install -y git
#安装maven
sudo yum install -y maven
#安装依赖
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
#设置源
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo yum makecache fast
#安装docker
sudo yum install -y docker-ce
#启动服务
sudo systemctl start docker
#安装docker-compose
curl -L https://github.com/docker/compose/releases/download/v2.17.1/docker-compose-linux-x86_64 > /usr/local/bin/docker-compose
#授权
sudo chmod +x /usr/local/bin/docker-compose
#检测版本号
docker-compose -v- docker脚本下载
git clone https://gitee.com/beijing_hongye_huicheng/docker.gitRocketmq 需要特殊配制一下节点ip
在 config/broker.conf 文件中,将brokerIP1修改为部署docker的局域网ip
运行脚本
必须保证es本地挂载目录权限为 777 否则es启动不成功。默认es本地挂载目录为docker项目上一级的volumes/data
docker-compose up -d- 校验 (查看进程是否启动,如果反复启动的程序,可以使用docker logs 镜像id 查看日志)
docker psAPI部署
- 下载源码
cd /home/source
git clone https://gitee.com/beijing_hongye_huicheng/lilishop.git- 编辑运行API的脚本
vi pg_start_api1.sh脚本内容:
#!/bin/bash
# 开启 Fail-Fast 机制:除了交互式选择和特定检查外,关键命令执行失败(返回非 0)会立即退出验证环节
# 由于带有交互逻辑,这里不全局 set -e,而是在关键函数中处理错误
# ==========================================
# 统一变量与配置区 (Configuration Zone)
# ==========================================
version="4.3"
max_wait_seconds=60
code_path="/home/source/lilishop"
run_path="/home/source/api/"
# 定义所有服务名称数组(用于遍历和菜单选择)
service_names=("buyer" "manager" "im")
# 声明服务配置映射 (服务名对应 -> PID关键词:端口:JAR包名:JVM参数)
# 注意:Bash 3不支持关联数组声明,这里用 case 语句实现配置获取以兼容所有版本
get_service_config() {
local s_name=$1
case $s_name in
"buyer") echo "buyer 8083 buyer-api-$version.jar -Xmx1g -Xms256m -Xss512k" ;;
"manager") echo "manager 8081 manager-api-$version.jar -Xmx1g -Xms128m -Xss256k" ;;
"im") echo "im 8086 im-api-$version.jar -Xmx512m -Xms128m -Xss256k" ;;
*) echo "" ;;
esac
}
# 统一追加的生产环境通用 JVM 参数兜底策略
common_jvm_opts="-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=logs/"
# 打印颜色辅助函数
color_echo() {
local color=$1
local text=$2
case $color in
"red") echo -e "\033[31m${text}\033[0m" ;;
"green") echo -e "\033[32m${text}\033[0m" ;;
"yellow") echo -e "\033[33m${text}\033[0m" ;;
"blue") echo -e "\033[34m${text}\033[0m" ;;
*) echo "$text" ;;
esac
}
# ==========================================
# 核心功能函数区 (Core Functions)
# ==========================================
# 1. 检查目录
check_env() {
if [ ! -d "$code_path" ]; then
color_echo "red" "错误: 代码目录 $code_path 不存在!"
exit 1
fi
}
# 2. 拉取代码
pull_code() {
color_echo "blue" "\n==== [1/4] 更新代码 (Git Pull) ===="
cd "${code_path}" || exit 1
git checkout master || { color_echo "red" "Git Checkout 失败"; exit 1; }
git pull || { color_echo "red" "Git Pull 失败"; exit 1; }
color_echo "green" "代码更新完成。"
}
# 3. 编译构建
build_code() {
color_echo "blue" "\n==== [2/4] 构建代码 (Maven Build) ===="
cd "${code_path}" || exit 1
# 开启 Maven 多线程构建加速
mvn clean install -DskipTests -T 1C || { color_echo "red" "Maven 构建失败"; exit 1; }
color_echo "green" "Maven 构建完成。"
}
# 4. 拷贝与归档
prepare_jars() {
color_echo "blue" "\n==== [3/4] 归档旧文件,准备新 JAR 包 ===="
mkdir -p "${run_path}/logs"
# 清理所有旧的 jar 包
rm -f "${run_path}"/*.jar
# 移动刚才编译好的包
mv "${code_path}"/buyer-api/target/buyer-api-$version.jar "${run_path}"
mv "${code_path}"/manager-api/target/manager-api-$version.jar "${run_path}"
mv "${code_path}"/im-api/target/im-api-$version.jar "${run_path}"
color_echo "green" "JAR 包拷贝完成。"
}
# 5. 停止指定服务 (传all停全部)
stop_services() {
local target_service=$1
color_echo "blue" "\n==== [X] 停止服务 (Stop Services) [$target_service] ===="
local s_list=("${service_names[@]}")
if [ "$target_service" != "all" ]; then
s_list=("$target_service")
fi
for name in "${s_list[@]}"; do
# 获取对应进程的 PID
pids=$(ps -ef | grep java | grep "jar" | grep "$name" | grep -v 'grep' | awk '{print $2}')
if [ -n "$pids" ]; then
color_echo "yellow" "尝试优雅停机 $name (PID: $pids)..."
kill -15 $pids
# 等待进程退出,最多等 10 秒
wait_time=0
while ps -p $pids > /dev/null 2>&1; do
sleep 1
((wait_time++))
if [ $wait_time -ge 10 ]; then
color_echo "red" "进程未主动退出,执行强制清理 (kill -9)..."
kill -9 $pids
break
fi
done
color_echo "green" "$name 进程已完全终止。"
else
echo "服务 $name 目前未运行。"
fi
done
}
# 6. 启动指定服务 (传all起全部)
start_services() {
local target_service=$1
color_echo "blue" "\n==== [4/4] 启动服务 (Start Services) [$target_service] ===="
cd "${run_path}" || { color_echo "red" "进入运行目录失败"; exit 1; }
mkdir -p logs
local s_list=("${service_names[@]}")
if [ "$target_service" != "all" ]; then
s_list=("$target_service")
fi
for name in "${s_list[@]}"; do
config_str=$(get_service_config "$name")
if [ -z "$config_str" ]; then
color_echo "red" "未找到服务 $name 的配置,跳过。"
continue
fi
IFS=' ' read -r app_name port jar_file jvm_opts <<< "$config_str"
# 检查包是否存在
if [ ! -f "$jar_file" ]; then
color_echo "red" "错误:运行目录下找不到对应的包 ${jar_file},无法启动该服务!"
if [ "$target_service" = "all" ]; then continue; else exit 1; fi
fi
# 归档旧日志 (使用替换时间命名)
if [ -f "logs/${app_name}.out" ]; then
# 创建归档目录
mkdir -p logs/archive
# 获取当前时间格式: YYYYMMDD_HHMMSS
local current_time=$(date "+%Y%m%d_%H%M%S")
# 移动并重命名文件
mv "logs/${app_name}.out" "logs/archive/${app_name}_${current_time}.out"
fi
# 启动进程
nohup java $jvm_opts $common_jvm_opts -jar "$jar_file" --spring.profiles.active=prod > "logs/${app_name}.out" 2>&1 &
echo -n "启动 $app_name 中 (目标端口 $port)..."
# 智能检查:轮询检查端口是否处于 LISTEN 状态
port_ready=false
for ((i=1; i<=max_wait_seconds; i++)); do
if lsof -i :$port -sTCP:LISTEN >/dev/null 2>&1; then
port_ready=true
break
fi
echo -n "."
sleep 1
done
if [ "$port_ready" = true ]; then
color_echo "green" " 启动成功!"
else
color_echo "red" "\n[错误] $app_name 在 $max_wait_seconds 秒内未能成功启动端口 $port 开发!终端拦截。"
color_echo "yellow" "请查看尾部日志以便排查:"
tail -n 20 "logs/${app_name}.out"
# 启动单一服务失败退出,如果是all则继续尝试别的
if [ "$target_service" != "all" ]; then exit 1; fi
fi
done
}
# ==========================================
# 交互与调度逻辑 (Interactive & Dispatch Menu)
# ==========================================
show_menu() {
clear
color_echo "green" "=============================================="
color_echo "green" " LiliShop 一站式服务管理脚本 版本: $version"
color_echo "green" "=============================================="
echo "请选择你要执行的操作:"
echo "1. [一键发版] 全量拉取代码、构建并启动所有服务 (Default)"
echo "2. [离线一键] 不拉取代码,仅重新构建并启动所有服务"
echo "3. [仅起服务] 不构建,直接使用现有的 JAR 包启动所有服务"
echo "4. [选择重启] 重启单独的服务 (例如仅重启 buyer-api, 无构建)"
echo "5. [选择构建] 构建并重启单独的服务 (拉取最新代码 -> 编译 -> 仅重启此项)"
echo "6. [一键关停] 停止所有正在运行的服务"
echo "0. [退出] 取消并安全退出"
color_echo "green" "=============================================="
read -rp "请输入序号 [1-6,0] " choice
}
select_single_service() {
local action_type=$1 # start_only 或 build_and_start
echo ""
color_echo "yellow" "请选择要操作的服务名字 (输入数字):"
select srv in "${service_names[@]}"; do
if [ -n "$srv" ]; then
color_echo "blue" "你选择了: $srv"
if [ "$action_type" = "start_only" ]; then
stop_services "$srv"
start_services "$srv"
elif [ "$action_type" = "build_and_start" ]; then
pull_code
build_code
# 为单个服务更新 JAR 这里我们简单只拷贝他需要的
config_str=$(get_service_config "$srv")
IFS=' ' read -r app_name port jar_file jvm_opts <<< "$config_str"
# 由于模块目录命名跟 jar 不一定一样,简单的做法依然是全量拷贝,覆盖掉旧的。
prepare_jars
stop_services "$srv"
start_services "$srv"
fi
break
else
color_echo "red" "无效的选择,请重新输入"
fi
done
}
main() {
check_env
# 支持命令行静默参数调用 (方便配合 Jenkins/GitLab CI)
case "$1" in
--build-all)
pull_code; build_code; stop_services "all"; prepare_jars; start_services "all"
exit 0;;
--start-all)
stop_services "all"; start_services "all"
exit 0;;
--stop-all)
stop_services "all"
exit 0;;
*)
# 无参数,进入交互菜单
show_menu
case $choice in
1)
# 全量
pull_code; build_code; stop_services "all"; prepare_jars; start_services "all"
;;
2)
# 不拉取,构建+启动全部
build_code; stop_services "all"; prepare_jars; start_services "all"
;;
3)
# 不构建,仅启动全部旧包
stop_services "all"; start_services "all"
;;
4)
# 仅重启单独的服务(不构建)
select_single_service "start_only"
;;
5)
# 构建并重启单独的服务
select_single_service "build_and_start"
;;
6)
stop_services "all"
;;
0)
color_echo "yellow" "退出脚本。"
exit 0
;;
*)
color_echo "red" "无效的选择!"
exit 1
;;
esac
;;
esac
color_echo "green" "\n🎉 操作执行完毕。"
}
# 脚本入口
main "$@"- 执行脚本
sh pg_start_api1.sh可以指定不同的环境有不同的启动参数(上方为正式环境)
测试环境:
nohup java -Xmx256m -Xms128m -Xss256k -jar manager-api-$version.jar --spring.profiles.active=test > logs/manager.out 2>&1 &
nohup java -Xmx256m -Xms128m -Xss256k -jar common-api-$version.jar --spring.profiles.active=test > logs/common.out 2>&1 &
nohup java -Xmx256m -Xms128m -Xss256k -jar buyer-api-$version.jar --spring.profiles.active=test > logs/buyer.out 2>&1 &
nohup java -Xmx256m -Xms128m -Xss256k -jar consumer-$version.jar --spring.profiles.active=test > logs/consumer.out 2>&1 &
nohup java -Xmx256m -Xms128m -Xss256k -jar im-api-$version.jar --spring.profiles.active=test > logs/im.out 2>&1 &
nohup java -Xmx256m -Xms128m -Xss256k -jar seller-api-$version.jar --spring.profiles.active=test > logs/seller.out 2>&1 &开发环境:
nohup java -Xmx256m -Xms128m -Xss256k -jar manager-api-$version.jar --spring.profiles.active=dev > logs/manager.out 2>&1 &
nohup java -Xmx256m -Xms128m -Xss256k -jar common-api-$version.jar --spring.profiles.active=dev > logs/common.out 2>&1 &
nohup java -Xmx256m -Xms128m -Xss256k -jar buyer-api-$version.jar --spring.profiles.active=dev > logs/buyer.out 2>&1 &
nohup java -Xmx256m -Xms128m -Xss256k -jar consumer-$version.jar --spring.profiles.active=dev > logs/consumer.out 2>&1 &
nohup java -Xmx256m -Xms128m -Xss256k -jar im-api-$version.jar --spring.profiles.active=dev > logs/im.out 2>&1 &
nohup java -Xmx256m -Xms128m -Xss256k -jar seller-api-$version.jar --spring.profiles.active=dev > logs/seller.out 2>&1 &UI部署
- 下载源码
cd /home/source
git clone https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git- 安装node yarn
yum update
yum install -y nodejs
yum install -y npm
npm install -g yarn
# #设置镜像
# yarn config set registry https://registry.npmmirror.com --global
# yarn config set disturl https://registry.npmmirror.com/dist --global
# 升级node
npm install -g n
n install v14.16.0- 编辑脚本
vi start-ui.sh- 脚本内容:
#代码目录
code_path=/home/source/lilishop-ui
cd ${code_path}
git checkout master
git pull
cd ${code_path}/manager
yarn install
yarn build
cd ${code_path}/seller
yarn install
yarn build
cd ${code_path}/buyer
yarn install
yarn build
# 新增:IM客服聊天模块
cd ${code_path}/im
yarn install
yarn build- 执行脚本
sh start-ui.shNginx
- 安装nginx
sudo yum install -y nginx- Nginx 示例配置文件
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
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 /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
# 开启gzip
gzip on;
# 启用gzip压缩的最小文件;小于设置值的文件将不会被压缩
gzip_min_length 1k;
# gzip 压缩级别 1-10
gzip_comp_level 2;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
#http强制跳转 https
server {
listen 80;
server_name pickmall.cn;
rewrite ^(.*)$ https://$host$1 permanent;
location ~ / {
index index.html index.php index.htm;
}
}
#管理端
server {
listen 443 ssl;
ssl_certificate "/etc/nginx/ssl/pickmall.cn.pem";
ssl_certificate_key "/etc/nginx/ssl/pickmall.cn.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
include /etc/nginx/default.d/*.conf;
server_name admin-b2b2c.pickmall.cn;
try_files $uri $uri/ /index.html;
root /home/source/lilishop-ui/manager/dist;
}
#商家端
server {
listen 443 ssl;
ssl_certificate "/etc/nginx/ssl/pickmall.cn.pem";
ssl_certificate_key "/etc/nginx/ssl/pickmall.cn.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
include /etc/nginx/default.d/*.conf;
server_name store-b2b2c.pickmall.cn;
try_files $uri $uri/ /index.html;
root /home/source/lilishop-ui/seller/dist;
}
#h5端
server {
listen 443 ssl;
ssl_certificate "/etc/nginx/ssl/pickmall.cn.pem";
ssl_certificate_key "/etc/nginx/ssl/pickmall.cn.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
include /etc/nginx/default.d/*.conf;
server_name m-b2b2c.pickmall.cn;
try_files $uri $uri/ /index.html;
root /home/source/h5;
}
#PC端
server {
listen 443 ssl;
ssl_certificate "/etc/nginx/ssl/pickmall.cn.pem";
ssl_certificate_key "/etc/nginx/ssl/pickmall.cn.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
include /etc/nginx/default.d/*.conf;
server_name pc-b2b2c.pickmall.cn;
try_files $uri $uri/ /index.html;
root /home/source/lilishop-ui/buyer/dist;
}
#IM
server {
listen 443 ssl;
ssl_certificate "/etc/nginx/ssl/pickmall.cn.pem";
ssl_certificate_key "/etc/nginx/ssl/pickmall.cn.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
include /etc/nginx/default.d/*.conf;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
server_name im.pickmall.cn;
try_files $uri $uri/ /index.html;
root /home/source/lili-shop-ui/im/dist;
}
#admin-api
server {
listen 443 ssl;
ssl_certificate "/etc/nginx/ssl/pickmall.cn.pem";
ssl_certificate_key "/etc/nginx/ssl/pickmall.cn.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
include /etc/nginx/default.d/*.conf;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
server_name admin-api.pickmall.cn;
location / {
proxy_pass http://127.0.0.1:8887;
}
}
#buyer-api
server {
listen 443 ssl;
ssl_certificate "/etc/nginx/ssl/pickmall.cn.pem";
ssl_certificate_key "/etc/nginx/ssl/pickmall.cn.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
include /etc/nginx/default.d/*.conf;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
server_name buyer-api.pickmall.cn;
location / {
proxy_pass http://127.0.0.1:8888;
}
}
#im-api
server {
listen 443 ssl;
ssl_certificate "/etc/nginx/ssl/pickmall.cn.pem";
ssl_certificate_key "/etc/nginx/ssl/pickmall.cn.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
include /etc/nginx/default.d/*.conf;
server_name im-api.pickmall.cn;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://127.0.0.1:8885;
}
}
}- nginx 启动
service nginx restart代码更新部署
cd /home/source
sh pg_start_api1.sh
sh start-ui.sh