VortMall 企业版部署指南
VortMall 企业版部署指南
文档说明
适用场景:日活用户(DAU)> 50,000 的生产环境,采用 K8s(ACK Pro 版)部署,云 RDS 高可用 + 只读实例,核心服务 2+ 副本。
读者对象:客户运维人员。
约定:
<尖括号>表示需要替换为实际值的占位符- 命令示例中
#开头的行为注释,不需要执行 - 所有服务器默认使用 Linux(CentOS 7+ / Ubuntu 20+ / Alibaba Cloud Linux 3)
⚠ 密码安全提醒(1/3):本文档涉及多个组件的账号密码。所有密码必须在部署前确定,使用至少 16 位强密码(含大小写字母 + 数字 + 符号),严禁使用默认密码上线。
一、架构总览
┌──────────────────────────────────────────────────────┐
│ 公网入口 │
│ 域名 → WAF → CLB/ALB → ACK Ingress / 外部 Nginx │
└──────────────────────────┬───────────────────────────┘
│
┌──────────────────────────────────────────────────────────────────┐
│ ACK Pro 集群(3 Worker,跨 2 可用区) │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Gateway │ │ Order │ │ Payment │ │ Product │ ...×17 │
│ │ ×1~2 │ │ ×2 │ │ ×2 │ │ ×2 │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │ │
│ └───────────┴───────────┴───────────┘ │
│ Pod 反亲和性 │
│ 同一服务的副本分散到不同节点 │
└──────────────────────────┬───────────────────────────────────────┘
│ 内网
┌───────────────────────────────┼───────────────────────────────┐
│ │ │
┌─────┴──────┐ ┌─────────┴──────────┐ ┌───────┴───────┐
│ 云 RDS │ │ 中间件 ECS ×2 │ │ 云 Redis 4G │
│ MySQL 8.0 │ │ Nacos RocketMQ │ │ 主从版 │
│ 4C8G 高可用 │ │ Seata XXL-Job │ └───────────────┘
│ + 只读实例 │ │ MinIO EMQX │
└─────────────┘ │ ES Canal │ ┌───────────────┐
│ SkyWalking Logstash│ │ OSS │
└────────────────────┘ │ 图片/文件存储 │
└───────────────┘
企业版核心特点:
| 特性 | 说明 |
|---|---|
| ACK Pro 版 | 增强调度能力、安全审计、SLA 保障 |
| 跨可用区部署 | 3 台 Worker 分布在 2 个可用区,单 AZ 故障不影响服务 |
| 核心服务多副本 | Gateway、Order、Payment、Product、User 等核心服务 ≥ 2 副本 |
| Pod 反亲和性 | 同一服务的副本调度到不同节点,避免单点故障 |
| RDS 高可用 + 只读实例 | 主从自动切换 + 读写分离,降低主库压力 |
| Redis 4G 主从 | 更大缓存容量,主从高可用 |
| WAF 防护 | 防 SQL 注入、CC 攻击、恶意爬虫 |
| 2 台中间件 ECS | 中间件资源更充裕,互为备份 |
二、采购清单(阿里云)
| 产品 | 规格 | 数量 | 用途 | 购买链接 |
|---|---|---|---|---|
| ACK Pro 托管版 | Pro 版 | 1 集群 | 增强调度、安全审计 | ACK 控制台 |
| ECS(Worker) | 8C16G ecs.g7.2xlarge | 3 台 | 分布在 2 个可用区 | ECS 购买页 |
| ECS(中间件) | 8C32G ecs.g7.2xlarge,数据盘 500G ESSD | 2 台 | 中间件集群 | ECS 购买页 |
| RDS MySQL 8.0 | 4C8G 高可用版 + 200G ESSD | 1 | 主从自动切换 | RDS 购买页 |
| RDS 只读实例 | 2C4G | 1 | 读写分离 | RDS 购买页 |
| 云 Redis | 4G 标准版(主从) | 1 | 缓存 + 会话 | Redis 购买页 |
| OSS | 标准型 + 低频型 | 1 | 图片/文件存储 | OSS 控制台 |
| CLB | 标准型 | 1 | 负载均衡 | SLB 控制台 |
| EIP | 固定 10~20Mbps | 1 | 公网访问 | |
| WAF | 基础版 | 1 | 防 SQL 注入、CC 攻击 | WAF 控制台 |
公共配套:
- 域名:至少 1 个(.com / .cn),需完成 ICP 备案(周期 7~20 个工作日),建议采购服务器时同步提交
- SSL 证书:推荐通配符证书(¥1,000~3,000/年),可覆盖
*.example.com下所有子域名 - CDN(按需):商品图片多、全国访问要求高时开通,将 OSS 图片通过 CDN 加速
三、部署前准备
3.1 环境检查清单
| 检查项 | 要求 | 检查命令 |
|---|---|---|
| 操作系统 | CentOS 7+ / Ubuntu 20+ / Alibaba Cloud Linux 3 | cat /etc/os-release |
| Docker | 24.0+ | docker --version |
| Docker Compose | v2.20+ | docker compose version |
| kubectl | 1.28+ | kubectl version --client |
| 可用内存 | 中间件 ECS ≥ 32G | free -h |
| 磁盘 | 中间件数据盘 ≥ 500G SSD | df -h |
| 时区 | Asia/Shanghai | timedatectl |
| 文件描述符 | ≥ 65535 | ulimit -n |
3.2 需要提前准备的信息
| 信息 | 说明 | 示例 |
|---|---|---|
| ACK Worker 内网 IP | 3 台 Worker 节点内网 IP | 10.0.0.11、10.0.0.12、10.0.0.13 |
| 中间件 ECS 内网 IP | 2 台中间件 ECS 内网 IP | 10.0.0.21、10.0.0.22 |
| 中间件 ECS 公网 IP | 管理访问 | 47.100.xxx.xxx |
| 域名 | 已备案、已做 DNS 解析 | mall.example.com |
| SSL 证书文件 | .pem + .key | |
| RDS 内网连接地址 | 购买后在控制台获取 | rm-xxxxx.mysql.rds.aliyuncs.com |
| RDS 只读实例地址 | 购买后在控制台获取 | rr-xxxxx.mysql.rds.aliyuncs.com |
| Redis 内网连接地址 | 购买后在控制台获取 | r-xxxxx.redis.rds.aliyuncs.com |
| 强密码清单 | 见下方密码覆盖范围 | 至少 16 位,含大小写+数字+符号 |
| 部署包 | 后端源码 + 前端构建产物 | 由我方提供 |
密码覆盖范围:
| 组件 | 密码设置方式 | 默认密码 |
|---|---|---|
| MySQL(云 RDS) | 购买时在阿里云控制台设置 | 客户自定义 |
| Redis(云 Redis) | 购买时在阿里云控制台设置 | 客户自定义 |
| Nacos | 登录后在控制台修改 | nacos/nacos |
| XXL-Job | 登录后在用户管理中修改 | admin/123456 |
| MinIO | 修改 docker-compose.yml 中环境变量 | vortmall/vortmall666 |
| EMQX | 登录 Dashboard 修改 | admin/vortmall666 |
| Elasticsearch | 修改 docker-compose.yml 中 ELASTIC_PASSWORD | elastic/vortmall666 |
| Canal | 修改配置文件 | canal/canal123 |
| 商城管理后台 | 登录后在系统设置中修改 | admin/123456 |
3.3 Docker 安装(中间件 ECS 执行)
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
systemctl start docker && systemctl enable docker
docker --version && docker compose version
3.4 操作系统调优(中间件 ECS 执行)
cat >> /etc/sysctl.conf << 'EOF'
vm.max_map_count = 262144
vm.swappiness = 10
net.core.somaxconn = 32768
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5
fs.file-max = 1048576
EOF
sysctl -p
cat >> /etc/security/limits.conf << 'EOF'
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
EOF
3.5 Docker 守护进程优化(中间件 ECS 执行)
mkdir -p /etc/docker
cat > /etc/docker/daemon.json << 'EOF'
{
"log-driver": "json-file",
"log-opts": { "max-size": "50m", "max-file": "3" },
"storage-driver": "overlay2",
"live-restore": true,
"max-concurrent-downloads": 10,
"registry-mirrors": ["https://mirror.ccs.tencentyun.com"]
}
EOF
systemctl daemon-reload && systemctl restart docker
四、部署步骤
⚠ 密码安全提醒(2/3):以下步骤中涉及的所有密码,必须使用预先确定的强密码。严禁将默认密码带到生产环境。
步骤 1:配置阿里云 RDS MySQL
登录 RDS 控制台,完成以下配置:
- 创建数据库账号(建议用户名:
vortmall,密码:自定义强密码) - 字符集设为
utf8mb4,排序规则utf8mb4_unicode_ci - 白名单添加 ACK Worker 和中间件 ECS 的内网 IP 段(如
10.0.0.0/8) - 开启慢查询日志(阈值 1s)
- 记录内网连接地址和端口
验证:
mysql -h <RDS内网地址> -P 3306 -u vortmall -p -e "SELECT 1"
预期输出包含 1,表示连接成功。
步骤 2:配置阿里云 Redis
登录 Redis 控制台,完成以下配置:
- 设置访问密码(强密码)
- 白名单添加 ACK Worker 和中间件 ECS 的内网 IP 段
-
maxmemory-policy设为allkeys-lru - 记录内网连接地址和端口
验证:
redis-cli -h <Redis内网地址> -p 6379 -a <Redis密码> ping
预期输出 PONG。
步骤 3:配置阿里云 OSS
登录 OSS 控制台,完成以下配置:
- 创建 Bucket(地域与 ECS 一致,权限设为"私有")
- 创建 RAM 子账号,仅授予该 Bucket 的 OSS 读写权限
- 记录 AccessKey ID / AccessKey Secret / Bucket 名称 / Endpoint
验证:在 OSS 控制台上传一张测试图片,确认可以通过内网 Endpoint 访问。
步骤 4:准备中间件服务器
将部署文件上传到 2 台中间件 ECS。企业版使用 2 台中间件 ECS,建议分配如下:
| 中间件 ECS-1 | 中间件 ECS-2 |
|---|---|
| Nacos | Elasticsearch |
| RocketMQ(NameServer + Broker) | Kibana |
| Seata | Logstash |
| XXL-Job | Canal |
| MinIO | SkyWalking OAP |
| EMQX | SkyWalking UI |
以上为建议分配,可根据实际资源情况调整。如果负载不高,也可以全部部署在一台上。
分别上传部署文件:
scp -r deployment/DockerCompose/ root@<中间件ECS-1内网IP>:/opt/vortmall/
scp -r deployment/DockerCompose/ root@<中间件ECS-2内网IP>:/opt/vortmall/
步骤 5:修改中间件默认密码
此步骤必须在启动中间件之前完成。
登录中间件 ECS,编辑 /opt/vortmall/DockerCompose/docker-compose.yml,替换以下默认密码:
| 配置项 | 默认值 | 操作 |
|---|---|---|
MINIO_ROOT_USER / MINIO_ROOT_PASSWORD | vortmall / vortmall666 | 替换为自定义强密码 |
ELASTIC_PASSWORD | vortmall666 | 替换为自定义强密码 |
Redis 和 MySQL 使用云服务,不在此处配置。Nacos 和 XXL-Job 的密码在启动后通过 Web 控制台修改(见步骤 9)。
验证:grep 确认 docker-compose.yml 中不再包含 vortmall666:
grep -n "vortmall666" /opt/vortmall/DockerCompose/docker-compose.yml
预期无输出。
步骤 6:启动中间件
登录中间件 ECS-1:
ssh root@<中间件ECS-1内网IP>
cd /opt/vortmall/DockerCompose
# 替换 IP 占位符
sed -i "s/{{PUBLIC_IP}}/<中间件ECS-1内网IP>/g" docker-compose.yml
sed -i "s/{{PUBLIC_IP}}/<中间件ECS-1内网IP>/g" rocketMQ/data/broker/conf/broker.conf
# 启动非数据库中间件
docker compose up -d nacos namesrv broker rocketmq-dashboard xxl-job seata-server minio emqx
登录中间件 ECS-2(如需部署 ES 全家桶):
ssh root@<中间件ECS-2内网IP>
cd /opt/vortmall/DockerCompose
sed -i "s/{{PUBLIC_IP}}/<中间件ECS-2内网IP>/g" docker-compose.yml
docker compose up -d es kibana logstash canal-server skywalking-oap skywalking-ui
步骤 7:验证中间件
等待约 2~3 分钟后,逐项检查:
| 服务 | 验证方式 | 预期 |
|---|---|---|
| Nacos | curl -s http://<中间件ECS-1内网IP>:8848/nacos/v1/ns/service/list | HTTP 200 |
| RocketMQ | curl -s http://<中间件ECS-1内网IP>:8080/cluster/list.query | 包含 broker 信息 |
| XXL-Job | 浏览器访问 http://<中间件ECS-1内网IP>:8082/xxl-job-admin | 登录页 |
| MinIO | curl -s http://<中间件ECS-1内网IP>:9000/minio/health/live | HTTP 200 |
| EMQX | 浏览器访问 http://<中间件ECS-1内网IP>:18083 | Dashboard 页面 |
| ES | curl -s -u elastic:<ES密码> http://<中间件ECS-2内网IP>:9200/_cluster/health | 包含 status 字段 |
全部验证通过后再进入下一步。如果某项失败,执行
docker compose ps检查对应容器状态和日志。
步骤 8:初始化数据库
mysql -h <RDS内网地址> -P 3306 -u vortmall -p --default-character-set=utf8mb4 < db/version/mysql/demo.sql
初次体验使用
demo.sql(含演示数据),正式商用使用pure.sql(空库)。
验证(应有 15 个 vortmall_* 数据库):
mysql -h <RDS内网地址> -P 3306 -u vortmall -p -e "
SELECT TABLE_SCHEMA, COUNT(*) AS '表数量'
FROM information_schema.TABLES
WHERE TABLE_SCHEMA LIKE 'vortmall_%'
GROUP BY TABLE_SCHEMA;
"
步骤 9:修改中间件 Web 控制台默认密码
| 组件 | 访问地址 | 默认账号 | 操作 |
|---|---|---|---|
| Nacos | http://<中间件ECS-1内网IP>:8848/nacos | nacos/nacos | 登录后修改密码 |
| XXL-Job | http://<中间件ECS-1内网IP>:8082/xxl-job-admin | admin/123456 | 登录 → 用户管理 → 修改密码 |
| EMQX | http://<中间件ECS-1内网IP>:18083 | admin/vortmall666 | 登录 Dashboard 修改密码 |
验证:用新密码重新登录以上控制台,确认均可正常访问。
步骤 10:配置 Nacos
- 登录
http://<中间件ECS-1内网IP>:8848/nacos - 左侧菜单 → 命名空间 → 新建命名空间:
- 命名空间 ID:
public - 命名空间名:
VortMall
- 命名空间 ID:
- 切换到
public命名空间 → 配置管理 → 配置列表 → 创建配置:
Data ID:datasource-multiple.yml,Group:DEFAULT_GROUP,格式:YAML
spring:
datasource:
dynamic:
primary: master
strict: true
datasource:
master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://<RDS内网地址>:3306/${vortmall.datasource.db-name}?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
username: <数据库用户名>
password: <数据库密码>
${vortmall.datasource.db-name}是变量,每个服务自动填入自己的库名,不需要替换。只需将<RDS内网地址>、<数据库用户名>、<数据库密码>替换为实际值。
验证:在 Nacos 配置列表中,public 命名空间下能看到 datasource-multiple.yml 配置。
步骤 11:配置 XXL-Job
- 登录
http://<中间件ECS-1内网IP>:8082/xxl-job-admin - 确认执行器管理页面可正常访问
- 后端服务启动后,执行器会自动注册
验证:XXL-Job 管理后台可正常登录,页面无报错。
步骤 12:构建镜像
# 构建全部后端镜像(17 个)
cd deployment/k8s
bash build.sh
# 构建前端镜像
cd <项目根目录>
docker build -f deployment/docker/frontend/Dockerfile -t vortmall/vortmall-frontend:latest .
验证:
docker images | grep vortmall
预期列出 18 个镜像(17 个后端 + 1 个前端)。
步骤 13:推送镜像到阿里云 ACR
先在 ACR 控制台 创建命名空间和镜像仓库,然后推送:
# 登录 ACR
docker login registry.cn-hangzhou.aliyuncs.com -u <阿里云账号>
# 推送后端镜像
cd deployment/k8s
REGISTRY=registry.cn-hangzhou.aliyuncs.com/<命名空间> TAG=v1.0.0 bash build.sh --push
# 推送前端镜像
docker tag vortmall/vortmall-frontend:latest registry.cn-hangzhou.aliyuncs.com/<命名空间>/vortmall-frontend:v1.0.0
docker push registry.cn-hangzhou.aliyuncs.com/<命名空间>/vortmall-frontend:v1.0.0
将
cn-hangzhou替换为你的 ACR 所在地域,<命名空间>替换为你在 ACR 创建的命名空间。
验证:在 ACR 控制台的镜像仓库中,确认 18 个镜像均已上传。
步骤 14:修改 ConfigMap
编辑 deployment/k8s/configmap.yaml,将所有连接信息改为实际值:
data:
NACOS_ADDR: "<中间件ECS-1内网IP>:8848"
NACOS_NAMESPACE: "public"
DB_HOST: "<RDS内网地址>"
DB_PORT: "3306"
DB_USERNAME: "<数据库用户名>"
DB_PASSWORD: "<数据库密码>"
REDIS_HOST: "<Redis内网地址>"
REDIS_PORT: "6379"
REDIS_PASSWORD: "<Redis密码>"
ROCKETMQ_NAMESRV: "<中间件ECS-1内网IP>:9876"
SEATA_ADDR: "<中间件ECS-1内网IP>:8091"
XXLJOB_ADDR: "http://<中间件ECS-1内网IP>:8082/xxl-job-admin"
MINIO_ENDPOINT: "http://<中间件ECS-1内网IP>:9000"
MINIO_ACCESS_KEY: "<MinIO AccessKey>"
MINIO_SECRET_KEY: "<MinIO SecretKey>"
EMQX_HOST: "<中间件ECS-1内网IP>"
ES_HOST: "<中间件ECS-2内网IP>"
ES_PORT: "9200"
ES_PASSWORD: "<ES密码>"
SW_AGENT_COLLECTOR_BACKEND_SERVICES: "<中间件ECS-2内网IP>:11800"
LOGSTASH_HOST: "<中间件ECS-2内网IP>"
LOGSTASH_PORT: "5001"
JAVA_OPTS: "-XX:InitialRAMPercentage=25.0 -XX:MaxRAMPercentage=60.0 -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError"
TZ: "Asia/Shanghai"
验证:确认文件中不再包含未替换的占位符:
grep -n "<" deployment/k8s/configmap.yaml | grep -v "#"
步骤 15:修改服务镜像地址
将所有服务 YAML 中的镜像地址改为 ACR 私有仓库地址:
cd deployment/k8s/services
sed -i 's|image: vortmall/|image: registry.cn-hangzhou.aliyuncs.com/<命名空间>/|g' *.yaml
验证:
grep "image:" deployment/k8s/services/*.yaml
预期所有镜像地址以 registry.cn-hangzhou.aliyuncs.com/<命名空间>/ 开头。
步骤 16:K8s 部署与验证
cd deployment/k8s
# 一键部署
bash deploy.sh
# 等待全部 Pod 就绪(超时 5 分钟)
kubectl wait --for=condition=Ready pods --all -n vortmall --timeout=300s
# 查看状态
bash deploy.sh --status
验证:
kubectl get pods -n vortmall
所有 Pod 应为 Running 状态,重启次数为 0。
Pod 异常时的快速排查:
# 查看事件
kubectl describe pod <pod名称> -n vortmall
# 查看日志
kubectl logs <pod名称> -n vortmall --tail=200
| 状态 | 常见原因 | 解决 |
|---|---|---|
| ImagePullBackOff | 镜像地址或仓库凭证错误 | 检查镜像地址和 ACR 拉取凭证 |
| CrashLoopBackOff | 应用启动失败(通常连不上中间件) | 查日志,检查 ConfigMap 地址 |
| Pending | 节点资源不足 | 增加节点或降低 requests |
| OOMKilled | 内存不足 | 调高 resources.limits.memory |
步骤 17:核心服务扩到 2+ 副本 ★
以下步骤 17~19 为企业版独有。
确认步骤 16 所有服务正常运行后,将核心服务副本数扩到 2:
for svc in gateway order payment product user; do
kubectl scale deployment/vortmall-biz-${svc} -n vortmall --replicas=2 2>/dev/null
kubectl scale deployment/vortmall-${svc} -n vortmall --replicas=2 2>/dev/null
done
验证:
kubectl get deployment -n vortmall | grep -E "gateway|order|payment|product|user"
预期 READY 列显示 2/2。如果副本未就绪,检查节点资源是否充足:
kubectl top nodes
步骤 18:配置 Pod 反亲和性 ★
在核心服务的 YAML 中添加 Pod 反亲和性配置,使同一服务的多个副本分散到不同节点,避免单节点故障导致服务不可用。
以 vortmall-biz-order 为例,编辑 deployment/k8s/services/vortmall-biz-order.yaml,在 spec.template.spec 下添加:
spec:
template:
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: vortmall-biz-order
topologyKey: kubernetes.io/hostname
对以下核心服务重复上述操作(注意修改 matchLabels.app 为对应服务名):
| 服务 YAML | matchLabels.app |
|---|---|
vortmall-gateway.yaml | vortmall-gateway |
vortmall-biz-order.yaml | vortmall-biz-order |
vortmall-biz-payment.yaml | vortmall-biz-payment |
vortmall-biz-product.yaml | vortmall-biz-product |
vortmall-biz-user.yaml | vortmall-biz-user |
修改完成后重新 apply:
cd deployment/k8s/services
kubectl apply -f vortmall-gateway.yaml
kubectl apply -f vortmall-biz-order.yaml
kubectl apply -f vortmall-biz-payment.yaml
kubectl apply -f vortmall-biz-product.yaml
kubectl apply -f vortmall-biz-user.yaml
验证:确认同一服务的两个 Pod 分布在不同节点上:
kubectl get pods -n vortmall -o wide | grep -E "gateway|order|payment|product|user"
预期同一服务的 2 个 Pod 在 NODE 列显示不同的节点名。
步骤 19:配置 RDS 只读实例 ★
登录 RDS 控制台,为主实例创建只读实例:
- 规格:2C4G
- 确认只读实例与主实例在同一 VPC
- 记录只读实例的内网连接地址
RDS 只读实例会自动与主实例保持数据同步。可以在应用中对读请求使用只读实例地址,以降低主库压力。
在 Nacos 的 datasource-multiple.yml 配置中添加只读数据源(public 命名空间):
spring:
datasource:
dynamic:
primary: master
strict: true
datasource:
master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://<RDS主实例内网地址>:3306/${vortmall.datasource.db-name}?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
username: <数据库用户名>
password: <数据库密码>
slave:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://<RDS只读实例内网地址>:3306/${vortmall.datasource.db-name}?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
username: <数据库用户名>
password: <数据库密码>
配置发布后,应用会自动从 Nacos 拉取新配置。需要逐个重启业务服务使读写分离生效:
kubectl rollout restart deployment -n vortmall
验证:
# 确认所有服务重启完成
kubectl rollout status deployment -n vortmall --timeout=300s
# 检查服务日志,确认数据源加载成功
kubectl logs -l app=vortmall-biz-order -n vortmall --tail=50 | grep -i "datasource"
五、域名与 HTTPS
方案一:外部 Nginx(推荐)
upstream vortmall_frontend {
server <Worker节点1内网IP>:30080 max_fails=3 fail_timeout=30s;
server <Worker节点2内网IP>:30080 max_fails=3 fail_timeout=30s;
server <Worker节点3内网IP>:30080 max_fails=3 fail_timeout=30s;
keepalive 64;
}
server {
listen 80;
server_name <域名>;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name <域名>;
ssl_certificate /etc/nginx/ssl/<域名>.pem;
ssl_certificate_key /etc/nginx/ssl/<域名>.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
client_max_body_size 100m;
location / {
proxy_pass http://vortmall_frontend;
proxy_http_version 1.1;
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 https;
proxy_set_header Connection "";
}
location /ws {
proxy_pass http://vortmall_frontend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|webp|avif)$ {
proxy_pass http://vortmall_frontend;
expires 7d;
add_header Cache-Control "public, immutable";
access_log off;
}
}
方案二:K8s Ingress(ACK 原生)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: vortmall-ingress
namespace: vortmall
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
spec:
ingressClassName: nginx
tls:
- hosts:
- <域名>
secretName: vortmall-tls
rules:
- host: <域名>
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: vortmall-frontend
port:
number: 80
创建 TLS Secret:
kubectl create secret tls vortmall-tls --cert=<域名>.pem --key=<域名>.key -n vortmall
路由映射
前端容器内部已处理全部路由,外层代理不需要按路径拆分:
| URL 路径 | 对应页面 |
|---|---|
https://<域名>/ | PC 商城(Nuxt 3) |
https://<域名>/admin | 管理后台(Vue 3) |
https://<域名>/mobile | H5 移动端(UniApp) |
https://<域名>/api/* | 前台 API → Gateway |
https://<域名>/adminapi/* | 后台 API → Gateway |
六、部署验证
6.1 中间件连通性
| 检查项 | 方法 | 预期 |
|---|---|---|
| MySQL | mysql -h <RDS内网地址> -u vortmall -p -e "SELECT 1" | 返回 1 |
| Redis | redis-cli -h <Redis内网地址> -a <密码> ping | PONG |
| Nacos 控制台 | 浏览器 http://<中间件ECS-1内网IP>:8848/nacos | 能登录 |
| Nacos 服务数 | 控制台 → 服务列表(public 命名空间) | ≥ 17 个服务已注册 |
| RocketMQ | curl -s http://<中间件ECS-1内网IP>:8080/cluster/list.query | 包含 broker 信息 |
6.2 服务健康
kubectl get pods -n vortmall
所有服务应为 Running,重启次数为 0。核心服务副本数应为 2。
6.3 前端页面
| 页面 | 地址 | 预期 |
|---|---|---|
| PC 商城 | https://<域名>/ | 页面正常渲染 |
| 管理后台 | https://<域名>/admin | 登录页正常显示 |
| H5 移动端 | https://<域名>/mobile | 页面正常渲染 |
6.4 API 接口
curl -s https://<域名>/api/actuator/health
预期输出:{"status":"UP"}
6.5 企业版专项验证
| 检查项 | 方法 | 预期 |
|---|---|---|
| 多副本 | kubectl get deploy -n vortmall | grep -E "gateway|order|payment|product|user" | READY 列显示 2/2 |
| 反亲和性 | kubectl get pods -n vortmall -o wide | grep order | 2 个 Pod 在不同节点 |
| 只读实例 | mysql -h <只读实例地址> -u vortmall -p -e "SELECT 1" | 返回 1 |
6.6 一键验证脚本
# 验证中间件
bash verify-deployment.sh <中间件ECS-1内网IP>
# 验证全链路
bash verify-deployment.sh <域名>
七、安全加固
部署验证通过后、正式上线前必须完成。
⚠ 密码安全提醒(3/3):以下是最终安全检查。确认所有默认密码已修改,所有敏感端口已关闭,WAF 已开启。
7.1 密码最终确认
| 组件 | 默认密码 | 确认状态 |
|---|---|---|
| MySQL(云 RDS) | 客户自设 | ☐ 已设置强密码 |
| Redis(云 Redis) | 客户自设 | ☐ 已设置强密码 |
| MinIO | vortmall/vortmall666 | ☐ 已修改 |
| EMQX | admin/vortmall666 | ☐ 已修改 |
| Nacos | nacos/nacos | ☐ 已修改 |
| XXL-Job | admin/123456 | ☐ 已修改 |
| ES | elastic/vortmall666 | ☐ 已修改 |
| Canal | canal/canal123 | ☐ 已修改 |
| 商城管理后台 | admin/123456 | ☐ 已修改 |
修改密码后,同步更新 ConfigMap / Nacos 配置中对应的连接信息,并重启相关服务。
7.2 网络隔离(安全组)
公网入方向(仅开放必要端口):
| 端口 | 来源 | 说明 |
|---|---|---|
| 80 / 443 | 0.0.0.0/0 | HTTP / HTTPS |
| 22 | 办公 IP 段 | SSH(限定来源) |
内网入方向:
| 端口 | 来源 | 说明 |
|---|---|---|
| 全部 | VPC 网段(如 10.0.0.0/8) | 内网服务互通 |
中间件端口(3306、6379、8848、9876 等)绝不对公网开放。
7.3 Nginx 安全加固
# 隐藏版本号
server_tokens off;
# API 限速
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/s;
location /api {
limit_req zone=api burst=60 nodelay;
proxy_pass http://vortmall_frontend;
}
# 拦截非预期 Host
server {
listen 80 default_server;
listen 443 ssl default_server;
ssl_certificate /etc/nginx/ssl/<域名>.pem;
ssl_certificate_key /etc/nginx/ssl/<域名>.key;
return 444;
}
7.4 WAF 配置(企业版)
登录 WAF 控制台,完成以下配置:
接入配置:
- 将域名 CNAME 解析到 WAF 提供的防护地址
- 源站地址填写 CLB/SLB 的公网 IP
防护策略:
| 防护项 | 建议配置 | 说明 |
|---|---|---|
| Web 应用防护 | 开启,规则引擎「严格模式」 | 防 SQL 注入、XSS、命令注入等 OWASP Top 10 攻击 |
| CC 安全防护 | 开启,紧急模式阈值建议 1000 QPS | 防 CC 攻击导致后端过载 |
| 扫描防护 | 开启 | 防自动化扫描工具探测 |
| IP 黑名单 | 按需配置 | 封禁已知恶意 IP |
| 区域封禁 | 按需配置 | 如仅面向国内市场,可封禁海外访问 |
验证:
# 测试 SQL 注入防护(应被 WAF 拦截)
curl -s "https://<域名>/api/test?id=1' OR '1'='1"
预期返回 WAF 拦截页面或 403 状态码,而非正常 API 响应。
八、日常运维
8.1 常用操作
| 操作 | 命令 |
|---|---|
| 查看日志 | kubectl logs -f deploy/vortmall-biz-order -n vortmall |
| 最后 200 行 | kubectl logs --tail=200 <pod名称> -n vortmall |
| 重启单个服务 | kubectl rollout restart deploy/vortmall-biz-order -n vortmall |
| 重启全部 | kubectl rollout restart deploy -n vortmall |
| 扩缩容 | kubectl scale deploy/vortmall-biz-order --replicas=3 -n vortmall |
| 资源占用 | kubectl top pods -n vortmall |
| 进入容器 | kubectl exec -it <pod名称> -n vortmall -- sh |
8.2 版本升级(滚动更新)
企业版核心服务有 2+ 副本,使用滚动更新策略,可实现零停机升级:
# 1. 备份数据库(通过 RDS 控制台或手动)
mysqldump -h <RDS内网地址> -u vortmall -p --all-databases --single-transaction --quick | gzip > backup_$(date +%Y%m%d).sql.gz
# 2. 执行增量 SQL(如有)
mysql -h <RDS内网地址> -u vortmall -p < db/update/update.sql
# 3. 构建新版本镜像并推送
cd deployment/k8s
REGISTRY=registry.cn-hangzhou.aliyuncs.com/<命名空间> TAG=v1.1.0 bash build.sh --push
# 4. 滚动更新单个服务
kubectl set image deployment/vortmall-biz-order \
vortmall-biz-order=registry.cn-hangzhou.aliyuncs.com/<命名空间>/vortmall-biz-order:v1.1.0 \
-n vortmall
# 5. 监控更新进度
kubectl rollout status deployment/vortmall-biz-order -n vortmall
8.3 分批发布(企业版推荐)
对于多副本服务,建议按以下顺序分批更新,降低发布风险:
| 批次 | 服务 | 说明 |
|---|---|---|
| 第 1 批 | vortmall-biz-file、vortmall-biz-content、vortmall-biz-decoration | 低风险辅助服务 |
| 第 2 批 | vortmall-biz-product、vortmall-biz-user、vortmall-biz-logistics | 核心基础服务 |
| 第 3 批 | vortmall-biz-order、vortmall-biz-payment、vortmall-biz-marketing | 核心交易服务 |
| 第 4 批 | vortmall-gateway、vortmall-auth | 入口服务(最后更新) |
每批更新完成后,验证服务健康再继续下一批:
# 检查第 N 批服务状态
kubectl rollout status deployment/vortmall-biz-order -n vortmall --timeout=120s
# 快速验证 API 可用性
curl -s https://<域名>/api/actuator/health
8.4 滚动更新策略
建议在核心服务的 Deployment YAML 中配置滚动更新策略,确保更新期间始终有可用实例:
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
maxUnavailable: 0:更新期间不允许有不可用的 Pod,确保零停机maxSurge: 1:每次最多多创建 1 个新 Pod
8.5 回滚
# 回滚到上一版本
kubectl rollout undo deployment/vortmall-biz-order -n vortmall
# 查看回滚历史
kubectl rollout history deployment/vortmall-biz-order -n vortmall
# 回滚到指定版本
kubectl rollout undo deployment/vortmall-biz-order -n vortmall --to-revision=2
# 数据库回滚
gunzip < backup_20260327.sql.gz | mysql -h <RDS内网地址> -u vortmall -p
8.6 数据库备份
阿里云 RDS:
- 控制台 → 备份恢复 → 开启自动备份(保留 7 天)
- 开启 Binlog 备份
- 只读实例会自动同步主实例数据,无需单独备份
建议额外配置手动备份脚本作为双保险:
mysqldump -h <RDS内网地址> -u vortmall -p --all-databases --single-transaction --quick | gzip > backup_$(date +%Y%m%d).sql.gz
8.7 磁盘清理
docker image prune -a --filter "until=168h" -f
docker builder prune -f
find /opt/vortmall -name "*.log" -mtime +7 -delete
九、常见问题
9.1 Pod CrashLoopBackOff
Java 应用启动失败,通常是连不上中间件。
kubectl logs <pod名称> -n vortmall --tail=50
| 日志关键词 | 原因 | 解决 |
|---|---|---|
| Connection refused | 中间件未启动或地址错误 | 检查 ConfigMap 中的地址 |
| Access denied | 数据库账号密码错误 | 检查 ConfigMap 中的 DB_USERNAME/DB_PASSWORD |
| No DataSource | 数据库未初始化 | 确认 SQL 已导入 |
| Nacos connected failed | Nacos 地址或命名空间不匹配 | 检查 NACOS_ADDR 和 NACOS_NAMESPACE |
| OutOfMemoryError | 内存 limit 太低 | 调高 JAVA_OPTS 或 resources.limits.memory |
9.2 前端页面空白 / 404
# 检查前端 Pod 状态
kubectl get pods -n vortmall -l app=vortmall-frontend
# 检查前端文件是否存在
kubectl exec -it <frontend-pod> -n vortmall -- ls -la /usr/share/nginx/html/admin/
# 检查 API 代理连通性
kubectl exec -it <frontend-pod> -n vortmall -- curl -s http://vortmall-gateway:8000/actuator/health
9.3 Nacos 服务列表为空
# 确认命名空间 ID 一致(应为 "public")
curl -s 'http://<中间件ECS-1内网IP>:8848/nacos/v1/console/namespaces'
# 从 Worker 节点测试到 Nacos 的连通性
telnet <中间件ECS-1内网IP> 8848
telnet <中间件ECS-1内网IP> 9848
9.4 MySQL 连接数耗尽
企业版多副本下连接数压力更大,注意监控:
mysql -h <RDS内网地址> -u vortmall -p -e "SHOW STATUS LIKE 'Threads_connected';"
mysql -h <RDS内网地址> -u vortmall -p -e "SHOW PROCESSLIST;"
如需临时调整,在 RDS 控制台修改参数 max_connections。
9.5 Pod 反亲和性未生效
如果同一服务的两个 Pod 仍在同一节点:
# 检查节点资源
kubectl top nodes
# 检查 Pod 调度事件
kubectl describe pod <pod名称> -n vortmall | grep -A5 "Events"
常见原因:节点数不足(至少需要 2 个可调度节点)。preferredDuringSchedulingIgnoredDuringExecution 是软约束,资源不足时允许调度到同一节点。
附录 A:端口速查表
中间件端口
| 服务 | 端口 | 说明 |
|---|---|---|
| MySQL(云 RDS) | 3306 | 数据库 |
| Redis(云 Redis) | 6379 | 缓存 |
| Nacos | 8848, 9848 | 配置中心 + 服务发现 |
| RocketMQ NameServer | 9876 | MQ 名称服务 |
| RocketMQ Broker | 10909, 10911, 10912 | MQ Broker |
| RocketMQ Dashboard | 8080 | MQ 管理界面 |
| XXL-Job Admin | 8082 | 任务调度 |
| Seata | 7091, 8091 | 分布式事务 |
| MinIO | 9000 (API), 9001 (Console) | 对象存储 |
| EMQX | 1883 (MQTT), 18083 (Dashboard) | 消息 |
| ES | 9200, 9300 | 搜索引擎 |
| Kibana | 5601 | ES 可视化 |
| Logstash | 5001, 5044 | 日志收集 |
| Canal | 11111, 11112 | 数据同步 |
| SkyWalking OAP | 11800, 12800 | 链路追踪 |
| SkyWalking UI | 18080 | 链路追踪界面 |
应用服务端口
| 服务 | HTTP 端口 | XXL-Job 端口 | K8s NodePort |
|---|---|---|---|
| vortmall-frontend | 80 | - | 30080 |
| vortmall-gateway | 8000 | - | 30800 |
| vortmall-auth | 8001 | - | - |
| vortmall-biz-product | 19901 | - | - |
| vortmall-biz-payment | 19902 | 19702 | - |
| vortmall-biz-system | 19903 | - | - |
| vortmall-biz-marketing | 19904 | - | - |
| vortmall-biz-order | 19905 | 19705 | - |
| vortmall-biz-content | 19906 | - | - |
| vortmall-biz-organize | 19907 | - | - |
| vortmall-biz-logistics | 19908 | - | - |
| vortmall-biz-aftersales | 19909 | - | - |
| vortmall-biz-distribution | 19910 | - | - |
| vortmall-biz-decoration | 19911 | - | - |
| vortmall-biz-message | 19912 | - | - |
| vortmall-biz-user | 19913 | - | - |
| vortmall-biz-file | 19914 | - | - |
| vortmall-biz-pos | 19915 | - | - |
附录 B:服务列表
| 服务 | 注册名 | 数据库 | 说明 |
|---|---|---|---|
| Gateway | vortmall-gateway | - | API 网关 |
| Auth | vortmall-auth | - | 认证授权 |
| Product | vortmall-biz-product | vortmall_product | 商品、分类、品牌、规格 |
| Payment | vortmall-biz-payment | vortmall_payment | 支付、退款 |
| System | vortmall-biz-system | vortmall_system | 系统配置、菜单、权限 |
| Marketing | vortmall-biz-marketing | vortmall_marketing | 营销、优惠券、满减 |
| Order | vortmall-biz-order | vortmall_order | 订单、购物车、结算 |
| Content | vortmall-biz-content | vortmall_content | 文章、公告 |
| Organize | vortmall-biz-organize | vortmall_organize | 组织架构、店铺 |
| Logistics | vortmall-biz-logistics | vortmall_logistics | 物流、运费模板 |
| Aftersales | vortmall-biz-aftersales | vortmall_aftersales | 售后、退货 |
| Distribution | vortmall-biz-distribution | vortmall_distribution | 分销 |
| Decoration | vortmall-biz-decoration | vortmall_decoration | 页面装修 |
| Message | vortmall-biz-message | vortmall_message | 消息、通知、短信 |
| User | vortmall-biz-user | vortmall_user | 用户、会员 |
| File | vortmall-biz-file | vortmall_file | 文件上传 |
| POS | vortmall-biz-pos | vortmall_pos | 收银台、门店 |
赣公网安备36010902001041号