no message

main
HUOJIN\92525 2026-03-20 17:07:12 +08:00
parent ed80459d54
commit 29f15f67a5
18 changed files with 9196 additions and 1096 deletions

View File

@ -185,22 +185,6 @@ mybatis-plus:
minidao: minidao:
base-package: org.jeecg.modules.jmreport.*,org.jeecg.modules.drag.* base-package: org.jeecg.modules.jmreport.*,org.jeecg.modules.drag.*
jeecg: jeecg:
# AI集成
ai-chat:
enabled: true
model: deepseek-chat
apiKey: sk-d88f463e2eb04f59b0f6ed614c25b6b9
apiHost: https://api.deepseek.com/v1
timeout: 60
# AIRag向量库
ai-rag:
embed-store:
host: 127.0.0.1
port: 5432
database: postgres
user: postgres
password: postgres
table: embeddings
# 平台上线安全配置 # 平台上线安全配置
firewall: firewall:
# 数据源安全 (开启后Online报表和图表的数据源为必填) # 数据源安全 (开启后Online报表和图表的数据源为必填)
@ -266,17 +250,6 @@ jeecg:
api-key: ?? api-key: ??
# 应用秘钥 # 应用秘钥
secret-key: ?? secret-key: ??
#xxl-job配置
xxljob:
enabled: false
adminAddresses: http://127.0.0.1:9080/xxl-job-admin
appname: ${spring.application.name}
accessToken: ''
address: 127.0.0.1:30007
ip: 127.0.0.1
port: 30007
logPath: logs/cpte/job/jobhandler/
logRetentionDays: 30
#分布式锁配置 #分布式锁配置
redisson: redisson:
address: 47.117.45.79:6379 address: 47.117.45.79:6379

View File

@ -142,7 +142,7 @@ spring:
slow-sql-millis: 5000 slow-sql-millis: 5000
datasource: datasource:
master: master:
url: jdbc:mysql://10.254.27.192:3306/cpte-wms?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true url: jdbc:mysql://101.35.253:3306/cpte-wms?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
username: root username: root
password: cpte@123 password: cpte@123
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver

View File

@ -23,8 +23,8 @@ import java.util.Map;
* *
*/ */
@FeignClient( @FeignClient(
name = "wms-basic-service", name = "cpte-wms-basic",
url = "${feign.client.wms-basic.url:http://wms-basic-service:8001}", url = "${feign.client.wms-basic.url:}",
configuration = FeignClientConfiguration.class, configuration = FeignClientConfiguration.class,
fallbackFactory = BasicServiceFallbackFactory.class fallbackFactory = BasicServiceFallbackFactory.class
) )

View File

@ -250,18 +250,16 @@ knife4j:
# Feign 客户端配置(本地开发环境使用 localhost # Feign 客户端配置(本地开发环境使用 localhost
feign: feign:
client: client:
# Feign 全局配置
config: config:
default: default:
connectTimeout: 5000 connectTimeout: 5000
readTimeout: 10000 readTimeout: 10000
loggerLevel: BASIC loggerLevel: BASIC
# 本地开发环境服务地址配置
# 服务地址配置(与代码变量名匹配)
wms-basic: wms-basic:
url: http://localhost:8001/cpte-wms-basic url: http://localhost:8001/cpte-wms-basic
wms-inventory:
url: http://localhost:8004/cpte-wms-inventory
wms-schedule:
url: http://localhost:8005/cpte-wms-schedule
#第三方登录 #第三方登录
justauth: justauth:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,720 @@
# CPTE WMS 微服务架构文档
## 1. 架构概述
### 1.1 系统定位
CPTE WMS 是基于 Spring Boot 3.5.5 + Spring Cloud 2025.0.0 构建的仓库管理系统微服务架构,采用 Kubernetes 进行容器编排部署。
### 1.2 架构风格
- **微服务架构**: 业务按领域拆分为独立服务
- **服务网格**: 基于 Kubernetes Service 的服务发现
- **事件驱动**: Redis 发布订阅实现异步通信
- **容器化部署**: Docker + Kubernetes
---
## 2. 系统架构图
### 2.1 整体架构
```
┌────────────────────────────────────────────────────────────────────────────────┐
│ 外部访问层 │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ Nginx Ingress │ │
│ │ (负载均衡 / SSL 终止 / 路由) │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────┐
│ 应用服务层 │
│ ┌──────────────────────────────────────────────────────────────────────────┐ │
│ │ Namespace: cpte-wms │ │
│ │ │ │
│ │ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │ │
│ │ │ Basic Service │ │Inbound Service │ │Outbound Service│ │ │
│ │ │ 基础服务 │ │ 入库服务 │ │ 出库服务 │ │ │
│ │ │ Port: 8001 │ │ Port: 8002 │ │ Port: 8003 │ │ │
│ │ │ /cpte-wms-basic│ │/cpte-wms-inbound│ │/cpte-wms-outbound│ │ │
│ │ └───────┬────────┘ └───────┬────────┘ └───────┬────────┘ │ │
│ │ │ │ │ │ │
│ │ │ ┌──────────────┼───────────────┐ │ │ │
│ │ │ │ │ │ │ │ │
│ │ ▼ ▼ ▼ ▼ ▼ │ │
│ │ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │ │
│ │ │Inventory Service│ │Schedule Service│ │ System Service │ │ │
│ │ │ 库存服务 │ │ 调度服务 │ │ 系统服务 │ │ │
│ │ │ Port: 8004 │ │ Port: 8005 │ │ Port: 8000 │ │ │
│ │ │/cpte-wms-inventory│ │/cpte-wms-schedule│ │/cpte-wms │ │ │
│ │ └────────────────┘ └────────────────┘ └────────────────┘ │ │
│ │ │ │
│ │ ┌────────────────────────────────────────────────────────────────────┐ │ │
│ │ │ cpte-wms-api (共享层) │ │ │
│ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │
│ │ │ │ Feign Client│ │ DTO │ │ 分布式锁 │ │ 工具类 │ │ │ │
│ │ │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │
│ │ └────────────────────────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────┐
│ 基础设施层 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ MySQL │ │ Redis │ │ MinIO │ │ Nacos │ │
│ │ 数据持久化 │ │ 缓存/锁/消息 │ │ 文件存储 │ │ 配置中心 │ │
│ │ Port: 53306 │ │ Port: 6379 │ │ │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
└────────────────────────────────────────────────────────────────────────────────┘
```
### 2.2 服务拓扑图
```
┌─────────────────┐
│ System Service │
│ 系统服务 │
│ Port: 8000 │
└────────┬────────┘
┌───────────────────────────┼───────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Basic Service │◄───────▶│Inbound Service │◄───────▶│Outbound Service │
│ 基础服务 │ Feign │ 入库服务 │ Feign │ 出库服务 │
│ Port: 8001 │ │ Port: 8002 │ │ Port: 8003 │
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
│ │ │
│ Feign │ Feign │ Feign
│ │ │
└──────────────┬────────────┴────────────┬──────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│Inventory Service│ │Schedule Service │
│ 库存服务 │ │ 调度服务 │
│ Port: 8004 │ │ Port: 8005 │
└─────────────────┘ └─────────────────┘
```
---
## 3. 服务清单
### 3.1 核心服务
| 服务名称 | 服务标识 | 端口 | Context Path | 职责 |
|---------|---------|------|-------------|------|
| 基础服务 | cpte-wms-basic | 8001 | /cpte-wms-basic | 物料、库区、点位、容器等基础数据管理 |
| 入库服务 | cpte-wms-inbound | 8002 | /cpte-wms-inbound | ASN 管理、收货、上架等入库业务 |
| 出库服务 | cpte-wms-outbound | 8003 | /cpte-wms-outbound | 拣货、发货、波次等出库业务 |
| 库存服务 | cpte-wms-inventory | 8004 | /cpte-wms-inventory | 库存查询、盘点、移库等库存业务 |
| 调度服务 | cpte-wms-schedule | 8005 | /cpte-wms-schedule | AGV 调度、输送线控制、定时任务 |
| 系统服务 | cpte-wms | 8000 | /cpte-wms | 用户、权限、系统管理等 |
### 3.2 共享模块
| 模块名称 | Artifact ID | 职责 |
|---------|-------------|------|
| 公共 API | cpte-wms-api | Feign Client、DTO、分布式锁、工具类 |
| 基础核心 | cpte-boot-base-core | 公共组件、配置、异常处理 |
| 系统业务 | cpte-system-biz | 用户权限、字典、日志等 |
---
## 4. 服务通信架构
### 4.1 通信方式
```
┌─────────────────────────────────────────────────────────────────┐
│ 服务通信方式 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 同步通信 (OpenFeign) │
│ ┌─────────┐ HTTP/REST ┌─────────┐ │
│ │ Service │ ──────────────▶ │ Service │ │
│ │ A │ │ B │ │
│ └─────────┘ └─────────┘ │
│ │
│ 2. 异步通信 (Redis Pub/Sub) │
│ ┌─────────┐ Publish ┌───────┐ Subscribe ┌─────────┐
│ │ Service │ ─────────────▶ │ Redis │ ──────────────▶ │ Service │
│ │ A │ │ │ │ B │
│ └─────────┘ └───────┘ └─────────┘
│ │
│ 3. 分布式锁 (Redisson) │
│ ┌─────────┐ Lock/Unlock ┌───────┐ │
│ │ Service │ ◄────────────────▶ │ Redis │ │
│ │ A │ │ │ │
│ └─────────┘ └───────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.2 OpenFeign 配置
```yaml
feign:
client:
wms-basic:
url: http://cpte-wms-basic:8001/cpte-wms-basic
config:
default:
connectTimeout: 5000 # 连接超时 5 秒
readTimeout: 10000 # 读取超时 10 秒
loggerLevel: INFO # 日志级别
```
**Feign 核心配置**:
- HTTP 客户端: OkHttp
- 连接超时: 5 秒
- 读取超时: 10 秒
- 重试策略: 初始间隔 100ms最大间隔 1 秒,最多重试 3 次
### 4.3 服务调用关系
```
┌─────────────────────────────────────────────────────────────────────────┐
│ 服务调用依赖关系 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ Inbound Service (入库服务) │
│ ├── Feign → Basic Service (获取物料、库区信息) │
│ ├── Feign → Inventory Service (更新库存) │
│ └── Feign → Schedule Service (触发 AGV 任务) │
│ │
│ Outbound Service (出库服务) │
│ ├── Feign → Basic Service (获取物料、点位信息) │
│ ├── Feign → Inventory Service (扣减库存、锁定库存) │
│ └── Feign → Schedule Service (触发拣货任务) │
│ │
│ Inventory Service (库存服务) │
│ ├── Feign → Basic Service (获取物料、容器信息) │
│ └── Redisson → 分布式锁 (库存操作锁) │
│ │
│ Schedule Service (调度服务) │
│ ├── Feign → Basic Service (获取点位信息) │
│ ├── Feign → Inventory Service (库存校验) │
│ └── Quartz → 定时任务调度 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
---
## 5. 数据架构
### 5.1 数据存储架构
```
┌─────────────────────────────────────────────────────────────────────────┐
│ 数据存储架构 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ MySQL (主数据库) │ │
│ │ cpte-wms 数据库 │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ base_item │ │ base_area │ │ base_point │ 基础数据 │ │
│ │ │ 物料表 │ │ 库区表 │ │ 点位表 │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ data_asn │ │asn_detail │ │receive_record│ 入库数据 │ │
│ │ │ 入库单 │ │ 入库明细 │ │ 收货记录 │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ sys_user │ │ sys_role │ │ sys_permission│ 系统数据 │ │
│ │ │ 用户表 │ │ 角色表 │ │ 权限表 │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Redis (缓存/消息) │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Session │ │ 数据缓存 │ │ 分布式锁 │ │ │
│ │ │ 会话存储 │ │ 热点数据 │ │ Redisson │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Pub/Sub │ │ 消息队列 │ │ │
│ │ │ 事件发布 │ │ 异步任务 │ │ │
│ │ └─────────────┘ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
### 5.2 数据库连接池
```yaml
Druid 连接池配置:
initial-size: 5 # 初始连接数
min-idle: 5 # 最小空闲连接
maxActive: 1000 # 最大活跃连接
maxWait: 60000 # 最大等待时间 60s
validationQuery: SELECT 1 # 验证 SQL
```
### 5.3 Redis 部署模式
支持多种部署模式:
- **STANDALONE**: 单机模式
- **MASTER_SLAVE**: 主从模式
- **SENTINEL**: 哨兵模式
- **CLUSTER**: 集群模式
---
## 6. 部署架构
### 6.1 Kubernetes 部署架构
```
┌─────────────────────────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ Namespace: cpte-wms │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ Workload (Deployment) │ │ │
│ │ │ │ │ │
│ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐│ │ │
│ │ │ │ Pod │ │ Pod │ │ Pod │ │ Pod │ │ Pod ││ │ │
│ │ │ │ Basic │ │ Inbound │ │Outbound │ │Inventory│ │Schedule ││ │ │
│ │ │ │ :8001 │ │ :8002 │ │ :8003 │ │ :8004 │ │ :8005 ││ │ │
│ │ │ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘│ │ │
│ │ │ │ │ │ │ │ │ │ │
│ │ └───────┼───────────┼───────────┼───────────┼───────────┼──────┘ │ │
│ │ │ │ │ │ │ │ │
│ │ ┌───────┴───────────┴───────────┴───────────┴───────────┴──────┐ │ │
│ │ │ Service (ClusterIP) │ │ │
│ │ │ │ │ │
│ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │
│ │ │ │cpte-wms │ │cpte-wms │ │cpte-wms │ │inventory│ │schedule │ │ │ │
│ │ │ │ -basic │ │ -inbound│ │ -outbound│ │ -service│ │ -service│ │ │ │
│ │ │ │ :8001 │ │ :8002 │ │ :8003 │ │ :8004 │ │ :8005 │ │ │ │
│ │ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ │
│ │ └───────────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌───────────────────────────────────────────────────────────────┐ │ │
│ │ │ ConfigMap & Secret │ │ │
│ │ │ │ │ │
│ │ │ ConfigMap: application.yml, 环境变量 │ │ │
│ │ │ Secret: DB_PASSWORD, REDIS_PASSWORD, SIGNATURE_SECRET │ │ │
│ │ └───────────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌───────────────────────────────────────────────────────────────┐ │ │
│ │ │ PersistentVolumeClaim │ │ │
│ │ │ │ │ │
│ │ │ cpte-wms-basic-data (10Gi) - 文件上传存储 │ │ │
│ │ │ cpte-wms-inbound-data (10Gi) - 文件上传存储 │ │ │
│ │ └───────────────────────────────────────────────────────────────┘ │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ 基础设施服务 │ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ MySQL │ │ Redis │ │ Nginx │ │ MinIO │ │ │
│ │ │ Service │ │ Service │ │ Ingress │ │ OSS │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
│ └───────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
```
### 6.2 服务资源配置
| 服务 | CPU Request | CPU Limit | Memory Request | Memory Limit | 副本数 |
|-----|-------------|-----------|----------------|--------------|--------|
| Basic | 500m | 2000m | 1Gi | 2Gi | 1 |
| Inbound | 500m | 2000m | 1Gi | 2Gi | 1 |
| Outbound | 100m | 500m | 256Mi | 1Gi | 1 |
| Inventory | 100m | 500m | 256Mi | 1Gi | 1 |
| Schedule | 100m | 500m | 256Mi | 1Gi | 1 |
### 6.3 健康检查配置
```yaml
探针配置:
livenessProbe:
path: /{context}/actuator/health/liveness
initialDelaySeconds: 90-180
periodSeconds: 20
timeoutSeconds: 10
failureThreshold: 3
readinessProbe:
path: /{context}/actuator/health/readiness
initialDelaySeconds: 45-120
periodSeconds: 10-15
timeoutSeconds: 5-10
failureThreshold: 3
startupProbe:
path: /{context}/actuator/health/liveness
initialDelaySeconds: 0-30
periodSeconds: 10
failureThreshold: 30-90
```
---
## 7. 安全架构
### 7.1 认证授权架构
```
┌─────────────────────────────────────────────────────────────────────────┐
│ 认证授权架构 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Client │─────▶│ Nginx │─────▶│ Service │ │
│ │ │ │ Ingress │ │ Instance │ │
│ └─────────┘ └─────────────┘ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ JwtFilter │ │
│ │ - Token 解析 │ │
│ │ - Token 验证 │ │
│ │ - Token 刷新 │ │
│ └──────────┬──────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ ShiroRealm │ │
│ │ - 用户认证 │ │
│ │ - 角色校验 │ │
│ │ - 权限校验 │ │
│ └──────────┬──────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ Business Logic │ │
│ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
### 7.2 敏感信息管理
```
┌─────────────────────────────────────────────────────────────────────────┐
│ Kubernetes Secret 管理 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ Secret 类型: Opaque │
│ │
│ 存储的敏感信息: │
│ ├── MYSQL_HOST # MySQL 主机地址 │
│ ├── MYSQL_PORT # MySQL 端口 │
│ ├── MYSQL_DATABASE # 数据库名称 │
│ ├── MYSQL_USERNAME # 数据库用户名 │
│ ├── MYSQL_PASSWORD # 数据库密码 │
│ ├── REDIS_HOST # Redis 主机地址 │
│ ├── REDIS_PORT # Redis 端口 │
│ ├── REDIS_PASSWORD # Redis 密码 │
│ ├── MAIL_HOST # 邮件服务器地址 │
│ ├── MAIL_USERNAME # 邮件用户名 │
│ ├── MAIL_PASSWORD # 邮件密码 │
│ └── SIGNATURE_SECRET # 接口签名密钥 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
### 7.3 服务间认证
```java
// Feign Token 拦截器
public class FeignTokenInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
// 从当前上下文获取 Token 并传递给下游服务
String token = getCurrentToken();
template.header("Authorization", "Bearer " + token);
}
}
```
---
## 8. 可观测性架构
### 8.1 监控架构
```
┌─────────────────────────────────────────────────────────────────────────┐
│ 监控架构 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Prometheus 采集层 │ │
│ │ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Basic │ │ Inbound │ │Outbound │ │Inventory│ │Schedule │ │ │
│ │ │ :8001 │ │ :8002 │ │ :8003 │ │ :8004 │ │ :8005 │ │ │
│ │ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │ │
│ │ │ │ │ │ │ │ │
│ │ └───────────┴───────────┴───────────┴───────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ /actuator/prometheus │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Prometheus Server │ │
│ │ - 指标采集 │ │
│ │ - 数据存储 │ │
│ │ - 告警规则 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Grafana 可视化 │ │
│ │ - 仪表盘展示 │ │
│ │ - 告警通知 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
### 8.2 Actuator 端点
| 端点 | 路径 | 说明 |
|-----|------|------|
| health | /actuator/health | 健康状态 |
| info | /actuator/info | 应用信息 |
| prometheus | /actuator/prometheus | Prometheus 指标 |
| metrics | /actuator/metrics | JVM 指标 |
### 8.3 日志架构
```
┌─────────────────────────────────────────────────────────────────────────┐
│ 日志架构 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Pod │ │ Pod │ │ Pod │ │ Pod │ │ Pod │ │
│ │ stdout │ │ stdout │ │ stdout │ │ stdout │ │ stdout │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │ │ │
│ └───────────┴───────────┴───────────┴───────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 日志收集器 (Filebeat/Fluentd) │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Elasticsearch │ │
│ │ - 日志存储 │ │
│ │ - 全文检索 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Kibana │ │
│ │ - 日志查询 │ │
│ │ - 可视化分析 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
---
## 9. 高可用架构
### 9.1 服务高可用
```
┌─────────────────────────────────────────────────────────────────────────┐
│ 服务高可用设计 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. 多副本部署 │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Deployment (replicas: N) │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Pod 1 │ │ Pod 2 │ │ Pod N │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ 2. 滚动更新 │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ strategy: │ │
│ │ type: RollingUpdate │ │
│ │ rollingUpdate: │ │
│ │ maxSurge: 1 # 最多多 1 个 Pod │ │
│ │ maxUnavailable: 0 # 最少可用 Pod 数 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ 3. 健康检查 │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ livenessProbe → 存活检查 (失败则重启) │ │
│ │ readinessProbe → 就绪检查 (失败则从 Service 移除) │ │
│ │ startupProbe → 启动检查 (慢启动保护) │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ 4. 服务降级 │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ @FeignClient(fallbackFactory = BasicServiceFallbackFactory)│ │
│ │ → 服务不可用时返回默认响应 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
### 9.2 数据高可用
```
┌─────────────────────────────────────────────────────────────────────────┐
│ 数据高可用设计 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ MySQL 高可用: │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Master │ ───▶ │ Slave │ │ │
│ │ │ (读写) │ │ (只读) │ │ │
│ │ └─────────────┘ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ Redis 高可用: │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Master │ ───▶ │ Slave │ ◀─── │ Sentinel │ │ │
│ │ └─────────────┘ └─────────────┘ │ (监控) │ │ │
│ │ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
---
## 10. 技术栈清单
### 10.1 核心框架
| 组件 | 版本 | 用途 |
|-----|------|------|
| Spring Boot | 3.5.5 | 应用框架 |
| Spring Cloud | 2025.0.0 | 微服务治理 |
| JDK | 17 | 运行环境 |
### 10.2 数据层
| 组件 | 版本 | 用途 |
|-----|------|------|
| MyBatis Plus | 3.5.12 | ORM 框架 |
| Druid | 1.2.24 | 连接池 |
| MySQL | 8.0.27 | 关系数据库 |
| Redis | - | 缓存/分布式锁 |
### 10.3 服务通信
| 组件 | 版本 | 用途 |
|-----|------|------|
| OpenFeign | 4.2.0 | 服务调用 |
| OkHttp | - | HTTP 客户端 |
| Redisson | 3.27.0 | 分布式锁 |
### 10.4 容器化
| 组件 | 用途 |
|-----|------|
| Docker | 容器运行时 |
| Kubernetes | 容器编排 |
| KubeSphere | 容器平台 |
### 10.5 其他组件
| 组件 | 版本 | 用途 |
|-----|------|------|
| Knife4j | 4.5.0 | API 文档 |
| Quartz | - | 定时任务 |
| Shiro | 2.0.4 | 安全框架 |
| JWT | 4.5.0 | Token 认证 |
---
## 11. 服务依赖关系图
```
┌─────────────────┐
│ System Service │
│ (用户/权限) │
└────────┬────────┘
│ 认证
┌──────────────────────────────┼──────────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Basic Service │◄───────────│Inbound Service │───────────▶│Outbound Service │
│ (基础数据) │ Feign │ (入库业务) │ Feign │ (出库业务) │
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
│ │ │
│ Feign │ Feign │ Feign
│ │ │
│ ┌────────────────────┼────────────────────┐ │
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌─────────────────────────┐ ┌─────────────────┐ ┌─────────────────────────┐
│ Inventory Service │◄───│Schedule Service │───▶│ 基础设施 │
│ (库存业务) │ │ (调度任务) │ │ ┌─────┐ ┌─────┐ │
└─────────────────────────┘ └─────────────────┘ │ │MySQL│ │Redis│ │
│ └─────┘ └─────┘ │
└─────────────────────────┘
```
---
## 附录
### A. 服务端口汇总
| 服务 | 容器端口 | Service 端口 | ClusterIP |
|-----|---------|-------------|-----------|
| cpte-wms-basic | 8001 | 8001 | 10.233.42.190 |
| cpte-wms-inbound | 8002 | 8002 | 10.233.51.195 |
| cpte-wms-outbound | 8003 | 8003 | - |
| inventory-service | 8004 | 8004 | - |
| outbound-service | 8003 | 8003 | - |
### B. Context Path 汇总
| 服务 | Context Path |
|-----|-------------|
| Basic | /cpte-wms-basic |
| Inbound | /cpte-wms-inbound |
| Outbound | /cpte-wms-outbound |
| Inventory | /cpte-wms-inventory |
| Schedule | /cpte-wms-schedule |
### C. 关键配置项
| 配置项 | 说明 |
|-------|------|
| spring.application.name | 服务名称 |
| server.port | 服务端口 |
| server.servlet.context-path | 上下文路径 |
| feign.client.wms-basic.url | 基础服务地址 |
| jeecg.redisson.address | Redis 地址 |

View File

@ -1,473 +0,0 @@
# CPTE WMS KubeSphere 部署指南
本文档详细说明如何将 CPTE WMS 系统部署到 KubeSphere/Kubernetes 环境。
## 目录
- [环境要求](#环境要求)
- [架构概览](#架构概览)
- [部署步骤](#部署步骤)
- [配置说明](#配置说明)
- [常见问题](#常见问题)
---
## 环境要求
### 服务器要求
| 组件 | 最低配置 | 推荐配置 |
|------|---------|---------|
| CPU | 4核 | 8核+ |
| 内存 | 16GB | 32GB+ |
| 存储 | 100GB | 500GB+ SSD |
### 软件要求
- Kubernetes 1.20+
- KubeSphere 3.3+
- Docker 20.10+
- kubectl 命令行工具
- Helm 3.0+ (可选)
### 存储类要求
确保 Kubernetes 集群有可用的 StorageClass用于持久化存储
```bash
kubectl get storageclass
```
如果没有默认存储类需要先创建。KubeSphere 默认提供 `local` 存储类。
---
## 架构概览
### 服务架构
```
┌─────────────────────────────────────────────────────────────────┐
│ Ingress (Nginx) │
│ wms.yourdomain.com │
└─────────────────────────────────────────────────────────────────┘
┌───────────────────────┼───────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ cpte-wms- │ │ cpte-wms- │ │ cpte-wms- │
│ system │ │ basic │ │ inbound │
│ (8000) │ │ (8001) │ │ (8002) │
│ 系统主服务 │ │ 基础服务 │ │ 入库服务 │
└───────────────┘ └───────────────┘ └───────────────┘
│ │ │
└───────────────────────┼───────────────────────┘
┌───────────────────────┼───────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ cpte-wms- │ │ cpte-wms- │ │ cpte-wms- │
│ outbound │ │ inventory │ │ schedule │
│ (8003) │ │ (8004) │ │ (8005) │
│ 出库服务 │ │ 库存服务 │ │ 调度服务 │
└───────────────┘ └───────────────┘ └───────────────┘
│ │ │
└───────────────────────┼───────────────────────┘
┌───────────┴───────────┐
│ │
▼ ▼
┌───────────────┐ ┌───────────────┐
│ mysql-service │ │ redis-service │
│ (3306) │ │ (6379) │
│ NodePort:30926│ │ NodePort:30899│
└───────────────┘ └───────────────┘
┌───────────────┐
│ nginx-service │
│ (80) │
│ NodePort:30575│
└───────────────┘
```
### 文件结构
```
k8s/
├── namespace.yaml # 命名空间定义
├── configmap/
│ └── application-config.yaml # 应用配置
├── secrets/
│ └── application-secrets.yaml # 敏感信息配置
├── manifests/
│ ├── mysql.yaml # MySQL 部署
│ ├── redis.yaml # Redis 部署 (Service: redis-service, NodePort: 30899)
│ └── nginx.yaml # Nginx 部署 (Service: nginx-service, NodePort: 30575)
├── services/
│ ├── system-service.yaml # 系统主服务
│ ├── basic-service.yaml # 基础服务
│ ├── inbound-service.yaml # 入库服务
│ ├── outbound-service.yaml # 出库服务
│ ├── inventory-service.yaml # 库存服务
│ └── schedule-service.yaml # 调度服务
├── ingress/
│ └── ingress.yaml # Ingress 路由配置
└── scripts/
├── build-images.sh # Linux 构建脚本
├── build-images.bat # Windows 构建脚本
├── deploy.sh # Linux 部署脚本
└── deploy.bat # Windows 部署脚本
```
---
## 部署步骤
### 第一步:准备工作
#### 1.1 克隆项目到服务器
```bash
# 在服务器上
git clone <your-repo-url>
cd Cpte-Boot
```
#### 1.2 配置域名和密钥
编辑 `k8s/secrets/application-secrets.yaml`,修改以下敏感信息:
```yaml
stringData:
DB_USERNAME: "root"
DB_PASSWORD: "your_secure_password" # 修改为安全密码
REDIS_PASSWORD: "" # 如需密码认证
SIGNATURE_SECRET: "your_signature_key" # 修改签名密钥
```
编辑 `k8s/ingress/ingress.yaml`,修改域名:
```yaml
spec:
rules:
- host: wms.yourdomain.com # 修改为你的域名
```
#### 1.3 配置 DNS 解析
在域名服务商处配置 DNS 解析,将域名指向 Kubernetes 集群的 Ingress IP
```bash
# 获取 Ingress IP
kubectl get svc -n ingress-nginx
```
### 第二步:构建 Docker 镜像
#### 方式一:在开发机构建后推送
```bash
# Windows
k8s\scripts\build-images.bat 3.8.3 your-registry.com
# Linux/Mac
chmod +x k8s/scripts/build-images.sh
./k8s/scripts/build-images.sh 3.8.3 your-registry.com
# 推送镜像
docker push your-registry.com/cpte-wms-system:3.8.3
docker push your-registry.com/cpte-wms-basic:3.8.3
docker push your-registry.com/cpte-wms-inbound:3.8.3
docker push your-registry.com/cpte-wms-outbound:3.8.3
docker push your-registry.com/cpte-wms-inventory:3.8.3
docker push your-registry.com/cpte-wms-schedule:3.8.3
```
#### 方式二:在服务器本地构建
```bash
# 在服务器上执行
cd Cpte-Boot
./k8s/scripts/build-images.sh
```
### 第三步:部署到 Kubernetes
#### 方式一:使用部署脚本
```bash
# Linux/Mac
chmod +x k8s/scripts/deploy.sh
./k8s/scripts/deploy.sh cpte-wms
# Windows
k8s\scripts\deploy.bat cpte-wms
```
#### 方式二:手动部署
```bash
# 1. 创建命名空间
kubectl apply -f k8s/namespace.yaml
# 2. 创建 Secrets 和 ConfigMaps
kubectl apply -f k8s/secrets/application-secrets.yaml
kubectl apply -f k8s/configmap/application-config.yaml
# 3. 部署中间件
kubectl apply -f k8s/manifests/mysql.yaml
kubectl apply -f k8s/manifests/redis.yaml
kubectl apply -f k8s/manifests/nginx.yaml
# 4. 等待中间件就绪
kubectl wait --for=condition=ready pod -l app=cpte-wms-mysql -n cpte-wms --timeout=300s
kubectl wait --for=condition=ready pod -l app=redis -n cpte-wms --timeout=300s
kubectl wait --for=condition=ready pod -l app=nginx -n cpte-wms --timeout=300s
# 5. 部署应用服务
kubectl apply -f k8s/services/system-service.yaml
kubectl apply -f k8s/services/basic-service.yaml
kubectl apply -f k8s/services/inbound-service.yaml
kubectl apply -f k8s/services/outbound-service.yaml
kubectl apply -f k8s/services/inventory-service.yaml
kubectl apply -f k8s/services/schedule-service.yaml
# 6. 创建 Ingress
kubectl apply -f k8s/ingress/ingress.yaml
```
### 第四步:验证部署
```bash
# 查看所有 Pod 状态
kubectl get pods -n cpte-wms
# 查看服务状态
kubectl get svc -n cpte-wms
# 查看 Ingress
kubectl get ingress -n cpte-wms
# 查看日志
kubectl logs -f deployment/cpte-wms-system -n cpte-wms
```
### 第五步:初始化数据库
首次部署需要初始化数据库:
```bash
# 进入 MySQL Pod
kubectl exec -it -n cpte-wms $(kubectl get pod -n cpte-wms -l app=cpte-wms-mysql -o jsonpath='{.items[0].metadata.name}') -- mysql -uroot -p
# 或者使用 port-forward
kubectl port-forward svc/cpte-wms-mysql 3306:3306 -n cpte-wms
# 使用数据库客户端连接并执行 SQL 脚本
# SQL 脚本位于项目的 db 目录
```
---
## KubeSphere 控制台操作
### 通过 KubeSphere 控制台部署
#### 1. 创建项目
1. 登录 KubeSphere 控制台
2. 进入「应用负载」→「项目」
3. 点击「创建」,输入项目名称 `cpte-wms`
#### 2. 创建配置
1. 进入项目 `cpte-wms`
2. 点击「配置」→「配置字典」→「创建」
3. 上传 `k8s/configmap/application-config.yaml`
#### 3. 创建密钥
1. 点击「配置」→「密钥」→「创建」
2. 上传 `k8s/secrets/application-secrets.yaml`
#### 4. 创建应用负载
1. 点击「应用负载」→「工作负载」→「创建」
2. 选择「部署」,依次创建各服务
#### 5. 创建服务
1. 点击「应用负载」→「服务」→「创建」
2. 配置服务端口映射
#### 6. 创建应用路由
1. 点击「应用负载」→「应用路由」→「创建」
2. 配置域名和路由规则
### 使用 KubeSphere 应用商店
如果配置了应用商店,可以直接使用 Helm Chart 部署。
---
## 配置说明
### 环境变量说明
| 变量名 | 说明 | 默认值 |
|--------|------|--------|
| SPRING_PROFILES_ACTIVE | Spring 配置环境 | k8s |
| DB_HOST | 数据库主机 | cpte-wms-mysql |
| DB_PORT | 数据库端口 | 3306 |
| DB_NAME | 数据库名称 | cpte-wms |
| DB_USERNAME | 数据库用户名 | root |
| DB_PASSWORD | 数据库密码 | - |
| REDIS_HOST | Redis 主机 | redis-service |
| REDIS_PORT | Redis 端口 | 6379 |
| REDIS_PASSWORD | Redis 密码 | - |
### 资源配置调整
根据实际负载调整各服务的资源配置:
```yaml
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "1000m"
```
### 副本数调整
修改 `replicas` 字段调整副本数:
```yaml
spec:
replicas: 2 # 调整副本数
```
---
## 常见问题
### Q1: Pod 一直处于 Pending 状态
**原因**:可能是存储类不存在或资源不足
**解决**
```bash
# 检查存储类
kubectl get storageclass
# 检查事件
kubectl describe pod <pod-name> -n cpte-wms
```
### Q2: 服务无法启动
**原因**:可能是数据库未就绪或配置错误
**解决**
```bash
# 查看日志
kubectl logs <pod-name> -n cpte-wms
# 检查数据库连接
kubectl exec -it <mysql-pod> -n cpte-wms -- mysql -uroot -p
```
### Q3: Ingress 无法访问
**原因**:可能是 Ingress Controller 未安装或域名解析问题
**解决**
```bash
# 检查 Ingress Controller
kubectl get svc -n ingress-nginx
# 检查 Ingress 状态
kubectl describe ingress -n cpte-wms
```
### Q4: 镜像拉取失败
**原因**:镜像不存在或仓库认证问题
**解决**
```bash
# 创建镜像拉取密钥
kubectl create secret docker-registry regcred \
--docker-server=<your-registry> \
--docker-username=<username> \
--docker-password=<password> \
-n cpte-wms
# 在 Deployment 中添加 imagePullSecrets
```
### Q5: 数据库连接超时
**原因**MySQL 未完全启动
**解决**:检查 initContainers 是否正常等待 MySQL 就绪
---
## 运维命令
### 日常运维
```bash
# 查看所有资源状态
kubectl get all -n cpte-wms
# 重启服务
kubectl rollout restart deployment/cpte-wms-system -n cpte-wms
# 扩缩容
kubectl scale deployment/cpte-wms-system --replicas=3 -n cpte-wms
# 查看资源使用
kubectl top pods -n cpte-wms
# 进入容器
kubectl exec -it <pod-name> -n cpte-wms -- /bin/sh
```
### 备份与恢复
```bash
# 备份 MySQL
kubectl exec -n cpte-wms <mysql-pod> -- mysqldump -uroot -p cpte-wms > backup.sql
# 备份 PVC
kubectl get pvc -n cpte-wms -o yaml > pvc-backup.yaml
```
### 日志查看
```bash
# 查看服务日志
kubectl logs -f deployment/cpte-wms-system -n cpte-wms
# 查看最近 100 行日志
kubectl logs --tail=100 deployment/cpte-wms-system -n cpte-wms
# 查看所有容器日志
kubectl logs -f deployment/cpte-wms-system -n cpte-wms --all-containers
```
---
## 联系支持
如有问题,请联系:
- 邮箱cpte@163.com
- 网站http://www.cpte.com

View File

@ -1,3 +1,10 @@
# =============================================================================
# Nginx 部署配置
# Namespace: cpte-wms
# =============================================================================
---
# 1. ConfigMap
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
@ -5,7 +12,7 @@ metadata:
namespace: cpte-wms namespace: cpte-wms
annotations: annotations:
kubesphere.io/creator: admin kubesphere.io/creator: admin
kubesphere.io/description: 配置文件 kubesphere.io/description: Nginx 配置文件
data: data:
nginx.conf: | nginx.conf: |
worker_processes 1; worker_processes 1;
@ -17,99 +24,119 @@ data:
http { http {
include mime.types; include mime.types;
default_type application/octet-stream; default_type application/octet-stream;
# ✅ 字符编码设置
charset utf-8;
charset_types text/html text/plain text/css application/javascript application/json;
sendfile on; sendfile on;
keepalive_timeout 65; keepalive_timeout 65;
charset utf-8;
gzip on; # Gzip 压缩配置
gzip_static on; gzip on;
gzip_buffers 4 16k; gzip_static on;
gzip_comp_level 5; gzip_buffers 4 16k;
gzip_types text/plain application/javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; gzip_comp_level 5;
gzip_types text/plain application/javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
server { server {
listen 80; listen 80;
listen [::]:80; listen [::]:80;
server_name 101.35.253.46; server_name 101.35.253.46;
# 前端配置 # Gzip 压缩配置
location / { gzip_min_length 1k;
root /html/dist; gzip_buffers 4 16k;
try_files $uri $uri/ /index.html last; gzip_comp_level 3;
index index.html; gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
expires -1; gzip_vary on;
gzip_disable "MSIE [1-6]\.";
# 禁用 OPTIONS 请求
if ($request_method ~* OPTIONS) {
return 403;
} }
# 后端api配置 # 前端配置
location / {
root /html/dist;
try_files $uri $uri/ /index.html last;
index index.html;
expires -1;
}
# 后端系统服务配置
location /cpte-wms/ { location /cpte-wms/ {
# 反向代理的java地址 proxy_pass http://cpte-wms-system:8000/cpte-wms/;
proxy_pass http://101.35.253.46:8000/cpte-wms/; proxy_redirect off;
proxy_redirect off;
# 设置代理消息头 # 设置代理消息头
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host; proxy_set_header Host $http_host;
# 设置没有缓存 # 禁用缓存
expires -1; expires -1;
# 安全配置 # 安全配置
add_header Set-Cookie "Path=/; HttpOnly; Secure"; add_header Set-Cookie "Path=/; HttpOnly; Secure";
add_header X-Content-Type-Options "nosniff"; add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block"; add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options "ALLOW-FROM 101.35.253.46"; add_header X-Frame-Options "ALLOW-FROM 101.35.253.46";
add_header Content-Security-Policy "frame-ancestors 101.35.253.46"; add_header Content-Security-Policy "frame-ancestors 101.35.253.46";
}
# 后端基础服务配置
location /cpte-wms-basic/ {
proxy_pass http://cpte-wms-basic:8001/cpte-wms-basic/;
proxy_redirect off;
# 设置代理消息头
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
# 禁用缓存
expires -1;
# 安全配置
add_header Set-Cookie "Path=/; HttpOnly; Secure";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options "ALLOW-FROM 101.35.253.46";
add_header Content-Security-Policy "frame-ancestors 101.35.253.46";
}
# 后端入库服务配置
location /cpte-wms-inbound/ {
proxy_pass http://cpte-wms-inbound:8002/cpte-wms-inbound/;
proxy_redirect off;
# 设置代理消息头
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
# 禁用缓存
expires -1;
# 安全配置
add_header Set-Cookie "Path=/; HttpOnly; Secure";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options "ALLOW-FROM 101.35.253.46";
add_header Content-Security-Policy "frame-ancestors 101.35.253.46";
} }
# 健康检查端点 # 健康检查端点
location /health { location /health {
access_log off; return 200 'OK';
return 200 "healthy\n";
add_header Content-Type text/plain; add_header Content-Type text/plain;
} }
# 就绪检查端点
location /ready { location /ready {
access_log off; return 200 'Ready';
return 200 "ready\n";
add_header Content-Type text/plain; add_header Content-Type text/plain;
} }
} }
} }
default.html: |
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nginx - CPTE WMS</title>
<style>
body { font-family: Arial, "Microsoft YaHei", sans-serif; margin: 40px; background: #f5f5f5; }
.container { background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); max-width: 600px; margin: 0 auto; }
h1 { color: #009639; }
.info { background: #e8f5e9; padding: 15px; border-radius: 4px; margin: 20px 0; }
.info p { margin: 8px 0; }
</style>
</head>
<body>
<div class="container">
<h1>✅ Nginx 部署成功!</h1>
<div class="info">
<p><strong>项目:</strong> CPTE WMS</p>
<p><strong>环境:</strong> Production</p>
<p><strong>时间:</strong> <span id="time"></span></p>
</div>
</div>
<script>document.getElementById('time').innerText = new Date().toLocaleString('zh-CN');</script>
</body>
</html>
--- ---
# 2. Deployment # 2. Deployment
apiVersion: apps/v1 apiVersion: apps/v1
@ -120,7 +147,7 @@ metadata:
labels: labels:
app: nginx app: nginx
annotations: annotations:
kubesphere.io/description: "1.28.0" kubesphere.io/description: "WEB服务"
spec: spec:
replicas: 1 replicas: 1
strategy: strategy:
@ -141,96 +168,73 @@ spec:
prometheus.io/port: "80" prometheus.io/port: "80"
spec: spec:
containers: containers:
- name: nginx - name: nginx
image: docker.io/library/nginx:1.28.0 image: docker.io/library/nginx:1.0
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
ports:
ports: - name: http
- name: http containerPort: 80
containerPort: 80 protocol: TCP
protocol: TCP resources:
requests:
resources: cpu: "50m"
requests: memory: "64Mi"
cpu: "50m" limits:
memory: "64Mi" cpu: "500m"
limits: memory: "256Mi"
cpu: "500m" livenessProbe:
memory: "256Mi" httpGet:
path: /health
livenessProbe: port: 80
httpGet: initialDelaySeconds: 10
path: /health periodSeconds: 10
port: 80 timeoutSeconds: 5
initialDelaySeconds: 10 failureThreshold: 3
periodSeconds: 10 readinessProbe:
timeoutSeconds: 5 httpGet:
failureThreshold: 3 path: /ready
port: 80
readinessProbe: initialDelaySeconds: 5
httpGet: periodSeconds: 5
path: /ready timeoutSeconds: 3
port: 80 failureThreshold: 3
initialDelaySeconds: 5 startupProbe:
periodSeconds: 5 httpGet:
timeoutSeconds: 3 path: /health
failureThreshold: 3 port: 80
initialDelaySeconds: 0
startupProbe: periodSeconds: 5
httpGet: timeoutSeconds: 3
path: /health failureThreshold: 30
port: 80 volumeMounts:
initialDelaySeconds: 0 - name: nginx-conf
periodSeconds: 5 mountPath: /etc/nginx/nginx.conf
timeoutSeconds: 3 subPath: nginx.conf
failureThreshold: 30 readOnly: true
- name: nginx-cache
volumeMounts: mountPath: /var/cache/nginx
- name: nginx-conf - name: nginx-log
mountPath: /etc/nginx/nginx.conf mountPath: /var/log/nginx
subPath: nginx.conf
readOnly: true
- name: nginx-html
mountPath: /html/dist
readOnly: true
- name: nginx-cache
mountPath: /var/cache/nginx
- name: nginx-log
mountPath: /var/log/nginx
env:
- name: NGINX_ENTRYPOINT_QUIET_LOGS
value: "true"
# ⚠️ 修复重点volumes 配置
volumes: volumes:
- name: nginx-conf - name: nginx-conf
configMap: configMap:
name: nginx-conf name: nginx-conf
items: items:
- key: nginx.conf - key: nginx.conf
path: nginx.conf path: nginx.conf
- name: nginx-html - name: nginx-cache
configMap: emptyDir: {}
name: nginx-conf - name: nginx-log
items: emptyDir: {}
- key: default.html
path: index.html
- name: nginx-cache
emptyDir: {}
- name: nginx-log
emptyDir: {}
restartPolicy: Always restartPolicy: Always
--- ---
# 3. Service # 3. Service
kind: Service
apiVersion: v1 apiVersion: v1
kind: Service
metadata: metadata:
name: nginx-service name: nginx-service
namespace: cpte-wms namespace: cpte-wms
creationTimestamp: '2026-03-16T11:55:00Z'
labels: labels:
app: nginx app: nginx
spec: spec:
@ -242,13 +246,6 @@ spec:
nodePort: 30575 nodePort: 30575
selector: selector:
app: nginx app: nginx
clusterIP: 10.233.51.227
clusterIPs:
- 10.233.51.227
type: NodePort type: NodePort
sessionAffinity: None sessionAffinity: None
externalTrafficPolicy: Cluster externalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
internalTrafficPolicy: Cluster

View File

@ -251,7 +251,6 @@ apiVersion: v1
metadata: metadata:
name: redis-service name: redis-service
namespace: cpte-wms namespace: cpte-wms
creationTimestamp: '2026-03-16T10:47:03Z'
labels: labels:
app: redis app: redis
spec: spec:
@ -260,16 +259,14 @@ spec:
protocol: TCP protocol: TCP
port: 6379 port: 6379
targetPort: 6379 targetPort: 6379
nodePort: 30899
selector: selector:
app: redis app: redis
clusterIP: 10.233.50.165 clusterIP: 10.233.50.165
clusterIPs: clusterIPs:
- 10.233.50.165 - 10.233.50.165
type: NodePort type: ClusterIP
sessionAffinity: None sessionAffinity: None
externalTrafficPolicy: Cluster
ipFamilies: ipFamilies:
- IPv4 - IPv4
ipFamilyPolicy: SingleStack ipFamilyPolicy: SingleStack
internalTrafficPolicy: Cluster internalTrafficPolicy: Cluster

View File

@ -1,3 +1,286 @@
# ===== 1. Secret - 应用敏感信息 =====
kind: Secret
apiVersion: v1
metadata:
name: cpte-wms-basic-secret
namespace: cpte-wms
annotations:
kubesphere.io/creator: admin
kubesphere.io/description: 基础服务
type: Opaque
stringData:
MYSQL_HOST: "47.103.100.52"
MYSQL_PORT: "53306"
MYSQL_DATABASE: "cpte-wms"
MYSQL_USERNAME: "root"
MYSQL_PASSWORD: "Youchain@56"
REDIS_HOST: "redis-service"
REDIS_PORT: "6379"
REDIS_PASSWORD: "cpte@123"
MAIL_HOST: "smtp.163.com"
MAIL_USERNAME: "cpteos@163.com"
MAIL_PASSWORD: "cpte@123"
DRUID_LOGIN_PASSWORD: "cpte@123"
SIGNATURE_SECRET: "dd05f1c54d63749eda95f9fa6d49v442a"
---
# ===== 2. ConfigMap - 应用配置文件(修复 Shiro 格式)=====
kind: ConfigMap
apiVersion: v1
metadata:
name: cpte-wms-basic-conf
namespace: cpte-wms
annotations:
kubesphere.io/creator: admin
kubesphere.io/description: 基础服务配置文件
data:
application.yml: |
server:
port: 8001
tomcat:
max-swallow-size: -1
error:
include-exception: true
include-stacktrace: ALWAYS
include-message: ALWAYS
servlet:
context-path: /cpte-wms-basic
compression:
enabled: true
min-response-size: 1024
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
management:
endpoints:
web:
exposure:
include: health,info,prometheus,metrics
base-path: /actuator
endpoint:
health:
show-details: when_authorized
probes:
enabled: true
info:
enabled: true
prometheus:
enabled: true
security:
enabled: false
spring:
application:
name: cpte-wms-basic
flyway:
enabled: false
clean-disabled: true
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
mail:
timeJobSend: false
host: ${MAIL_HOST}
username: ${MAIL_USERNAME}
password: ${MAIL_PASSWORD}
properties:
mail.smtp.timeout: 10000
mail.smtp.connectiontimeout: 10000
mail.smtp.writetimeout: 10000
mail.smtp.auth: true
mail.smtp.ssl.enable: true
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
jpa:
open-in-view: false
aop:
proxy-target-class: true
freemarker:
suffix: .ftl
content-type: text/html
charset: UTF-8
cache: false
prefer-file-system-access: false
template-loader-path:
- classpath:/templates
template_update_delay: 0
mvc:
static-path-pattern: /**
pathmatch:
matching-strategy: ant_path_matcher
resource:
static-locations: classpath:/static/,classpath:/public/
autoconfigure:
exclude:
- com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure
- org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration
datasource:
druid:
stat-view-servlet:
enabled: true
loginUsername: admin
loginPassword: ${DRUID_LOGIN_PASSWORD}
web-stat-filter:
enabled: true
dynamic:
druid:
initial-size: 5
min-idle: 5
maxActive: 1000
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
filters: stat,slf4j
wall:
selectWhereAlwayTrueCheck: false
stat:
slow-sql-millis: 5000
merge-sql: true
datasource:
master:
url: jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_DATABASE}?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
username: ${MYSQL_USERNAME}
password: ${MYSQL_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
data:
redis:
database: 0
host: ${REDIS_HOST}
port: ${REDIS_PORT}
password: ${REDIS_PASSWORD}
mybatis-plus:
mapper-locations: classpath*:org/jeecg/**/xml/*Mapper.xml,classpath*:org/cpte/**/xml/*Mapper.xml
global-config:
banner: false
db-config:
id-type: ASSIGN_ID
table-underline: true
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
call-setners-on-nulls: true
minidao:
base-package: org.jeecg.modules.jmreport.*,org.jeecg.modules.drag.*
# ========== 关键修复Shiro excludeUrls 改为单行 ==========
jeecg:
firewall:
dataSourceSafe: false
lowCodeMode: dev
signatureSecret: ${SIGNATURE_SECRET}
signUrls: /sys/dict/getDictItems/*,/sys/dict/loadDict/*,/sys/dict/loadDictOrderByValue/*,/sys/dict/loadDictItem/*,/sys/dict/loadTreeData,/sys/api/queryTableDictItemsByCode,/sys/api/queryFilterTableDictInfo,/sys/api/queryTableDictByKeys,/sys/api/translateDictFromTable,/sys/api/translateDictFromTableByKeys,/sys/sendChangePwdSms,/sys/user/sendChangePhoneSms,/sys/sms,/desform/api/sendVerifyCode
uploadType: local
domainUrl:
pc: http://101.35.253.46:8001/cpte-wms-basic/sys/common/upload
app: http://101.35.253.46:8051
path:
upload: /home/wms/upload
webapp: /home/wms/webapp
shiro:
excludeUrls: /test/cpteDemo/demo3,/test/cpteDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**,/cpte-wms-basic/actuator/**,/actuator/**
oss:
accessKey: ??
secretKey: ??
endpoint: oss-cn-beijing.aliyuncs.com
bucketName: cptedev
sms-template:
signature:
templateCode:
SMS_175435174:
SMS_465391221:
SMS_175430166:
file-view-domain: http://fileview.cpte.com
minio:
minio_url: http://minio.cpte.com
minio_name: ??
minio_pass: ??
bucketName: otatest
jmreport:
saasMode:
firewall:
dataSourceSafe: false
lowCodeMode: dev
gao-de-api:
api-key: ??
secret-key: ??
redisson:
address: ${REDIS_HOST}:${REDIS_PORT}
password: ${REDIS_PASSWORD}
type: STANDALONE
enabled: true
baidu-api:
app-id: ??
api-key: ??
secret-key: ??
cas:
prefixUrl: http://cas.example.org:8443/cas
logging:
level:
org.springframework.context.support.PostProcessorRegistrationDelegate: error
org.flywaydb: debug
org.jeecg.modules.system.mapper: info
org.jeecg.modules.demo.test.mapper: info
knife4j:
enable: true
production: false
basic:
enable: false
username: cpte
password: cpte1314
justauth:
enabled: true
type:
GITHUB:
client-id: ??
client-secret: ??
redirect-uri: http://101.35.253.46:8000/cpte-wms/sys/thirdLogin/github/callback
WECHAT_ENTERPRISE:
client-id: ??
client-secret: ??
redirect-uri: http://101.35.253.46:8000/cpte-wms/sys/thirdLogin/wechat_enterprise/callback
agent-id: ??
DINGTALK:
client-id: ??
client-secret: ??
redirect-uri: http://101.35.253.46:8000/cpte-wms/sys/thirdLogin/dingtalk/callback
WECHAT_OPEN:
client-id: ??
client-secret: ??
redirect-uri: http://101.35.253.46:8000/cpte-wms/sys/thirdLogin/wechat_open/callback
cache:
type: default
prefix: 'demo::'
timeout: 1h
---
# ===== 3. PersistentVolumeClaim - 文件存储 =====
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: cpte-wms-basic-data
namespace: cpte-wms
annotations:
kubesphere.io/creator: admin
kubesphere.io/description: 文件上传存储
spec:
accessModes:
- ReadWriteOnce
storageClassName: local
resources:
requests:
storage: 10Gi
---
# ===== 4. Deployment - 系统服务(修复探针路径)=====
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
@ -5,8 +288,16 @@ metadata:
namespace: cpte-wms namespace: cpte-wms
labels: labels:
app: cpte-wms-basic app: cpte-wms-basic
version: v1
annotations:
kubesphere.io/description: "WMS-基础服务"
spec: spec:
replicas: 2 replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector: selector:
matchLabels: matchLabels:
app: cpte-wms-basic app: cpte-wms-basic
@ -14,79 +305,170 @@ spec:
metadata: metadata:
labels: labels:
app: cpte-wms-basic app: cpte-wms-basic
version: v1
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8001"
prometheus.io/path: "/cpte-wms-basic/actuator/prometheus"
spec: spec:
initContainers:
- name: wait-for-mysql
image: busybox:1.36
command: ['sh', '-c', 'until nc -z mysql-service 3306; do echo waiting for mysql; sleep 2; done;']
- name: wait-for-redis
image: busybox:1.36
command: ['sh', '-c', 'until nc -z redis-service 6379; do echo waiting for redis; sleep 2; done;']
containers: containers:
- name: cpte-wms-basic - name: cpte-wms-basic
image: cpte-wms-basic:3.8.3 image: docker.io/library/cpte-wms-basic:1.0
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
ports: ports:
- containerPort: 8001 - name: http
envFrom: containerPort: 8001
- configMapRef: protocol: TCP
name: cpte-wms-config env:
- secretRef: - name: MYSQL_HOST
name: cpte-wms-secrets valueFrom:
env: secretKeyRef:
- name: SERVER_PORT name: cpte-wms-basic-secret
value: "8001" key: MYSQL_HOST
- name: DB_URL - name: MYSQL_PORT
value: "jdbc:mysql://$(DB_HOST):$(DB_PORT)/$(DB_NAME)?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai" valueFrom:
- name: JAVA_OPTS secretKeyRef:
value: "$(JAVA_OPTS_SERVICES)" name: cpte-wms-basic-secret
resources: key: MYSQL_PORT
requests: - name: MYSQL_DATABASE
memory: "256Mi" valueFrom:
cpu: "100m" secretKeyRef:
limits: name: cpte-wms-basic-secret
memory: "512Mi" key: MYSQL_DATABASE
cpu: "500m" - name: MYSQL_USERNAME
volumeMounts: valueFrom:
- name: upload-path secretKeyRef:
mountPath: /data/upload name: cpte-wms-basic-secret
- name: logs-path key: MYSQL_USERNAME
mountPath: /data/logs - name: MYSQL_PASSWORD
livenessProbe: valueFrom:
httpGet: secretKeyRef:
path: /cpte-wms-basic/actuator/health name: cpte-wms-basic-secret
port: 8001 key: MYSQL_PASSWORD
initialDelaySeconds: 90 - name: REDIS_HOST
periodSeconds: 30 valueFrom:
timeoutSeconds: 10 secretKeyRef:
failureThreshold: 3 name: cpte-wms-basic-secret
readinessProbe: key: REDIS_HOST
httpGet: - name: REDIS_PORT
path: /cpte-wms-basic/actuator/health valueFrom:
port: 8001 secretKeyRef:
initialDelaySeconds: 45 name: cpte-wms-basic-secret
periodSeconds: 10 key: REDIS_PORT
timeoutSeconds: 5 - name: REDIS_PASSWORD
failureThreshold: 3 valueFrom:
secretKeyRef:
name: cpte-wms-basic-secret
key: REDIS_PASSWORD
- name: MAIL_HOST
valueFrom:
secretKeyRef:
name: cpte-wms-basic-secret
key: MAIL_HOST
- name: MAIL_USERNAME
valueFrom:
secretKeyRef:
name: cpte-wms-basic-secret
key: MAIL_USERNAME
- name: MAIL_PASSWORD
valueFrom:
secretKeyRef:
name: cpte-wms-basic-secret
key: MAIL_PASSWORD
- name: DRUID_LOGIN_PASSWORD
valueFrom:
secretKeyRef:
name: cpte-wms-basic-secret
key: DRUID_LOGIN_PASSWORD
- name: SIGNATURE_SECRET
valueFrom:
secretKeyRef:
name: cpte-wms-basic-secret
key: SIGNATURE_SECRET
- name: JAVA_OPTS
value: "-Xms512m -Xmx2048m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/app/logs/heapdump.hprof"
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "2000m"
memory: "2Gi"
# ========== 关键修复 3: 探针路径 ==========
livenessProbe:
httpGet:
path: /cpte-wms-basic/actuator/health/liveness # ✅ 包含 context-path
port: 8001
initialDelaySeconds: 180
periodSeconds: 20
timeoutSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /cpte-wms-basic/actuator/health/readiness # ✅ 包含 context-path
port: 8001
initialDelaySeconds: 120
periodSeconds: 15
timeoutSeconds: 10
failureThreshold: 3
startupProbe:
httpGet:
path: /cpte-wms-basic/actuator/health/liveness # ✅ 包含 context-path
port: 8001
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 90
volumeMounts:
- name: cpte-wms-basic-conf
mountPath: /app/application.yml
subPath: application.yml
readOnly: true
- name: cpte-wms-basic-data
mountPath: /home/wms
- name: host-time
mountPath: /etc/localtime
readOnly: true
securityContext:
runAsNonRoot: false
volumes: volumes:
- name: upload-path - name: cpte-wms-basic-conf
emptyDir: {} configMap:
- name: logs-path name: cpte-wms-basic-conf
emptyDir: {} items:
- key: application.yml
path: application.yml
- name: cpte-wms-basic-data
persistentVolumeClaim:
claimName: cpte-wms-basic-data
- name: host-time
hostPath:
path: /etc/localtime
type: File
restartPolicy: Always
--- ---
apiVersion: v1 # ===== 5. Service - ClusterIP 集群内访问 =====
kind: Service kind: Service
apiVersion: v1
metadata: metadata:
name: cpte-wms-basic name: cpte-wms-basic
namespace: cpte-wms namespace: cpte-wms
labels: labels:
app: cpte-wms-basic app: cpte-wms-basic
spec: spec:
type: ClusterIP
ports: ports:
- port: 8001 - name: cpte-wms-basic
targetPort: 8001 protocol: TCP
protocol: TCP port: 8001
name: http targetPort: 8001
selector: selector:
app: cpte-wms-basic app: cpte-wms-basic
clusterIP: 10.233.42.190
clusterIPs:
- 10.233.42.190
type: ClusterIP
sessionAffinity: None
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
internalTrafficPolicy: Cluster

View File

@ -1,3 +1,272 @@
# ===== 1. Secret - 应用敏感信息 =====
kind: Secret
apiVersion: v1
metadata:
name: cpte-wms-inbound-secret
namespace: cpte-wms
annotations:
kubesphere.io/creator: admin
kubesphere.io/description: 入库服务
type: Opaque
stringData:
MYSQL_HOST: "47.103.100.52"
MYSQL_PORT: "53306"
MYSQL_DATABASE: "cpte-wms"
MYSQL_USERNAME: "root"
MYSQL_PASSWORD: "Youchain@56"
REDIS_HOST: "redis-service"
REDIS_PORT: "6379"
REDIS_PASSWORD: "cpte@123"
MAIL_HOST: "smtp.163.com"
MAIL_USERNAME: "cpteos@163.com"
MAIL_PASSWORD: "cpte@123"
DRUID_LOGIN_PASSWORD: "cpte@123"
SIGNATURE_SECRET: "dd05f1c54d63749eda95f9fa6d49v442a"
---
# ===== 2. ConfigMap - 应用配置文件(修复 Shiro 格式)=====
kind: ConfigMap
apiVersion: v1
metadata:
name: cpte-wms-inbound-conf
namespace: cpte-wms
annotations:
kubesphere.io/creator: admin
kubesphere.io/description: 基础服务配置文件
data:
application.yml: |
server:
port: 8002
tomcat:
max-swallow-size: -1
error:
include-exception: true
include-stacktrace: ALWAYS
include-message: ALWAYS
servlet:
context-path: /cpte-wms-inbound
compression:
enabled: true
min-response-size: 1024
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
management:
endpoints:
web:
exposure:
include: health,info,prometheus,metrics
base-path: /actuator
endpoint:
health:
show-details: when_authorized
probes:
enabled: true
info:
enabled: true
prometheus:
enabled: true
security:
enabled: false
spring:
application:
name: cpte-wms-inbound
flyway:
enabled: false
clean-disabled: true
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
mail:
timeJobSend: false
host: ${MAIL_HOST}
username: ${MAIL_USERNAME}
password: ${MAIL_PASSWORD}
properties:
mail.smtp.timeout: 10000
mail.smtp.connectiontimeout: 10000
mail.smtp.writetimeout: 10000
mail.smtp.auth: true
mail.smtp.ssl.enable: true
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
jpa:
open-in-view: false
aop:
proxy-target-class: true
freemarker:
suffix: .ftl
content-type: text/html
charset: UTF-8
cache: false
prefer-file-system-access: false
template-loader-path:
- classpath:/templates
template_update_delay: 0
mvc:
static-path-pattern: /**
pathmatch:
matching-strategy: ant_path_matcher
resource:
static-locations: classpath:/static/,classpath:/public/
autoconfigure:
exclude:
- com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure
- org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration
datasource:
druid:
stat-view-servlet:
enabled: true
loginUsername: admin
loginPassword: ${DRUID_LOGIN_PASSWORD}
web-stat-filter:
enabled: true
dynamic:
druid:
initial-size: 5
min-idle: 5
maxActive: 1000
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
filters: stat,slf4j
wall:
selectWhereAlwayTrueCheck: false
stat:
slow-sql-millis: 5000
merge-sql: true
datasource:
master:
url: jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_DATABASE}?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
username: ${MYSQL_USERNAME}
password: ${MYSQL_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
data:
redis:
database: 0
host: ${REDIS_HOST}
port: ${REDIS_PORT}
password: ${REDIS_PASSWORD}
mybatis-plus:
mapper-locations: classpath*:org/jeecg/**/xml/*Mapper.xml,classpath*:org/cpte/**/xml/*Mapper.xml
global-config:
banner: false
db-config:
id-type: ASSIGN_ID
table-underline: true
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
call-setners-on-nulls: true
minidao:
base-package: org.jeecg.modules.jmreport.*,org.jeecg.modules.drag.*
# ========== 关键修复Shiro excludeUrls 改为单行 ==========
jeecg:
firewall:
dataSourceSafe: false
lowCodeMode: dev
signatureSecret: ${SIGNATURE_SECRET}
signUrls: /sys/dict/getDictItems/*,/sys/dict/loadDict/*,/sys/dict/loadDictOrderByValue/*,/sys/dict/loadDictItem/*,/sys/dict/loadTreeData,/sys/api/queryTableDictItemsByCode,/sys/api/queryFilterTableDictInfo,/sys/api/queryTableDictByKeys,/sys/api/translateDictFromTable,/sys/api/translateDictFromTableByKeys,/sys/sendChangePwdSms,/sys/user/sendChangePhoneSms,/sys/sms,/desform/api/sendVerifyCode
uploadType: local
domainUrl:
pc: http://101.35.253.46:8002/cpte-wms-inbound/sys/common/upload
app: http://101.35.253.46:8051
path:
upload: /home/wms/upload
webapp: /home/wms/webapp
shiro:
excludeUrls: /test/cpteDemo/demo3,/test/cpteDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**,/cpte-wms-inbound/actuator/**,/actuator/**
oss:
accessKey: ??
secretKey: ??
endpoint: oss-cn-beijing.aliyuncs.com
bucketName: cptedev
sms-template:
signature:
templateCode:
SMS_175435174:
SMS_465391221:
SMS_175430166:
file-view-domain: http://fileview.cpte.com
minio:
minio_url: http://minio.cpte.com
minio_name: ??
minio_pass: ??
bucketName: otatest
jmreport:
saasMode:
firewall:
dataSourceSafe: false
lowCodeMode: dev
gao-de-api:
api-key: ??
secret-key: ??
redisson:
address: ${REDIS_HOST}:${REDIS_PORT}
password: ${REDIS_PASSWORD}
type: STANDALONE
enabled: true
baidu-api:
app-id: ??
api-key: ??
secret-key: ??
cas:
prefixUrl: http://cas.example.org:8443/cas
logging:
level:
org.springframework.context.support.PostProcessorRegistrationDelegate: error
org.flywaydb: debug
org.jeecg.modules.system.mapper: info
org.jeecg.modules.demo.test.mapper: info
knife4j:
enable: true
production: false
basic:
enable: false
username: cpte
password: cpte1314
# ========== 修复 Feign 配置 ==========
feign:
client:
wms-basic:
url: http://cpte-wms-basic:8001/cpte-wms-basic
config:
default:
connectTimeout: 5000
readTimeout: 10000
loggerLevel: INFO
---
# ===== 3. PersistentVolumeClaim - 文件存储 =====
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: cpte-wms-inbound-data
namespace: cpte-wms
annotations:
kubesphere.io/creator: admin
kubesphere.io/description: 文件上传存储
spec:
accessModes:
- ReadWriteOnce
storageClassName: local
resources:
requests:
storage: 10Gi
---
# ===== 4. Deployment - 系统服务(修复探针路径)=====
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
@ -5,8 +274,16 @@ metadata:
namespace: cpte-wms namespace: cpte-wms
labels: labels:
app: cpte-wms-inbound app: cpte-wms-inbound
version: v1
annotations:
kubesphere.io/description: "WMS-入库服务"
spec: spec:
replicas: 2 replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector: selector:
matchLabels: matchLabels:
app: cpte-wms-inbound app: cpte-wms-inbound
@ -14,75 +291,172 @@ spec:
metadata: metadata:
labels: labels:
app: cpte-wms-inbound app: cpte-wms-inbound
version: v1
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8002"
prometheus.io/path: "/cpte-wms-inbound/actuator/prometheus"
spec: spec:
initContainers:
- name: wait-for-mysql
image: busybox:1.36
command: ['sh', '-c', 'until nc -z mysql-service 3306; do echo waiting for mysql; sleep 2; done;']
- name: wait-for-redis
image: busybox:1.36
command: ['sh', '-c', 'until nc -z redis-service 6379; do echo waiting for redis; sleep 2; done;']
containers: containers:
- name: cpte-wms-inbound - name: cpte-wms-inbound
image: cpte-wms-inbound:3.8.3 image: docker.io/library/cpte-wms-inbound:2.0
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
ports: ports:
- containerPort: 8002 - name: http
envFrom: containerPort: 8002
- configMapRef: protocol: TCP
name: cpte-wms-config env:
- secretRef: - name: MYSQL_HOST
name: cpte-wms-secrets valueFrom:
env: secretKeyRef:
- name: SERVER_PORT name: cpte-wms-inbound-secret
value: "8002" key: MYSQL_HOST
- name: DB_URL - name: MYSQL_PORT
value: "jdbc:mysql://$(DB_HOST):$(DB_PORT)/$(DB_NAME)?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai" valueFrom:
- name: JAVA_OPTS secretKeyRef:
value: "$(JAVA_OPTS_SERVICES)" name: cpte-wms-inbound-secret
resources: key: MYSQL_PORT
requests: - name: MYSQL_DATABASE
memory: "256Mi" valueFrom:
cpu: "100m" secretKeyRef:
limits: name: cpte-wms-inbound-secret
memory: "512Mi" key: MYSQL_DATABASE
cpu: "500m" - name: MYSQL_USERNAME
volumeMounts: valueFrom:
- name: logs-path secretKeyRef:
mountPath: /data/logs name: cpte-wms-inbound-secret
livenessProbe: key: MYSQL_USERNAME
httpGet: - name: MYSQL_PASSWORD
path: /actuator/health valueFrom:
port: 8002 secretKeyRef:
initialDelaySeconds: 90 name: cpte-wms-inbound-secret
periodSeconds: 30 key: MYSQL_PASSWORD
timeoutSeconds: 10 - name: REDIS_HOST
failureThreshold: 3 valueFrom:
readinessProbe: secretKeyRef:
httpGet: name: cpte-wms-inbound-secret
path: /actuator/health key: REDIS_HOST
port: 8002 - name: REDIS_PORT
initialDelaySeconds: 45 valueFrom:
periodSeconds: 10 secretKeyRef:
timeoutSeconds: 5 name: cpte-wms-inbound-secret
failureThreshold: 3 key: REDIS_PORT
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: cpte-wms-inbound-secret
key: REDIS_PASSWORD
- name: MAIL_HOST
valueFrom:
secretKeyRef:
name: cpte-wms-inbound-secret
key: MAIL_HOST
- name: MAIL_USERNAME
valueFrom:
secretKeyRef:
name: cpte-wms-inbound-secret
key: MAIL_USERNAME
- name: MAIL_PASSWORD
valueFrom:
secretKeyRef:
name: cpte-wms-inbound-secret
key: MAIL_PASSWORD
- name: DRUID_LOGIN_PASSWORD
valueFrom:
secretKeyRef:
name: cpte-wms-inbound-secret
key: DRUID_LOGIN_PASSWORD
- name: SIGNATURE_SECRET
valueFrom:
secretKeyRef:
name: cpte-wms-inbound-secret
key: SIGNATURE_SECRET
- name: JAVA_OPTS
value: "-Xms512m -Xmx2048m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/app/logs/heapdump.hprof"
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "2000m"
memory: "2Gi"
# ========== 关键修复 3: 探针路径 ==========
livenessProbe:
httpGet:
path: /cpte-wms-inbound/actuator/health/liveness # ✅ 包含 context-path
port: 8002
initialDelaySeconds: 180
periodSeconds: 20
timeoutSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /cpte-wms-inbound/actuator/health/readiness # ✅ 包含 context-path
port: 8002
initialDelaySeconds: 120
periodSeconds: 15
timeoutSeconds: 10
failureThreshold: 3
startupProbe:
httpGet:
path: /cpte-wms-inbound/actuator/health/liveness # ✅ 包含 context-path
port: 8002
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 90
volumeMounts:
- name: cpte-wms-inbound-conf
mountPath: /app/application.yml
subPath: application.yml
readOnly: true
- name: cpte-wms-inbound-data
mountPath: /home/wms
- name: host-time
mountPath: /etc/localtime
readOnly: true
securityContext:
runAsNonRoot: false
volumes: volumes:
- name: logs-path - name: cpte-wms-inbound-conf
emptyDir: {} configMap:
name: cpte-wms-inbound-conf
items:
- key: application.yml
path: application.yml
- name: cpte-wms-inbound-data
persistentVolumeClaim:
claimName: cpte-wms-inbound-data
- name: host-time
hostPath:
path: /etc/localtime
type: File
restartPolicy: Always
--- ---
apiVersion: v1 # ===== 5. Service - ClusterIP 集群内访问 =====
kind: Service kind: Service
apiVersion: v1
metadata: metadata:
name: cpte-wms-inbound name: cpte-wms-inbound
namespace: cpte-wms namespace: cpte-wms
labels: labels:
app: cpte-wms-inbound app: cpte-wms-inbound
annotations:
spec: spec:
type: ClusterIP
ports: ports:
- port: 8002 - name: cpte-wms-inbound
targetPort: 8002 protocol: TCP
protocol: TCP port: 8002
name: http targetPort: 8002
selector: selector:
app: cpte-wms-inbound app: cpte-wms-inbound
clusterIP: 10.233.51.195
clusterIPs:
- 10.233.51.195
type: ClusterIP
sessionAffinity: None
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
internalTrafficPolicy: Cluster

View File

@ -1,88 +1,207 @@
apiVersion: apps/v1 # ===== 1. Secret - 库存服务认证信息 =====
kind: Deployment kind: Secret
apiVersion: v1
metadata: metadata:
name: cpte-wms-inventory name: inventory-service-secret
namespace: cpte-wms namespace: cpte-wms
labels: annotations:
app: cpte-wms-inventory kubesphere.io/creator: admin
spec: kubesphere.io/description: 库存服务认证信息
replicas: 2 data:
selector: DB_USERNAME: cm9vdA==
matchLabels: DB_PASSWORD: Y3B0ZUAxMjM=
app: cpte-wms-inventory REDIS_PASSWORD: Y3B0ZUAxMjM=
template: SWAGGER_USERNAME: Y3B0ZV9hZG1pbg==
metadata: SWAGGER_PASSWORD: Y3B0ZV9zZWN1cmVfMjAyNA==
labels: SIGNATURE_SECRET: ZGQwNWYxYzU0ZDYzNzQ5ZWRhOTVmOWZhNmQ0OXY0NDJh
app: cpte-wms-inventory type: Opaque
spec:
initContainers:
- name: wait-for-mysql
image: busybox:1.36
command: ['sh', '-c', 'until nc -z mysql-service 3306; do echo waiting for mysql; sleep 2; done;']
- name: wait-for-redis
image: busybox:1.36
command: ['sh', '-c', 'until nc -z redis-service 6379; do echo waiting for redis; sleep 2; done;']
containers:
- name: cpte-wms-inventory
image: cpte-wms-inventory:3.8.3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8004
envFrom:
- configMapRef:
name: cpte-wms-config
- secretRef:
name: cpte-wms-secrets
env:
- name: SERVER_PORT
value: "8004"
- name: DB_URL
value: "jdbc:mysql://$(DB_HOST):$(DB_PORT)/$(DB_NAME)?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai"
- name: JAVA_OPTS
value: "$(JAVA_OPTS_SERVICES)"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
volumeMounts:
- name: logs-path
mountPath: /data/logs
livenessProbe:
httpGet:
path: /actuator/health
port: 8004
initialDelaySeconds: 90
periodSeconds: 30
timeoutSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /actuator/health
port: 8004
initialDelaySeconds: 45
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
volumes:
- name: logs-path
emptyDir: {}
--- ---
# ===== 2. ConfigMap - 库存服务环境变量配置 =====
kind: ConfigMap
apiVersion: v1
metadata:
name: inventory-service-config
namespace: cpte-wms
annotations:
kubesphere.io/creator: admin
kubesphere.io/description: 库存服务环境变量配置
data:
SPRING_PROFILES_ACTIVE: "k8s"
TZ: "Asia/Shanghai"
JAVA_OPTS: "-Xms256m -Xmx512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
MYSQL_HOST: "mysql-service"
MYSQL_PORT: "3306"
MYSQL_DATABASE: "cpte-wms"
REDIS_HOST: "redis-service"
REDIS_PORT: "6379"
SERVER_PORT: "8004"
CONTEXT_PATH: "/cpte-wms-inventory"
---
# ===== 3. Service - 库存服务 =====
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: cpte-wms-inventory name: inventory-service
namespace: cpte-wms namespace: cpte-wms
labels: labels:
app: cpte-wms-inventory app: inventory-service
service: cpte-wms-inventory
spec: spec:
type: ClusterIP type: ClusterIP
ports:
- port: 8004
targetPort: 8004
protocol: TCP
name: http
selector: selector:
app: cpte-wms-inventory app: inventory-service
ports:
- name: http
port: 8004
targetPort: 8004
protocol: TCP
---
# ===== 4. Deployment - 库存服务 =====
apiVersion: apps/v1
kind: Deployment
metadata:
name: inventory-service
namespace: cpte-wms
labels:
app: inventory-service
service: cpte-wms-inventory
annotations:
kubesphere.io/description: "库存服务 - SpringBoot 微服务"
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: inventory-service
template:
metadata:
labels:
app: inventory-service
version: v1
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8004"
prometheus.io/path: "/cpte-wms-inventory/actuator/prometheus"
spec:
containers:
- name: inventory-service
image: cpte-registry/cpte-wms-inventory:latest
imagePullPolicy: IfNotPresent
command: ["java"]
args:
- "-Xms256m"
- "-Xmx512m"
- "-XX:+UseG1GC"
- "-XX:MaxGCPauseMillis=200"
- "-Dspring.profiles.active=k8s"
- "-Dserver.port=8004"
- "-Dserver.servlet.context-path=/cpte-wms-inventory"
- "-jar"
- "/app/app.jar"
ports:
- containerPort: 8004
name: http
protocol: TCP
env:
- name: SPRING_PROFILES_ACTIVE
valueFrom:
configMapKeyRef:
name: inventory-service-config
key: SPRING_PROFILES_ACTIVE
- name: TZ
valueFrom:
configMapKeyRef:
name: inventory-service-config
key: TZ
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: inventory-service-secret
key: DB_USERNAME
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: inventory-service-secret
key: DB_PASSWORD
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: inventory-service-secret
key: REDIS_PASSWORD
- name: MYSQL_HOST
valueFrom:
configMapKeyRef:
name: inventory-service-config
key: MYSQL_HOST
- name: MYSQL_PORT
valueFrom:
configMapKeyRef:
name: inventory-service-config
key: MYSQL_PORT
- name: MYSQL_DATABASE
valueFrom:
configMapKeyRef:
name: inventory-service-config
key: MYSQL_DATABASE
- name: REDIS_HOST
valueFrom:
configMapKeyRef:
name: inventory-service-config
key: REDIS_HOST
- name: REDIS_PORT
valueFrom:
configMapKeyRef:
name: inventory-service-config
key: REDIS_PORT
volumeMounts:
- name: inventory-logs
mountPath: /data/logs
- name: host-time
mountPath: /etc/localtime
readOnly: true
livenessProbe:
httpGet:
path: /cpte-wms-inventory/actuator/health
port: 8004
initialDelaySeconds: 90
periodSeconds: 20
timeoutSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /cpte-wms-inventory/actuator/health
port: 8004
initialDelaySeconds: 45
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
startupProbe:
httpGet:
path: /cpte-wms-inventory/actuator/health
port: 8004
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 30
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "1Gi"
cpu: "500m"
volumes:
- name: inventory-logs
emptyDir: {}
- name: host-time
hostPath:
path: /etc/localtime
type: File
restartPolicy: Always

View File

@ -1,88 +1,207 @@
apiVersion: apps/v1 # ===== 1. Secret - 出库服务认证信息 =====
kind: Deployment kind: Secret
apiVersion: v1
metadata: metadata:
name: cpte-wms-outbound name: outbound-service-secret
namespace: cpte-wms namespace: cpte-wms
labels: annotations:
app: cpte-wms-outbound kubesphere.io/creator: admin
spec: kubesphere.io/description: 出库服务认证信息
replicas: 2 data:
selector: DB_USERNAME: cm9vdA==
matchLabels: DB_PASSWORD: Y3B0ZUAxMjM=
app: cpte-wms-outbound REDIS_PASSWORD: Y3B0ZUAxMjM=
template: SWAGGER_USERNAME: Y3B0ZV9hZG1pbg==
metadata: SWAGGER_PASSWORD: Y3B0ZV9zZWN1cmVfMjAyNA==
labels: SIGNATURE_SECRET: ZGQwNWYxYzU0ZDYzNzQ5ZWRhOTVmOWZhNmQ0OXY0NDJh
app: cpte-wms-outbound type: Opaque
spec:
initContainers:
- name: wait-for-mysql
image: busybox:1.36
command: ['sh', '-c', 'until nc -z mysql-service 3306; do echo waiting for mysql; sleep 2; done;']
- name: wait-for-redis
image: busybox:1.36
command: ['sh', '-c', 'until nc -z redis-service 6379; do echo waiting for redis; sleep 2; done;']
containers:
- name: cpte-wms-outbound
image: cpte-wms-outbound:3.8.3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8003
envFrom:
- configMapRef:
name: cpte-wms-config
- secretRef:
name: cpte-wms-secrets
env:
- name: SERVER_PORT
value: "8003"
- name: DB_URL
value: "jdbc:mysql://$(DB_HOST):$(DB_PORT)/$(DB_NAME)?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai"
- name: JAVA_OPTS
value: "$(JAVA_OPTS_SERVICES)"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
volumeMounts:
- name: logs-path
mountPath: /data/logs
livenessProbe:
httpGet:
path: /actuator/health
port: 8003
initialDelaySeconds: 90
periodSeconds: 30
timeoutSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /actuator/health
port: 8003
initialDelaySeconds: 45
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
volumes:
- name: logs-path
emptyDir: {}
--- ---
# ===== 2. ConfigMap - 出库服务环境变量配置 =====
kind: ConfigMap
apiVersion: v1
metadata:
name: outbound-service-config
namespace: cpte-wms
annotations:
kubesphere.io/creator: admin
kubesphere.io/description: 出库服务环境变量配置
data:
SPRING_PROFILES_ACTIVE: "k8s"
TZ: "Asia/Shanghai"
JAVA_OPTS: "-Xms256m -Xmx512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
MYSQL_HOST: "mysql-service"
MYSQL_PORT: "3306"
MYSQL_DATABASE: "cpte-wms"
REDIS_HOST: "redis-service"
REDIS_PORT: "6379"
SERVER_PORT: "8003"
CONTEXT_PATH: "/cpte-wms-outbound"
---
# ===== 3. Service - 出库服务 =====
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: cpte-wms-outbound name: outbound-service
namespace: cpte-wms namespace: cpte-wms
labels: labels:
app: cpte-wms-outbound app: outbound-service
service: cpte-wms-outbound
spec: spec:
type: ClusterIP type: ClusterIP
ports:
- port: 8003
targetPort: 8003
protocol: TCP
name: http
selector: selector:
app: cpte-wms-outbound app: outbound-service
ports:
- name: http
port: 8003
targetPort: 8003
protocol: TCP
---
# ===== 4. Deployment - 出库服务 =====
apiVersion: apps/v1
kind: Deployment
metadata:
name: outbound-service
namespace: cpte-wms
labels:
app: outbound-service
service: cpte-wms-outbound
annotations:
kubesphere.io/description: "出库服务 - SpringBoot 微服务"
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: outbound-service
template:
metadata:
labels:
app: outbound-service
version: v1
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8003"
prometheus.io/path: "/cpte-wms-outbound/actuator/prometheus"
spec:
containers:
- name: outbound-service
image: cpte-registry/cpte-wms-outbound:latest
imagePullPolicy: IfNotPresent
command: ["java"]
args:
- "-Xms256m"
- "-Xmx512m"
- "-XX:+UseG1GC"
- "-XX:MaxGCPauseMillis=200"
- "-Dspring.profiles.active=k8s"
- "-Dserver.port=8003"
- "-Dserver.servlet.context-path=/cpte-wms-outbound"
- "-jar"
- "/app/app.jar"
ports:
- containerPort: 8003
name: http
protocol: TCP
env:
- name: SPRING_PROFILES_ACTIVE
valueFrom:
configMapKeyRef:
name: outbound-service-config
key: SPRING_PROFILES_ACTIVE
- name: TZ
valueFrom:
configMapKeyRef:
name: outbound-service-config
key: TZ
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: outbound-service-secret
key: DB_USERNAME
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: outbound-service-secret
key: DB_PASSWORD
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: outbound-service-secret
key: REDIS_PASSWORD
- name: MYSQL_HOST
valueFrom:
configMapKeyRef:
name: outbound-service-config
key: MYSQL_HOST
- name: MYSQL_PORT
valueFrom:
configMapKeyRef:
name: outbound-service-config
key: MYSQL_PORT
- name: MYSQL_DATABASE
valueFrom:
configMapKeyRef:
name: outbound-service-config
key: MYSQL_DATABASE
- name: REDIS_HOST
valueFrom:
configMapKeyRef:
name: outbound-service-config
key: REDIS_HOST
- name: REDIS_PORT
valueFrom:
configMapKeyRef:
name: outbound-service-config
key: REDIS_PORT
volumeMounts:
- name: outbound-logs
mountPath: /data/logs
- name: host-time
mountPath: /etc/localtime
readOnly: true
livenessProbe:
httpGet:
path: /cpte-wms-outbound/actuator/health
port: 8003
initialDelaySeconds: 90
periodSeconds: 20
timeoutSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /cpte-wms-outbound/actuator/health
port: 8003
initialDelaySeconds: 45
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
startupProbe:
httpGet:
path: /cpte-wms-outbound/actuator/health
port: 8003
initialDelaySeconds: 0
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 30
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "1Gi"
cpu: "500m"
volumes:
- name: outbound-logs
emptyDir: {}
- name: host-time
hostPath:
path: /etc/localtime
type: File
restartPolicy: Always

View File

@ -1,88 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: cpte-wms-schedule
namespace: cpte-wms
labels:
app: cpte-wms-schedule
spec:
replicas: 1
selector:
matchLabels:
app: cpte-wms-schedule
template:
metadata:
labels:
app: cpte-wms-schedule
spec:
initContainers:
- name: wait-for-mysql
image: busybox:1.36
command: ['sh', '-c', 'until nc -z mysql-service 3306; do echo waiting for mysql; sleep 2; done;']
- name: wait-for-redis
image: busybox:1.36
command: ['sh', '-c', 'until nc -z redis-service 6379; do echo waiting for redis; sleep 2; done;']
containers:
- name: cpte-wms-schedule
image: cpte-wms-schedule:3.8.3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8005
envFrom:
- configMapRef:
name: cpte-wms-config
- secretRef:
name: cpte-wms-secrets
env:
- name: SERVER_PORT
value: "8005"
- name: DB_URL
value: "jdbc:mysql://$(DB_HOST):$(DB_PORT)/$(DB_NAME)?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai"
- name: JAVA_OPTS
value: "$(JAVA_OPTS_SERVICES)"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
volumeMounts:
- name: logs-path
mountPath: /data/logs
livenessProbe:
httpGet:
path: /actuator/health
port: 8005
initialDelaySeconds: 90
periodSeconds: 30
timeoutSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /actuator/health
port: 8005
initialDelaySeconds: 45
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
volumes:
- name: logs-path
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: cpte-wms-schedule
namespace: cpte-wms
labels:
app: cpte-wms-schedule
spec:
type: ClusterIP
ports:
- port: 8005
targetPort: 8005
protocol: TCP
name: http
selector:
app: cpte-wms-schedule

View File

@ -1,3 +1,314 @@
# ===== 1. Secret - 应用敏感信息 =====
kind: Secret
apiVersion: v1
metadata:
name: cpte-wms-system-secret
namespace: cpte-wms
annotations:
kubesphere.io/creator: admin
kubesphere.io/description: 系统服务
type: Opaque
stringData:
MYSQL_HOST: "47.103.100.52"
MYSQL_PORT: "53306"
MYSQL_DATABASE: "cpte-wms"
MYSQL_USERNAME: "root"
MYSQL_PASSWORD: "Youchain@56"
REDIS_HOST: "redis-service"
REDIS_PORT: "6379"
REDIS_PASSWORD: "cpte@123"
MAIL_HOST: "smtp.163.com"
MAIL_USERNAME: "cpteos@163.com"
MAIL_PASSWORD: "cpte@123"
DRUID_LOGIN_PASSWORD: "cpte@123"
SIGNATURE_SECRET: "dd05f1c54d63749eda95f9fa6d49v442a"
---
# ===== 2. ConfigMap - 应用配置文件(修复 Shiro 格式)=====
kind: ConfigMap
apiVersion: v1
metadata:
name: cpte-wms-system-conf
namespace: cpte-wms
annotations:
kubesphere.io/creator: admin
kubesphere.io/description: 系统服务配置文件
data:
application.yml: |
server:
port: 8000
tomcat:
max-swallow-size: -1
error:
include-exception: true
include-stacktrace: ALWAYS
include-message: ALWAYS
servlet:
context-path: /cpte-wms
compression:
enabled: true
min-response-size: 1024
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
management:
endpoints:
web:
exposure:
include: health,info,prometheus,metrics
base-path: /actuator
endpoint:
health:
show-details: when_authorized
probes:
enabled: true
info:
enabled: true
prometheus:
enabled: true
security:
enabled: false
spring:
application:
name: cpte-wms-system
flyway:
enabled: false
clean-disabled: true
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
mail:
timeJobSend: false
host: ${MAIL_HOST}
username: ${MAIL_USERNAME}
password: ${MAIL_PASSWORD}
properties:
mail.smtp.timeout: 10000
mail.smtp.connectiontimeout: 10000
mail.smtp.writetimeout: 10000
mail.smtp.auth: true
mail.smtp.ssl.enable: true
quartz:
job-store-type: jdbc
jdbc:
initialize-schema: embedded
auto-startup: true
startup-delay: 1s
overwrite-existing-jobs: true
properties:
org:
quartz:
scheduler:
instanceName: MyScheduler
instanceId: AUTO
jobStore:
class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: QRTZ_
isClustered: true
misfireThreshold: 12000
clusterCheckinInterval: 15000
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
jpa:
open-in-view: false
aop:
proxy-target-class: true
freemarker:
suffix: .ftl
content-type: text/html
charset: UTF-8
cache: false
prefer-file-system-access: false
template-loader-path:
- classpath:/templates
template_update_delay: 0
mvc:
static-path-pattern: /**
pathmatch:
matching-strategy: ant_path_matcher
resource:
static-locations: classpath:/static/,classpath:/public/
autoconfigure:
exclude:
- com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure
- org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration
datasource:
druid:
stat-view-servlet:
enabled: true
loginUsername: admin
loginPassword: ${DRUID_LOGIN_PASSWORD}
web-stat-filter:
enabled: true
dynamic:
druid:
initial-size: 5
min-idle: 5
maxActive: 1000
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
filters: stat,slf4j
wall:
selectWhereAlwayTrueCheck: false
stat:
slow-sql-millis: 5000
merge-sql: true
datasource:
master:
url: jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_DATABASE}?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
username: ${MYSQL_USERNAME}
password: ${MYSQL_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
data:
redis:
database: 0
host: ${REDIS_HOST}
port: ${REDIS_PORT}
password: ${REDIS_PASSWORD}
mybatis-plus:
mapper-locations: classpath*:org/jeecg/**/xml/*Mapper.xml,classpath*:org/cpte/**/xml/*Mapper.xml
global-config:
banner: false
db-config:
id-type: ASSIGN_ID
table-underline: true
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
call-setners-on-nulls: true
minidao:
base-package: org.jeecg.modules.jmreport.*,org.jeecg.modules.drag.*
# ========== 关键修复Shiro excludeUrls 改为单行 ==========
jeecg:
firewall:
dataSourceSafe: false
lowCodeMode: dev
signatureSecret: ${SIGNATURE_SECRET}
signUrls: /sys/dict/getDictItems/*,/sys/dict/loadDict/*,/sys/dict/loadDictOrderByValue/*,/sys/dict/loadDictItem/*,/sys/dict/loadTreeData,/sys/api/queryTableDictItemsByCode,/sys/api/queryFilterTableDictInfo,/sys/api/queryTableDictByKeys,/sys/api/translateDictFromTable,/sys/api/translateDictFromTableByKeys,/sys/sendChangePwdSms,/sys/user/sendChangePhoneSms,/sys/sms,/desform/api/sendVerifyCode
uploadType: local
domainUrl:
pc: http://101.35.253.46:8000/cpte-wms/sys/common/upload
app: http://101.35.253.46:8051
path:
upload: /home/wms/upload
webapp: /home/wms/webapp
shiro:
excludeUrls: /test/cpteDemo/demo3,/test/cpteDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**,/cpte-wms/actuator/**,/actuator/**
oss:
accessKey: ??
secretKey: ??
endpoint: oss-cn-beijing.aliyuncs.com
bucketName: cptedev
sms-template:
signature:
templateCode:
SMS_175435174:
SMS_465391221:
SMS_175430166:
file-view-domain: http://fileview.cpte.com
minio:
minio_url: http://minio.cpte.com
minio_name: ??
minio_pass: ??
bucketName: otatest
jmreport:
saasMode:
firewall:
dataSourceSafe: false
lowCodeMode: dev
gao-de-api:
api-key: ??
secret-key: ??
redisson:
address: ${REDIS_HOST}:${REDIS_PORT}
password: ${REDIS_PASSWORD}
type: STANDALONE
enabled: true
baidu-api:
app-id: ??
api-key: ??
secret-key: ??
cas:
prefixUrl: http://cas.example.org:8443/cas
logging:
level:
org.springframework.context.support.PostProcessorRegistrationDelegate: error
org.flywaydb: debug
org.jeecg.modules.system.mapper: info
org.jeecg.modules.demo.test.mapper: info
knife4j:
enable: true
production: false
basic:
enable: false
username: cpte
password: cpte1314
justauth:
enabled: true
type:
GITHUB:
client-id: ??
client-secret: ??
redirect-uri: http://101.35.253.46:8000/cpte-wms/sys/thirdLogin/github/callback
WECHAT_ENTERPRISE:
client-id: ??
client-secret: ??
redirect-uri: http://101.35.253.46:8000/cpte-wms/sys/thirdLogin/wechat_enterprise/callback
agent-id: ??
DINGTALK:
client-id: ??
client-secret: ??
redirect-uri: http://101.35.253.46:8000/cpte-wms/sys/thirdLogin/dingtalk/callback
WECHAT_OPEN:
client-id: ??
client-secret: ??
redirect-uri: http://101.35.253.46:8000/cpte-wms/sys/thirdLogin/wechat_open/callback
cache:
type: default
prefix: 'demo::'
timeout: 1h
---
# ===== 3. PersistentVolumeClaim - 文件存储 =====
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: cpte-wms-system-data
namespace: cpte-wms
annotations:
kubesphere.io/creator: admin
kubesphere.io/description: 文件上传存储
spec:
accessModes:
- ReadWriteOnce
storageClassName: local
resources:
requests:
storage: 10Gi
---
# ===== 4. Deployment - 系统服务(修复探针路径)=====
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
@ -5,8 +316,16 @@ metadata:
namespace: cpte-wms namespace: cpte-wms
labels: labels:
app: cpte-wms-system app: cpte-wms-system
version: v1
annotations:
kubesphere.io/description: "WMS-系统服务"
spec: spec:
replicas: 2 replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector: selector:
matchLabels: matchLabels:
app: cpte-wms-system app: cpte-wms-system
@ -14,81 +333,171 @@ spec:
metadata: metadata:
labels: labels:
app: cpte-wms-system app: cpte-wms-system
version: v1
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8000"
prometheus.io/path: "/cpte-wms/actuator/prometheus"
spec: spec:
initContainers:
- name: wait-for-mysql
image: busybox:1.36
command: ['sh', '-c', 'until nc -z mysql-service 3306; do echo waiting for mysql; sleep 2; done;']
- name: wait-for-redis
image: busybox:1.36
command: ['sh', '-c', 'until nc -z redis-service 6379; do echo waiting for redis; sleep 2; done;']
containers: containers:
- name: cpte-wms-system - name: cpte-wms-system
image: cpte-wms-system:3.8.3 image: docker.io/library/cpte-wms-system:1.0
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
ports: ports:
- containerPort: 8000 - name: http
envFrom: containerPort: 8000
- configMapRef: protocol: TCP
name: cpte-wms-config env:
- secretRef: - name: MYSQL_HOST
name: cpte-wms-secrets valueFrom:
env: secretKeyRef:
- name: SERVER_PORT name: cpte-wms-system-secret
value: "8000" key: MYSQL_HOST
- name: DB_URL - name: MYSQL_PORT
value: "jdbc:mysql://$(DB_HOST):$(DB_PORT)/$(DB_NAME)?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai" valueFrom:
resources: secretKeyRef:
requests: name: cpte-wms-system-secret
memory: "512Mi" key: MYSQL_PORT
cpu: "250m" - name: MYSQL_DATABASE
limits: valueFrom:
memory: "1Gi" secretKeyRef:
cpu: "1000m" name: cpte-wms-system-secret
volumeMounts: key: MYSQL_DATABASE
- name: upload-path - name: MYSQL_USERNAME
mountPath: /data/upload valueFrom:
- name: webapp-path secretKeyRef:
mountPath: /data/webapp name: cpte-wms-system-secret
- name: logs-path key: MYSQL_USERNAME
mountPath: /data/logs - name: MYSQL_PASSWORD
livenessProbe: valueFrom:
httpGet: secretKeyRef:
path: /cpte-wms/actuator/health name: cpte-wms-system-secret
port: 8000 key: MYSQL_PASSWORD
initialDelaySeconds: 120 - name: REDIS_HOST
periodSeconds: 30 valueFrom:
timeoutSeconds: 10 secretKeyRef:
failureThreshold: 3 name: cpte-wms-system-secret
readinessProbe: key: REDIS_HOST
httpGet: - name: REDIS_PORT
path: /cpte-wms/actuator/health valueFrom:
port: 8000 secretKeyRef:
initialDelaySeconds: 60 name: cpte-wms-system-secret
periodSeconds: 10 key: REDIS_PORT
timeoutSeconds: 5 - name: REDIS_PASSWORD
failureThreshold: 3 valueFrom:
secretKeyRef:
name: cpte-wms-system-secret
key: REDIS_PASSWORD
- name: MAIL_HOST
valueFrom:
secretKeyRef:
name: cpte-wms-system-secret
key: MAIL_HOST
- name: MAIL_USERNAME
valueFrom:
secretKeyRef:
name: cpte-wms-system-secret
key: MAIL_USERNAME
- name: MAIL_PASSWORD
valueFrom:
secretKeyRef:
name: cpte-wms-system-secret
key: MAIL_PASSWORD
- name: DRUID_LOGIN_PASSWORD
valueFrom:
secretKeyRef:
name: cpte-wms-system-secret
key: DRUID_LOGIN_PASSWORD
- name: SIGNATURE_SECRET
valueFrom:
secretKeyRef:
name: cpte-wms-system-secret
key: SIGNATURE_SECRET
- name: JAVA_OPTS
value: "-Xms512m -Xmx2048m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/app/logs/heapdump.hprof"
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "2000m"
memory: "2Gi"
# ========== 关键修复 3: 探针路径 ==========
livenessProbe:
httpGet:
path: /cpte-wms/actuator/health/liveness # ✅ 包含 context-path
port: 8000
initialDelaySeconds: 180
periodSeconds: 20
timeoutSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /cpte-wms/actuator/health/readiness # ✅ 包含 context-path
port: 8000
initialDelaySeconds: 120
periodSeconds: 15
timeoutSeconds: 10
failureThreshold: 3
startupProbe:
httpGet:
path: /cpte-wms/actuator/health/liveness # ✅ 包含 context-path
port: 8000
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 90
volumeMounts:
- name: cpte-wms-system-conf
mountPath: /app/application.yml
subPath: application.yml
readOnly: true
- name: cpte-wms-system-data
mountPath: /home/wms
- name: host-time
mountPath: /etc/localtime
readOnly: true
securityContext:
runAsNonRoot: false
volumes: volumes:
- name: upload-path - name: cpte-wms-system-conf
emptyDir: {} configMap:
- name: webapp-path name: cpte-wms-system-conf
emptyDir: {} items:
- name: logs-path - key: application.yml
emptyDir: {} path: application.yml
- name: cpte-wms-system-data
persistentVolumeClaim:
claimName: cpte-wms-system-data
- name: host-time
hostPath:
path: /etc/localtime
type: File
restartPolicy: Always
--- ---
apiVersion: v1 # ===== 5. Service - ClusterIP 集群内访问 =====
kind: Service kind: Service
apiVersion: v1
metadata: metadata:
name: cpte-wms-system name: cpte-wms-system
namespace: cpte-wms namespace: cpte-wms
labels: labels:
app: cpte-wms-system app: cpte-wms-system
spec: spec:
type: ClusterIP
ports: ports:
- port: 8000 - name: http
targetPort: 8000 protocol: TCP
protocol: TCP port: 8000
name: http targetPort: 8000
selector: selector:
app: cpte-wms-system app: cpte-wms-system
clusterIP: 10.233.44.59
clusterIPs:
- 10.233.44.59
type: ClusterIP
sessionAffinity: None
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
internalTrafficPolicy: Cluster

3116
sql/cpte-wms.sql 100644

File diff suppressed because it is too large Load Diff

12
sql/package.json 100644
View File

@ -0,0 +1,12 @@
{
"name": "sql",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": ""
}

File diff suppressed because it is too large Load Diff