# 风七六本地生活服务平台全量开发规范 --- ## 部署文档参考 - **阿里云开发环境部署方案 **:[基于 Podman 的阿里云开发环境全量部署方案(完善版)](file:///d:/FzxBDSH/FzxFile/%E5%9F%BA%E4%BA%8E%20Podman%20%E7%9A%84%E9%98%BF%E9%87%8C%E4%BA%91%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E5%85%A8%E9%87%8F%E9%83%A8%E7%BD%B2%E6%96%B9%E6%A1%88%EF%BC%88%E5%AE%8C%E5%96%84%E7%89%88%EF%BC%89.md) --- ## 一、技术栈规范 ### 1.1 容器技术 #### 容器运行时 - **使用 Podman** 而非 Docker - Podman 是无守护进程的容器引擎,更安全、更轻量 - 命令兼容 Docker,但使用 `podman` 命令 #### 容器编排 - **使用 podman-compose** 而非 docker-compose - 配置文件格式与 docker-compose 兼容 - 命令:`podman-compose up -d`、`podman-compose down` #### 镜像仓库 - 国内镜像加速:`docker.m.daocloud.io`、`docker.1ms.run` - 镜像命名格式:`docker.m.daocloud.io/library/:` #### Podman 与 Docker 兼容注意事项 - Podman 网络模式默认使用 bridge,需注意端口映射配置 - Podman 不支持 Docker 的 `--network host` 方式,需使用 `--network=host` - Podman 卷挂载路径格式与 Docker 一致 ### 1.2 数据库 #### 主数据库(MariaDB) - **使用 MariaDB** 而非 MySQL(商业授权合规要求) - MariaDB 是 MySQL 的开源分支,完全兼容 MySQL - 版本:10.11(LTS 版本) - 镜像:`docker.m.daocloud.io/library/mariadb:10.11` #### 数据库连接配置 - JDBC URL 格式:`jdbc:mariadb://:/` - 驱动类:`org.mariadb.jdbc.Driver` - 如果应用不支持 MariaDB 驱动,可以使用 MySQL 兼容模式: - JDBC URL:`jdbc:mysql://:/` - 驱动类:`com.mysql.cj.jdbc.Driver` #### PostgreSQL(用于 Kong API 网关) - 版本:16.4 - 镜像:`postgres:16.4` #### 数据库表/字段命名规范 - 表名:小写 + 下划线,如 `order_info`、`user_address` - 字段名:小写 + 下划线,如 `user_mobile`、`order_amount` - 主键:`id`(自增)或 `uuid`(分布式场景) - 外键:`{关联表名}_id`,如 `user_id`、`order_id` ### 1.3 服务注册与配置中心(Nacos) #### 基础配置 - 版本:2.4.3 - 镜像:`docker.1ms.run/nacos/nacos-server:v2.4.3` - 模式:standalone(单机模式,开发环境)/ cluster(集群模式,生产环境) - 存储:嵌入式存储(开发环境)/ MariaDB(生产环境) #### 配置注意事项 - Nacos 2.4.3 使用 MySQL 驱动连接 MariaDB - 环境变量命名:`MYSQL_SERVICE_*` 而非 `SPRING_DATASOURCE_*` - 如果外部数据库配置失败,Nacos 会自动回退到嵌入式存储 #### 配置分层(Nacos) - 公共配置:`common-{profile}.yml`(所有服务共享) - 业务配置:`{service}-{profile}.yml`(各服务独立配置) - 优先级:服务配置 > 公共配置 > 本地配置 ### 1.4 缓存(Redis) #### 基础配置 - 版本:7.2.4 - 镜像:`docker.m.daocloud.io/library/redis:7.2.4` - 配置文件:`./config/redis/redis.conf` #### 核心配置示例 ```ini # 内存限制(生产环境建议 2GB) maxmemory 2gb maxmemory-policy allkeys-lru # 持久化配置 appendonly yes appendfsync everysec # 连接限制 maxclients 10000 timeout 0 ``` ### 1.5 消息队列(RocketMQ) #### 基础配置 - 版本:5.3.1 - 镜像:`docker.1ms.run/apache/rocketmq:5.3.1` - 组件:NameServer + Broker #### 部署建议 - 开发环境:单节点 NameServer + 单节点 Broker - 生产环境:双节点 NameServer + 双节点 Broker(主从) ### 1.6 API 网关(Kong) #### 基础配置 - 版本:3.9.0 - 镜像:`docker.1ms.run/library/kong:3.9.0` - 数据库:PostgreSQL ### 1.7 监控体系 #### Prometheus - 版本:v2.54.1 - 镜像:`docker.1ms.run/prom/prometheus:v2.54.1` #### Grafana - 版本:11.2.0 - 镜像:`docker.1ms.run/grafana/grafana:11.2.0` ### 1.8 网络配置 #### 自定义网络 - 网络名称:`fzx-network` - 驱动:bridge - 子网:172.20.0.0/16 - 网关:172.20.0.1 #### 网络别名 - MariaDB:`mariadb` - Redis:`redis` - PostgreSQL:`postgres` - Nacos:`nacos` #### 阿里云环境网络配置(关键!) **问题背景**:阿里云ECS默认使用`systemd-resolved`,宿主机`/etc/resolv.conf`指向`127.0.0.53` ,Podman默认bridge网络不做DNS转发,导致容器内无法解析内部服务名(如`nacos`),直接报**NXDOMAIN**。 **解决方案**: 1. **创建自定义网络**(必须!) ```bash # 删除旧默认网络(可选) podman network rm bridge # 创建自定义网络(带DNS解析) podman network create fzx-aliyun-dev-network --subnet=172.20.0.0/16 --gateway=172.20.0.1 ``` 2. **配置容器DNS** ```bash # 临时:覆盖宿主机resolv.conf echo "nameserver 223.5.5.5" > /etc/resolv.conf echo "nameserver 119.29.29.29" >> /etc/resolv.conf # 永久:修改podman配置 vi /etc/containers/containers.conf # 找到 [network],添加: dns_servers = ["223.5.5.5", "119.29.29.29"] ``` 3. **compose文件配置示例** ```yaml networks: fzx-aliyun-dev-network: external: true driver: bridge ipam: config: - subnet: 172.20.0.0/16 gateway: 172.20.0.1 dns: - 223.5.5.5 - 119.29.29.29 ``` **避坑要点**: - **网络不统一**:所有服务必须在**同一个自定义网络**,不能混用默认bridge - **DNS没改**:阿里云宿主机默认`127.0.0.53`,容器用不了,必须改成**公共DNS** - **Nacos地址别写localhost**:容器内`localhost`是容器自己,必须写**服务名nacos**或**宿主机IP** ### 1.9 数据持久化 #### 命名卷 - 使用 Podman 命名卷而非 bind mount - 命名格式:`fzx-{service}-data` - 示例:`fzx-mariadb-data`、`fzx-redis-data` #### 卷配置示例 ```yaml volumes: mariadb-data: name: fzx-mariadb-data driver: local ``` --- ## 二、开发流程规范 ### 2.1 代码提交规则 #### 自动检验流程 每次修改或生成文件完成后,必须执行以下检验和提交流程: 1. **检查仓库状态** ```bash git status ``` 2. **查看修改内容** ```bash git diff ``` 3. **本地验证清单** - 单元测试通过率 100% - 代码检查 0 错误 - 编译无异常 - 相关文档已更新 4. **添加修改到暂存区** ```bash git add -A ``` 5. **提交修改** ```bash git commit -m ": - - - " ``` 6. **推送到远程仓库** ```bash git push origin develop ``` #### 提交信息规范 提交信息必须遵循以下格式: ``` : ``` ##### Type 类型 - `feat`: 新功能 - `fix`: 修复 bug - `docs`: 文档更新 - `style`: 代码格式调整(不影响功能) - `refactor`: 代码重构 - `perf`: 性能优化 - `test`: 测试相关 - `chore`: 构建过程或辅助工具的变动 - `ci`: CI/CD 配置 - `build`: 构建相关 ##### Subject 规范 - 使用中文描述 - 不超过 50 个字 - 使用动词开头,如"添加"、"修复"、"更新" - 结尾不加句号 ##### Body 规范 - 使用中文描述 - 每行不超过 72 个字 - 详细说明修改内容和原因 - 使用列表形式列出主要修改 #### 提交限制 - 单次提交代码量不超过 500 行 - 避免超大提交,拆分逻辑相关的修改 #### 合并请求(MR/PR)审核规则 - 至少 1 人审核通过 - 审核内容包括:代码质量、安全性、命名规范、测试覆盖 #### 示例 ``` feat: 添加用户登录功能 - 实现 JWT 认证机制 - 添加登录页面 UI - 集成微信登录接口 - 添加登录状态管理 ``` ### 2.2 分支管理规则 #### 分支策略 - `main`: 生产环境分支(受保护) - `develop`: 开发环境分支 - `feature/*`: 功能开发分支(从 develop 创建) - `hotfix/*`: 紧急修复分支(从 main 创建) - `release/*`: 发布分支(从 develop 创建) #### 工作流程 1. 从 `develop` 分支创建功能分支:`feature/user-login` 2. 在功能分支上开发并提交 3. 完成后合并回 `develop` 分支(需 MR 审核) 4. 定期将 `develop` 分支推送到远程仓库 5. 发布前创建 `release/{version}` 分支进行测试 6. 测试通过后合并到 `main` 和 `develop` #### 分支命名规范 - 功能分支:`feature/{功能名称}`,如 `feature/payment-integration` - 修复分支:`hotfix/{问题描述}`,如 `hotfix/order-payment-error` - 发布分支:`release/{版本号}`,如 `release/v1.0.0` ### 2.3 文档管理规则 #### 文档更新 - 修改代码时必须更新相关文档 - 添加新功能时必须添加使用文档 - 修改 API 时必须更新 API 文档 #### 文档位置 - 项目文档:`/docs` - API 文档:`/docs/api` - 部署文档:`/docs/deployment` #### 文档格式 - 使用 Markdown 格式 - 文件名使用小写 + 中横线,如 `api-documentation.md` - 图片存放在 `/docs/assets` 目录 ### 2.4 跨团队协作规范 #### 接口联调流程 1. **需求评审**:各团队共同评审接口设计文档(API 文档需包含请求/响应格式、错误码、超时时间) 2. **契约测试**:使用 Pact 或 Spring Cloud Contract 进行接口契约测试 3. **联调环境**:在测试环境进行联合调试,确保接口互通 4. **文档同步**:接口变更需同步更新 API 文档,并通知相关团队 #### 分支合并冲突处理 1. **冲突检测**:合并前先拉取目标分支最新代码,本地解决冲突 2. **冲突分类**: - **代码逻辑冲突**:与相关开发人员沟通确认解决方案 - **配置文件冲突**:保留最新配置或协商合并 - **测试文件冲突**:运行测试验证合并结果 3. **冲突记录**:记录重大冲突及解决方案,便于后续复盘 #### 基线更新同步机制 1. **同步通知**:基线更新后 24 小时内通知所有开发人员 2. **同步时效**:开发人员需在收到通知后 48 小时内同步基线 3. **未同步风险**:未同步基线可能导致代码冲突,责任由开发人员承担 --- ## 三、项目基线管理规范 ### 3.1 基线定义 **clean-base** 分支为项目唯一纯净基线,是所有功能开发、bug 修复、环境部署的基础版本。 #### 基线要求 - ✅ 无编译错误 - ✅ 无未使用代码、无冗余依赖 - ✅ 无敏感配置、无本地调试代码 - ✅ 数据库、网关、服务注册发现配置统一规范 - ✅ 可直接构建、启动、部署 ### 3.2 基线使用规则 - **禁止直接在 clean-base 上开发业务功能** - **所有新功能必须从 clean-base 分支拉出开发分支** - **基线仅接受**:架构修复、配置统一、依赖清理、代码规范修复 - **基线提交必须清晰标注**:`chore: 基线更新` / `fix: 基线修复` - **每次基线更新必须本地验证构建成功** ### 3.3 基线更新流程(必须遵守) ``` 1. 切换到 clean-base → git checkout clean-base → git pull origin clean-base 2. 修复问题(规范、依赖、配置、未使用代码) 3. 本地构建验证(mvn compile) → cd backend && mvn clean compile -DskipTests 4. 提交并推送 → git add -A → git commit -m "chore: 基线更新 - 清理未使用依赖" → git push origin clean-base 5. 通知所有开发人员同步最新基线 ``` ### 3.4 基线禁止行为 - ❌ 不允许提交临时文件、测试文件、IDE 配置文件 - ❌ 不允许提交未完成代码、注释代码 - ❌ 不允许强制推送他人修改过的基线 - ❌ 不允许在基线中混合业务功能与架构修复 ### 3.5 基线版本管理 - 基线版本采用语义化版本控制:`v{major}.{minor}.{patch}-clean-base` - 重大架构变更升级 major 版本 - 配置/依赖清理升级 minor 版本 - 修复性更新升级 patch 版本 - 版本标签示例:`v1.0.0-clean-base`、`v1.1.0-clean-base`、`v1.1.1-clean-base` ### 3.6 临时文件管理规则 #### 临时文件存放位置 所有本地优化配置、临时文件统一存放在: ``` local_optimization_temp/ ├── kong/ # Kong网关配置 ├── temp_security/ # 临时安全工具 ├── nginx/ # Nginx配置 ├── Dockerfile.optimized # 优化版Dockerfile └── init-kong.sh # Kong初始化脚本 ``` #### 临时文件规则 | 规则 | 说明 | |------------------|-----------------------| | ✅ 保留在本地 | 作为本地优化参考 | | ❌ 不提交Git | 不污染版本库 | | ❌ 不合并到基线 | 保持基线纯净 | | 🔄 可复制到feature分支 | 如需正式集成,先移到feature分支测试 | #### .gitignore 配置 确保以下内容已在 `.gitignore` 中: ``` local_optimization_temp/ *.local *.temp *.tmp .DS_Store .idea/ .vscode/ ``` --- ## 四、质量与安全规范 ### 4.1 代码质量规则 #### 代码检查 - 提交前必须运行代码检查工具 - 修复所有错误和警告 - 保持代码风格一致 - **连带修复原则**:在修复问题过程中发现的相关问题(如编译错误、明显的代码缺陷、缺失的导入等),应一并解决,避免后续重复进入相同代码模块浪费时间。但需保持提交原子性,可拆分多个提交。 #### 测试要求 - 新增功能必须包含单元测试(覆盖率 ≥ 80%) - 修复 bug 必须包含回归测试 - 提交前必须确保所有测试通过 #### 代码注释规范 ##### 类/方法注释模板(JavaDoc/TSDoc) ```java /** * 功能描述:用户服务接口 * * @author 作者名 * @version 1.0.0 * @since 2026-05-01 */ public interface UserService { /** * 根据用户ID获取用户信息 * * @param userId 用户ID(必填) * @return 用户信息对象 * @throws NotFoundException 用户不存在时抛出 */ User getUserById(String userId); } ``` ##### 注释要求 - 复杂业务逻辑必须加注释 - 注释语言统一使用中文 - 避免无意义注释(如 `// 获取用户`) - 定期清理过时注释 #### 导入顺序规范(阿里开发手册强制规范) **【强制】** Java 导入语句必须按以下顺序排列,组间不允许有空行: ``` 1. java.* (Java 标准库) 2. javax.* (Java 扩展库) 3. org.* (第三方组织库,如 Spring、Hibernate) 4. com.* (本公司/项目内部包) 5. net.* (网络相关库) 6. static 导入 (静态导入,放在最后) ``` **导入顺序规则:** - 每组导入之间**不允许有空行** - 同组内导入按字母顺序排列 - 同一模块的导入应集中排列 - 未使用的导入必须删除 **常见第三方库分组示例:** | 库 | 分组 | |---|------| | java.util, java.time, java.io | java | | javax.servlet, javax.persistence | javax | | org.springframework, org.apache, org.slf4j | org | | com.fzx, com.google | com | **反面示例(错误):** ```java import com.fzx.service.UserService; // com 在前 import org.springframework.stereotype.Service; // org 在后 import java.util.List; // java 在最后 ``` **正面示例(正确):** ```java import java.util.List; import org.springframework.stereotype.Service; import com.fzx.service.UserService; ``` #### 方法参数数量规范(阿里开发手册强制规范) **【强制】** 方法参数数量限制: | 参数数量 | 处理方式 | |---------|---------| | ≤ 3 个 | 可直接使用基本参数 | | 4-5 个 | 建议封装为DTO对象 | | > 5 个 | **必须**封装为DTO对象 | | > 7 个 | Checkstyle强制报错,必须修复 | **规范说明:** - 参数过多会导致方法调用复杂、可读性差、维护困难 - 封装DTO对象可以提高代码可维护性和可扩展性 - DTO对象应使用Lombok的`@Data`、`@Builder`注解简化代码 **反面示例(错误):** ```java // 8个参数,违反规范 private WithdrawalRecord createWithdrawalRecord(Long accountId, SplitAccount account, BigDecimal amount, BigDecimal fee, BigDecimal actualAmount, String bankName, String bankAccount, String accountName) { // ... } ``` **正面示例(正确):** ```java // 使用DTO封装参数 @Data @Builder @NoArgsConstructor @AllArgsConstructor public class WithdrawalCreationDTO { private Long accountId; private Object account; private BigDecimal amount; private BigDecimal fee; private BigDecimal actualAmount; private String bankName; private String bankAccount; private String accountName; } private WithdrawalRecord createWithdrawalRecord(WithdrawalCreationDTO dto) { // ... } ``` **DTO命名规范:** - 创建类DTO:`{业务对象}CreationDTO`,如`WithdrawalCreationDTO` - 更新类DTO:`{业务对象}UpdateDTO`,如`WithdrawalUpdateDTO` - 查询类DTO:`{业务对象}QueryDTO`,如`WithdrawalQueryDTO` - DTO应放置在对应模块的`dto`包下 ### 4.2 安全规则 #### 敏感信息管理 - 禁止提交密码、密钥等敏感信息 - 使用环境变量或配置文件管理敏感信息 - 定期检查代码中的敏感信息泄露(CI/CD 自动扫描) #### 硬编码防护 - 禁止硬编码配置信息,如域名、URL、端口等 - 禁止硬编码敏感信息,如 API 密钥、密码等 - 使用配置文件或环境变量管理所有配置信息 - 对于 CORS 配置,必须使用配置文件管理允许的域名列表 #### 输入验证 - 对所有用户输入进行严格的验证和过滤 - 验证输入的类型、长度、格式等 - 防止 SQL 注入、XSS 攻击等安全漏洞 - 使用参数化查询处理数据库操作 #### 接口签名规则 - API 请求必须包含 `timestamp` + `nonce` + `sign` 校验 - 签名算法:HMAC-SHA256 - timestamp 有效期:5 分钟(防止重放攻击) - nonce:随机字符串,确保请求唯一性 #### 认证和授权 - 实现强密码策略(8-32 位,包含大小写字母、数字、特殊字符) - 使用 HTTPS 协议传输敏感数据 - 实现基于角色的访问控制(RBAC) - 定期更新认证令牌(JWT Token 过期时间:2 小时) - 实现会话超时机制(30 分钟无操作自动退出) #### 数据加密 - 敏感数据(手机号、身份证号)使用 AES-256 加密存储 - 传输敏感数据使用 HTTPS + TLS 1.3 - 定期更新加密密钥(每季度轮换) - RSA 密钥长度:2048 位(签名)/ 4096 位(加密) #### 安全日志记录 - 记录所有安全相关的操作(登录、权限变更、数据访问) - 记录异常访问和攻击尝试 - 定期检查和分析安全日志 - 实现日志备份和归档(保留 30 天) --- ## 五、部署脚本规范(强制) ### 5.1 错误码标准化 所有部署脚本必须使用统一错误码: | 错误码 | 常量名 | 说明 | |-----|--------|------| | 0 | `SUCCESS` | 成功 | | 21 | `NO_DEPLOY_SERVICES` | 无可部署服务 | | 33 | `INVALID_COMPOSE_FILE` | 无效的compose文件 | | 40 | `KEY_MISSING` | 密钥缺失 | | 41 | `KEY_TOO_SHORT` | 密钥长度不足 | | 42 | `KEY_VERIFY_FAILED` | 密钥验证失败 | | 43 | `DECRYPT_FAILED` | 环境解密失败 | | 50 | `PRE_CHECK_FAILED` | 前置校验失败 | | 50 | `DISK_SPACE_INSUFFICIENT` | 磁盘空间不足 | | 51 | `COMPOSE_SYNTAX_ERROR` | Compose语法错误 | | 52 | `IMAGE_NOT_FOUND` | 镜像不存在 | | 53 | `REGISTRY_LOGIN_FAILED` | 仓库登录失败 | | 1 | `DEPLOY_FAILED` | 部署失败 | ### 5.2 前置校验规范 所有部署脚本必须执行以下前置校验: | 校验项 | 开关变量 | 错误码 | 说明 | |-------|--------|------|------| | 目录权限 | `SKIP_PRE_CHECK` | 50 | 检查部署目录权限为755 | | 磁盘空间 | `SKIP_DISK_CHECK` | 50 | 检查磁盘使用率<90% | | Compose语法 | - | 51 | 验证compose配置文件语法 | | 仓库登录 | `SKIP_REGISTRY_LOGIN` | 53 | 验证镜像仓库连通性 | | 镜像存在性 | `SKIP_IMAGE_CHECK` | 52 | 验证目标镜像存在 | | 端口占用 | `SKIP_PORT_CHECK` | 50 | 检查服务端口未被占用 | ### 5.3 配置加密规范 #### 加密算法 - **算法**:AES-256-GCM - **密钥长度**:32字节(64位十六进制)或32位字符串 - **IV长度**:12字节(随机生成) - **Tag长度**:16字节 #### 加密格式 ``` ENCRYPTED::{base64编码的加密数据} ``` #### 加密验证 在解密前必须执行加密解密验证: ```python test_plaintext = 'fzx_encryption_test_2024' encrypted = encrypt_value(test_plaintext, key) decrypted = decrypt_value(encrypted, key) if decrypted != test_plaintext: return ErrorCode.KEY_VERIFY_FAILED ``` #### 解密失败处理 - **任何配置项解密失败**:立即阻断部署 - **返回错误码**:43(DECRYPT_FAILED) - **禁止继续执行**:不要使用原始加密值继续部署 ### 5.4 校验日志规范 所有前置校验日志必须添加 `[PRE_CHECK]` 前缀: ``` [PRE_CHECK] 执行部署前置校验... [PRE_CHECK] 1/6 校验部署目录权限... [PRE_CHECK] OK: 目录权限已修正为755 [PRE_CHECK] 2/6 校验磁盘空间... [PRE_CHECK] INFO: 磁盘空间检查: /opt - 可用=20G, 使用率=60% [PRE_CHECK] 3/6 校验Compose语法... [PRE_CHECK] OK: Compose语法校验通过: podman-compose.aliyun-dev.yml [PRE_CHECK] 4/6 校验镜像仓库连通性... [PRE_CHECK] OK: 镜像仓库已登录: registry.cn-hangzhou.aliyuncs.com [PRE_CHECK] 5/6 校验镜像存在性... [PRE_CHECK] OK: 镜像存在: registry.cn-hangzhou.aliyuncs.com/fzxbdsh/api-gateway:v1.1.0 [PRE_CHECK] 6/6 校验端口占用... [PRE_CHECK] OK: 端口占用检查通过 ``` ### 5.5 脚本开发要求 - ✅ 必须使用错误码返回 - ✅ 必须包含完整的错误日志输出 - ✅ 必须执行前置校验 - ✅ 禁止硬编码敏感信息 - ✅ 禁止使用明文密码 - ✅ 必须支持校验开关配置 --- ## 六、配置管理规范(强制) ### 6.1 环境变量规范 #### 环境变量文件结构 ``` env/ ├── .env.example # 示例配置(无敏感信息) └── .env.aliyun-dev # 加密的环境变量文件(提交到Git) ``` #### 敏感变量清单 | 变量名 | 用途 | 加密要求 | |-------|------|---------| | `MARIADB_ROOT_PASSWORD` | 数据库根密码 | 必须加密 | | `MARIADB_PASSWORD` | 数据库服务密码 | 必须加密 | | `REDIS_PASSWORD` | Redis密码 | 必须加密 | | `JWT_SECRET_KEY` | JWT密钥 | 必须加密 | | `NACOS_PASSWORD` | Nacos密码 | 必须加密 | | `REGISTRY_USERNAME` | 镜像仓库用户名 | 必须加密 | | `REGISTRY_PASSWORD` | 镜像仓库密码 | 必须加密 | | `WEBHOOK_TOKEN` | Webhook令牌 | 必须加密 | | `JENKINS_PASSWORD` | Jenkins密码 | 必须加密 | #### 环境变量命名规范 - 全大写,下划线分隔 - 前缀标识用途:`MARIADB_`、`REDIS_`、`JWT_`、`NACOS_`等 - 避免缩写,使用完整单词 ### 6.2 配置文件加密规范 #### 加密流程 ``` 1. 创建.env文件(包含敏感信息) ↓ 2. 使用env-encrypt.py加密 ↓ 3. 生成.env.aliyun-dev(加密版本) ↓ 4. 提交加密版本到Git ↓ 5. 删除明文版本 ``` #### 解密流程 ``` 1. 从Jenkins Credentials获取ENV_ENCRYPT_KEY ↓ 2. 在本地(Jenkins容器内)解密.env.aliyun-dev ↓ 3. 上传解密后的.env文件到服务器 ↓ 4. 执行部署 ``` #### 加密密钥管理 - **密钥存储**:Jenkins Credentials(ID: `env-encrypt-key`) - **密钥格式**:64位十六进制或32位字符串 - **密钥轮换**:每90天轮换一次,更新所有相关加密配置 --- ## 七、镜像仓库管理规范(强制) ### 7.1 镜像仓库配置 #### 本地开发环境仓库 - **仓库名称**:fzx-local-registry - **地址**:`http://localhost:5000` - **数据目录**:`D:\opt\local-registry\data`(Windows)/ `/opt/local-registry/data`(Linux) - **用途**:本地开发、测试镜像存储 #### 阿里云开发环境仓库 - **仓库名称**:fzx-aliyun-registry - **地址**:`http://localhost:5000`(容器网络) - **数据目录**:`/opt/local-registry/data` - **用途**:阿里云开发环境镜像存储 #### 阿里云容器镜像服务 - **仓库地址**:`registry.cn-hangzhou.aliyuncs.com/fzxbdsh` - **用途**:CI/CD流水线构建、部署镜像存储 - **认证方式**:使用 `REGISTRY_USERNAME`/`REGISTRY_PASSWORD` 环境变量 ### 7.2 镜像标签策略(强制) #### 标签命名规范 | 标签类型 | 格式 | 示例 | 用途 | |--------|------|------|------| | 开发测试标签 | `latest` | `localhost:5000/fzx/api-gateway:latest` | 本地开发、快速迭代 | | 稳定版本标签 | `v{major}.{minor}.{patch}` | `localhost:5000/fzx/api-gateway:v1.1.0` | 阿里云开发/测试环境部署 | #### 版本号同步规则 - **镜像版本号必须与基线版本保持一致** - 当前基线版本:`v1.1.0-clean-base` → 镜像标签:`v1.1.0` - 基线升级后,镜像标签同步升级 ### 7.3 镜像仓库登录规范(强制) #### 登录凭证配置 - **凭证来源**:Jenkins Credentials 或环境变量 - **用户名变量**:`REGISTRY_USERNAME` - **密码变量**:`REGISTRY_PASSWORD` - **禁止硬编码**:禁止在任何脚本或配置文件中硬编码仓库凭证 #### 登录验证流程 ``` 1. 部署前检查是否已登录 ↓ 2. 未登录时使用环境变量凭证登录 ↓ 3. 登录失败时阻断部署流程 ↓ 4. 返回错误码 53(REGISTRY_LOGIN_FAILED) ``` #### 依赖管理 - 定期更新依赖(每月检查) - 检查依赖包的安全漏洞(使用 dependency-check 或类似工具) - 使用固定版本(禁止使用 `latest`) - 第三方依赖审计流程(每月执行) - 引入新依赖前必须进行安全评估 #### 供应链安全扫描(SCA) - **强制启用 dependency-check**:绑定 Maven verify 阶段,作为上线安全卡点 - **离线模式配置**:生产环境网络隔离时使用离线模式,配置如下: ```xml org.owasp dependency-check-maven true ${maven.user.home}/.dependency-check true true 0 ``` - **漏洞库更新**:每月在联网环境执行 `mvn dependency-check:check` 更新本地缓存 - **禁止永久禁用**:仅允许临时跳过(`-Ddependency-check.skip=true`)或临时注释 execution,禁止删除插件配置 #### 安全审计日志规范 ```json { "timestamp": "2026-05-12T10:30:00", "level": "INFO", "traceId": "abc123", "userId": "123456", "operation": "LOGIN", "resource": "/api/v1/user/login", "status": "SUCCESS", "clientIp": "192.168.1.1", "userAgent": "Mozilla/5.0", "detail": "用户登录成功" } ``` ### 4.3 业务场景特殊规则 #### 支付/订单核心流程 - 接口幂等性设计(使用订单号/请求 ID 去重) - 分布式事务保障(使用 RocketMQ 消息事务) - 支付回调必须验证签名 - 订单状态机严格校验(禁止非法状态转换) ### 4.4 CI/CD 效率优化规范 #### Maven 依赖缓存 - 在 Jenkins Pipeline 中配置 Maven 本地仓库缓存 - 基于 `pom.xml` 哈希值生成缓存密钥 - 配置回退密钥,提高缓存命中率 ```groovy options { cache(path: '~/.m2/repository', key: 'maven-${MD5SUM(pom.xml)}', restoreKeys: ['maven-']) } ``` #### Docker 镜像分层缓存 - 使用 `--cache-from` 参数复用已有镜像层 - 按环境打标签,便于缓存复用 - 保留 `latest` 标签作为缓存源 #### 流水线并行化 - 单元测试与代码质量检查并行执行 - 不同环境采用不同的并行策略(开发环境简化) - 使用 `parallel` 块实现阶段并行 ```groovy stage('Parallel Tests') { parallel { stage('Unit Test') { steps { sh 'mvn test' } } stage('Code Quality') { steps { sh 'mvn checkstyle:check pmd:check' } } } } ``` ### 4.5 质量左移规范 #### Pre-commit 钩子配置 - 使用 `pre-commit` 工具在代码提交前执行检查 - 配置 Checkstyle 代码风格检查 - 添加 trailing-whitespace、remove-tabs 等基础检查 ```yaml repos: - repo: https://github.com/pre-commit/mirrors-checkstyle rev: 'google_checks' hooks: - id: checkstyle args: ['-c', 'checkstyle/checkstyle.xml'] - repo: https://github.com/Lucas-C/pre-commit-hooks rev: v1.1.10 hooks: - id: remove-tabs - id: trailing-whitespace ``` #### 钩子安装与使用 ```bash # 安装 pre-commit pip install pre-commit # 安装钩子 pre-commit install # 手动执行检查 pre-commit run --all-files ``` ### 4.6 监控告警规范 #### 告警分级策略 | 级别 | 触发条件 | 响应时间 | |--------|-----------------------|------| | P1(紧急) | Jenkins服务宕机、服务器磁盘>90% | 15分钟 | | P2(重要) | 构建连续失败≥3次、证书有效期<7天 | 30分钟 | | P3(一般) | 容器异常退出、资源使用率>80% | 1小时 | #### 钉钉告警集成 - 使用钉钉机器人推送告警消息 - 配置健康检查脚本定时执行 - 覆盖服务器、容器、应用多维度监控 ```bash send_alert() { local message=$1 curl -s -X POST $DINGTALK_WEBHOOK \ -H 'Content-Type: application/json' \ -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"$message\"}}" } ``` #### 运维操作标准化 - 环境切换脚本集成至 Jenkins 流水线 - 实现一键切换环境(dev/test/pre) - 操作日志自动记录,便于问题追溯 #### 巡检闭环流程 - 定期执行巡检脚本 - 记录 CPU、内存、容器状态等指标 - 异常情况自动触发告警 #### 高并发场景 - **Redis 限流**(单用户每秒最多 10 次请求) - **MQ 削峰**(秒杀场景使用消息队列缓冲) - **数据库读写分离**(读操作走从库) - **接口熔断降级**(使用 Sentinel 或 Hystrix) ##### Redis 限流实现示例(令牌桶算法) ```java // 使用 Redis 实现令牌桶限流 public boolean isAllowed(String userId, String resourceKey, int maxTokens, int refillRate) { String bucketKey = "rate:limit:" + resourceKey + ":" + userId; String timestampKey = bucketKey + ":timestamp"; try (var redisOps = redisTemplate.opsForValue()) { long now = System.currentTimeMillis() / 1000; Long currentTokens = redisOps.increment(bucketKey, -1); if (currentTokens == null || currentTokens > maxTokens) { // 初始化令牌桶 redisOps.set(bucketKey, String.valueOf(maxTokens)); redisOps.set(timestampKey, String.valueOf(now)); return true; } if (currentTokens >= 0) { return true; } // 令牌耗尽,尝试补充 Long lastRefillTime = Long.parseLong(redisOps.get(timestampKey)); long tokensToAdd = (now - lastRefillTime) * refillRate; if (tokensToAdd > 0) { long newTokens = Math.min(tokensToAdd, maxTokens); redisOps.set(bucketKey, String.valueOf(newTokens)); redisOps.set(timestampKey, String.valueOf(now)); return newTokens > 0; } return false; } } ``` ##### RocketMQ 分布式事务示例 ```java // 半消息发送 + 本地事务 + 事务状态回查 public void sendOrderMessage(String orderId, String payload) throws MQClientException { TransactionMQProducer producer = new TransactionMQProducer("order-transaction-group"); producer.setTransactionListener(new TransactionListener() { @Override public LocalTransactionState executeLocalTransaction(Message msg, Object arg) { try { // 1. 执行本地事务(扣库存、创建订单) orderService.createOrder(orderId); inventoryService.decreaseStock(orderId); return LocalTransactionState.COMMIT_MESSAGE; } catch (Exception e) { log.error("本地事务失败", e); return LocalTransactionState.ROLLBACK_MESSAGE; } } @Override public LocalTransactionState checkLocalTransaction(MessageExt msg) { // 回查本地事务状态 String orderId = msg.getKeys(); if (orderService.isOrderCreated(orderId)) { return LocalTransactionState.COMMIT_MESSAGE; } return LocalTransactionState.ROLLBACK_MESSAGE; } }); Message message = new Message("order-topic", "order-tag", orderId, payload.getBytes()); producer.sendMessageInTransaction(message, null); } #### 数据脱敏规则 - 手机号:`138****1234`(中间 4 位脱敏) - 身份证号:`110101**********1234`(中间 8 位脱敏) - 地址:`北京市朝阳区****街道`(详细地址脱敏) - 脱敏规则统一封装工具类,禁止重复实现 --- ## 四、交付与部署规范 ### 4.1 部署前检查 - 确保所有测试通过 - 确保代码已提交并推送 - 确保文档已更新 - 确认配置文件正确(环境变量、数据库连接等) ### 4.2 部署流程 #### 标准部署步骤 1. **构建前端应用**(执行 `npm run build`) 2. **构建后端服务**(执行 `mvn clean package`) 3. **打包 Docker/Podman 镜像** 4. **运行数据库迁移**(Flyway) 5. **部署到服务器**(滚动发布) 6. **验证部署结果**(健康检查、接口测试) #### 滚动发布流程 1. 停止部分容器(如 1/3) 2. 部署新版本 3. 启动新容器并验证健康状态 4. 重复步骤 1-3 直到全部更新完成 5. 监控服务状态 10 分钟 #### 蓝绿发布流程(适用于重大变更) 1. 部署新版本到"绿环境" 2. 验证绿环境服务正常 3. 切换流量到绿环境 4. 保留蓝环境一段时间(回滚备用) 5. 确认稳定后销毁蓝环境 #### 部署回滚规则 - 发布失败后 10 分钟内必须回滚 - 回滚流程:停止新版本 → 启动旧版本 → 验证服务 - 回滚后需记录原因并复盘 ### 4.3 容器化部署 #### 容器资源限制 | 服务 | CPU | 内存 | 备注 | |------|-----|------|------| | MariaDB | 2核 | 4GB | 生产环境 | | Redis | 1核 | 2GB | 生产环境 | | Nacos | 1核 | 1GB | 单机模式 | | API Gateway | 2核 | 2GB | 生产环境 | | 业务服务 | 1核 | 1GB | 每个服务 | #### 健康检查配置 ```yaml healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] interval: 30s timeout: 10s retries: 3 start_period: 60s ``` #### Kubernetes 适配(规模化部署) ##### Deployment 配置示例 ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: platform-service spec: replicas: 3 selector: matchLabels: app: platform-service template: metadata: labels: app: platform-service spec: containers: - name: platform-service image: fzx-platform-service:latest resources: requests: memory: "512Mi" cpu: "100m" limits: memory: "1Gi" cpu: "500m" livenessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 60 periodSeconds: 30 readinessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 30 periodSeconds: 10 ``` ##### HPA 自动扩缩容配置 ```yaml apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: platform-service-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: platform-service minReplicas: 3 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70 #### 日志管理 - 使用 JSON 文件驱动 - 设置日志大小限制(单个文件 100MB) - 日志保留数量(保留 30 个) - 启用日志压缩(gzip) - 日志采集:使用 Filebeat/Fluentd 采集到 Elasticsearch ### 4.4 CI/CD 流程规范 #### CI 流程 ``` 代码提交 → 代码检查(SonarQube)→ 单元测试 → 构建 → 镜像构建 → 镜像扫描(Trivy) ``` #### CD 流程 ``` 镜像推送 → 部署到测试环境 → 自动化测试 → 人工验证 → 部署到生产环境(滚动发布) ``` #### CI/CD 质量门禁 - 代码覆盖率 ≥ 80% - 代码检查无严重/阻断级问题 - 单元测试通过率 100% - 镜像扫描无高危漏洞 ### 4.5 监控运维 #### 监控指标 - CPU 使用率(阈值:>80% 告警) - 内存使用率(阈值:>85% 告警) - 磁盘使用率(阈值:>90% 告警) - 接口响应时间(阈值:>1s 告警) - 错误率(阈值:>5% 告警) #### 告警机制 - **告警渠道**:钉钉/企业微信/邮件 - **告警级别**:紧急(立即通知)、重要(10 分钟内处理)、一般(工作日处理) - **告警收敛**:同一问题 5 分钟内只告警一次 - **告警联动**:CPU>90% + 错误率>10% 自动触发服务降级 #### APM 链路追踪 - **工具选型**:SkyWalking 或 Jaeger - **追踪范围**:API Gateway → 业务服务 → 数据库 → 缓存 - **采样策略**:生产环境 10% 采样,测试环境 100% 采样 - **关键指标**: - 服务响应时间(P50/P95/P99) - 调用链成功率 - 数据库慢查询(>500ms) #### 故障应急预案 ##### 核心服务降级策略 - 支付服务降级:切换到备用支付通道 - 订单服务降级:只读模式,暂停创建订单 - 用户服务降级:缓存用户信息,减少数据库查询 ##### 数据库/缓存故障兜底 - 数据库故障:使用本地缓存数据应急 - Redis 故障:降级为数据库直接查询(性能下降但可用) - 主库故障:自动切换到从库 ##### 应急响应流程 1. 收到告警 → 确认问题 → 启动应急预案 2. 降级服务(如必要)→ 通知相关人员 3. 排查根因 → 修复问题 → 恢复服务 4. 复盘总结 → 更新应急预案 --- ## 五、命名与设计规范 ### 5.1 命名规范 #### 核心原则 | 原则 | 说明 | |------|------| | **全部小写** | 服务名、容器名、域名等必须使用小写字母 | | **中横线连接** | 单词之间使用中横线 `-` 连接,禁止使用下划线或驼峰 | | **业务领域命名** | 使用业务领域名称命名,不使用 `admin`、`manager`、`console` 等模糊词汇 | | **全局唯一** | 服务名在整个项目中必须唯一 | | **语义清晰** | 命名应直观表达服务/组件的功能 | #### 服务命名规范 **服务名格式**: `{业务领域}-service` | 服务名称 | 服务标识 | |----------|----------| | 平台端服务 | `platform-service` | | 用户端服务 | `user-service` | | 商家端服务 | `merchant-service` | | 骑手端服务 | `rider-service` | | 订单服务 | `order-service` | | API 网关 | `api-gateway` | #### 容器命名规范 **容器名格式**: `{环境}-{服务标识}` | 环境 | 标识 | |------|------| | 本地开发 | `fzx-local` | | 开发环境 | `dev` | | 测试环境 | `test` | | 生产环境 | `prod` | #### URL 路由规范 | 应用 | 主路径 | 别名路径(兼容) | |------|--------|----------------| | 平台端 | `/platform/` | `/admin/` | | 用户端 | `/user/` | - | | 商家端 | `/merchant/` | - | | 骑手端 | `/rider/` | - | | 官方网站 | `/official/` | `/`(根路径) | #### 前端组件/页面命名 - 组件:`PascalCase`,如 `UserOrderList.vue`、`MerchantCard.tsx` - 页面:`PascalCase`,如 `OrderDetailPage.vue` - 工具函数:`camelCase`,如 `formatPhone.ts` - 常量:`UPPER_SNAKE_CASE`,如 `MAX_RETRY_COUNT` #### 日志文件命名 - 格式:`{服务名}-{日期}.log` - 示例:`platform-service-2026-05-12.log` #### 统一别名规则 为保持向后兼容性,允许以下别名映射: - `platform` → `admin`(平台端管理后台,兼容旧链接) > **注意**:别名仅用于 URL 路由兼容,代码和配置中必须使用主名称 `platform`。 ### 5.2 UI/UX 设计规范 #### 主色调规范 - **主色调统一使用 #067bff** - 所有页面、组件、按钮、导航栏等 UI 元素的主色调必须使用 #067bff - 禁止使用 #1890ff、#ff7f00 等其他颜色作为主色调 - 主色调应用场景:按钮、导航栏、选中状态、重要图标等 #### 多端一致性规范 - 用户端小程序版本与 APP 版本必须保持功能、页面、交互体验完全一致 - 小程序版本必须包含与 APP 版本相同的所有页面 - 底部导航栏配置必须一致,包含相同数量的页面和相同的图标 - 所有新增功能必须同时在小程序和 APP 版本中实现 --- ## 六、接口规范 ### 6.1 RESTful API 字段规范 #### 响应码定义 | 响应码 | 含义 | 使用场景 | |--------|------|----------| | 200 | 成功 | 请求成功,返回数据 | | 201 | 创建成功 | POST 请求成功创建资源 | | 204 | 无内容 | 请求成功,但无返回数据 | | 400 | 参数错误 | 请求参数校验失败 | | 401 | 未认证 | 用户未登录或 Token 过期 | | 403 | 无权限 | 用户无权限访问该资源 | | 404 | 资源不存在 | 请求的资源不存在 | | 409 | 冲突 | 资源冲突(如重复提交) | | 500 | 服务异常 | 服务器内部错误 | #### 响应格式规范 ```json { "code": 200, "message": "success", "data": { // 业务数据 }, "timestamp": 1715472000000 } ``` #### 错误响应格式 ```json { "code": 400, "message": "参数错误:用户ID不能为空", "data": null, "timestamp": 1715472000000, "errorDetail": { "field": "userId", "message": "不能为空" } } ``` ### 6.2 接口版本管理 - 版本标识:`/v{版本号}/`,如 `/v1/user/login` - 版本升级策略:新增接口使用新版本,旧版本保留一段时间 - 版本废弃:提前 30 天通知,废弃后返回 410(Gone) ### 6.3 接口幂等性设计 - 使用 `requestId`(客户端生成的唯一标识)去重 - 对于支付/订单等核心接口,必须实现幂等性 - 幂等性保证时间:至少 24 小时 - 幂等性存储:使用 Redis 存储 requestId,设置过期时间 ### 6.4 分页响应格式规范 ```json { "code": 200, "message": "success", "data": { "list": [], "pagination": { "pageNum": 1, "pageSize": 10, "total": 100, "totalPages": 10 } }, "timestamp": 1715472000000 } ``` ### 6.5 API 限流规范 - **限流策略**:基于用户 ID/IP 的令牌桶限流 - **限流阈值**: - 普通接口:单用户每秒 10 次 - 核心接口(支付/订单):单用户每秒 5 次 - 公共接口:单 IP 每分钟 100 次 - **限流返回码**:429(Too Many Requests) - **限流提示**:{"code": 429, "message": "请求过于频繁,请稍后重试"} --- ## 七、多环境配置规范 ### 7.1 环境隔离方案 #### 配置文件结构 ``` backend/ ├── src/main/resources/ │ ├── application.yml # 公共配置 │ ├── application-dev.yml # 开发环境 │ ├── application-test.yml # 测试环境 │ └── application-prod.yml # 生产环境 └── .env # 环境变量(不提交版本控制) ``` #### 环境变量文件 - 文件位置:`./.env` - 包含所有敏感信息(密码、密钥等) - 不要提交到版本控制 #### 环境变量命名 - 使用大写字母和下划线 - 前缀表示服务名称 - 示例:`MARIADB_ROOT_PASSWORD`、`REDIS_PASSWORD` ### 7.2 配置中心分层(Nacos) #### 配置优先级(从高到低) 1. 运行时参数(命令行参数) 2. Nacos 服务配置(`{service}-{profile}.yml`) 3. Nacos 公共配置(`common-{profile}.yml`) 4. 本地配置文件(`application-{profile}.yml`) 5. 本地公共配置(`application.yml`) --- ## 八、最佳实践 ### 8.1 前端最佳实践 #### 架构设计 - 使用分层架构,将 UI、业务逻辑、数据访问分离 - 采用状态管理库(如 Provider、GetX)管理应用状态 - 实现路由管理,使用命名路由或路由导航器 #### API 集成 - 封装网络服务,统一处理 API 调用 - 实现错误处理机制,包括网络错误、业务错误等 - 使用拦截器处理认证 Token、请求/响应格式化等 #### 性能优化 - 使用 const 构造函数创建不变的 Widget - 实现懒加载和缓存机制 - 优化图片加载,使用适当的图片格式和大小 - 减少不必要的重建和重绘 #### 用户体验 - 实现加载状态和错误提示 - 提供离线支持和缓存策略 - 优化动画和过渡效果 ### 8.2 后端最佳实践 #### API 设计 - 采用 RESTful API 设计风格 - 统一响应格式,包含状态码、消息和数据 - 实现 API 版本控制 - 提供 API 文档(如 Swagger) #### 代码结构 - 采用分层架构,如 Controller、Service、Mapper - 实现依赖注入,减少代码耦合 - 使用异常处理机制,统一处理错误 #### 数据库设计 - 使用数据库迁移工具(如 Flyway)管理数据库结构 - 设计合理的表结构和索引 - 实现事务管理,确保数据一致性 #### 安全措施 - 实现认证和授权机制 - 防止 SQL 注入、XSS 等安全漏洞 - 对敏感数据进行加密处理 ### 8.3 中间件最佳实践 #### API 网关 - 配置合理的路由规则 - 实现限流、熔断等保护机制 - 统一处理跨域请求 #### 服务注册和发现 - 使用服务注册中心(如 Nacos)管理服务 - 实现服务健康检查和自动发现 #### 缓存策略 - 使用 Redis 等缓存技术提高性能 - 设计合理的缓存键和过期策略 - 实现缓存与数据库的一致性保证 ##### 缓存穿透防护 ```java // 使用布隆过滤器防止缓存穿透 public User getUserById(Long userId) { // 1. 先查布隆过滤器 if (!bloomFilter.mightContain(userId)) { return null; } // 2. 查缓存 User user = (User) redisTemplate.opsForValue().get("user:" + userId); if (user != null) { return user; } // 3. 查数据库 user = userRepository.findById(userId).orElse(null); if (user != null) { redisTemplate.opsForValue().set("user:" + userId, user, 30, TimeUnit.MINUTES); } else { // 空值也缓存,防止缓存穿透 redisTemplate.opsForValue().set("user:" + userId, null, 5, TimeUnit.MINUTES); } return user; } ``` ##### 缓存击穿防护(热点key过期) ```java // 使用分布式锁防止缓存击穿 public User getHotUser(Long userId) { String cacheKey = "user:hot:" + userId; // 1. 先查缓存 User user = (User) redisTemplate.opsForValue().get(cacheKey); if (user != null) { return user; } // 2. 获取分布式锁 String lockKey = "lock:user:" + userId; Boolean lockAcquired = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 30, TimeUnit.SECONDS); if (Boolean.TRUE.equals(lockAcquired)) { try { // 3. 双重检查缓存 user = (User) redisTemplate.opsForValue().get(cacheKey); if (user != null) { return user; } // 4. 查询数据库 user = userRepository.findById(userId).orElse(null); if (user != null) { redisTemplate.opsForValue().set(cacheKey, user, 2, TimeUnit.HOURS); } } finally { redisTemplate.delete(lockKey); } } else { // 等待其他线程更新缓存后重试 Thread.sleep(100); return getHotUser(userId); } return user; } ``` ##### 缓存雪崩防护 - **方案1**:设置不同的过期时间(随机偏移 0-30 分钟) - **方案2**:使用多级缓存(本地缓存 + Redis) - **方案3**:热点数据永不过期,后台定时更新 --- ## 九、问题排查 ### 9.1 Podman 配置错误 - **错误**:`invalid escape in string` - **解决**:检查 `/etc/containers/registries.conf.d/99-mirror.conf` 文件格式 ### 9.2 容器无法启动 1. 检查日志:`podman logs ` 2. 检查环境变量:`podman exec env` 3. 检查网络:`podman network inspect fzx-network` ### 9.3 数据库连接失败 1. 确认数据库容器正在运行 2. 确认网络别名正确 3. 确认用户名和密码正确 4. 确认数据库已创建 ### 9.4 Nacos 启动失败 1. 检查内存配置(至少 256MB) 2. 检查数据库连接配置 3. 查看日志:`podman logs fzx-local-nacos` ### 9.5 接口调用失败 1. 检查网络连通性:`curl http://localhost:8089/api/health` 2. 检查服务是否注册到 Nacos 3. 检查网关路由配置 --- ## 十、后端开发强制规范 ### 10.1 数据库字符集强制规范 #### 10.1.1 建库强制规则 所有业务库、新库,必须按以下标准创建: ```sql CREATE DATABASE 库名 DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci; ``` **禁止**:不指定字符集直接建库;使用 `utf8` / `latin1` / `gbk` #### 10.1.2 建表强制规则 所有业务表结尾必须固定声明: ```sql ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ``` #### 10.1.3 字段设计约束 - 所有字符串类业务字段,统一用 `varchar` / `text` - 禁止使用非 `utf8mb4` 排序规则 - 预留 emoji、生僻字存储能力 ### 10.2 JDBC 连接串统一规范 #### 标准模板 ```yaml jdbc:mariadb://mariadb:3306/库名?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=Asia/Shanghai&useSSL=false&allowMultiQueries=true ``` #### 强制必带参数 - `useUnicode=true` - `characterEncoding=utf8mb4` - `serverTimezone=Asia/Shanghai` ### 10.3 MariaDB Docker 部署规范 ```yaml command: - --character-set-server=utf8mb4 - --collation-server=utf8mb4_unicode_ci - --init-connect=SET NAMES utf8mb4 - --skip-character-set-client-handshake ``` ### 10.4 Spring Boot 依赖注入规范 #### 统一注入方案 所有 `@Service` / `@Component` / `@FeignClient` 实现类: - 统一使用 **Lombok + 构造器注入** - 固定注解:`@RequiredArgsConstructor` #### 标准模板 ```java @Service @RequiredArgsConstructor public class XxxServiceImpl implements XxxService { private final XxxMapper xxxMapper; private final XxxFeign xxxFeign; } ``` #### 三条红线(严禁违反) 1. **禁止混用**:同时写 `@Autowired` 字段 + 手动构造器 + `@RequiredArgsConstructor` 2. **禁止手写**无参/有参构造器与 Lombok 注解共存 3. **禁止**注入字段不加 `final` ### 10.5 阿里开发手册核心编码规范(强制) #### 10.5.1 空值判断规范 **强制要求**:使用 `Objects.isNull()` / `Objects.nonNull()` 替代 `== null` / `!= null` ```java // 正确写法 if (Objects.isNull(user)) { throw new ResourceNotFoundException("User", userId); } if (Objects.nonNull(user.getAddress())) { // 处理地址 } // 错误写法(禁止) if (user == null) { ... } if (user != null) { ... } ``` #### 10.5.2 字符串判断规范 **强制要求**:使用 `StringUtils.isEmpty()` / `StringUtils.isBlank()` 判断字符串 ```java // 正确写法 if (StringUtils.isEmpty(name)) { ... } if (StringUtils.isBlank(description)) { ... } // 错误写法(禁止) if ("".equals(name)) { ... } if (name == "") { ... } ``` #### 10.5.3 集合初始化规范 **强制要求**:集合初始化时必须指定初始容量 ```java // 正确写法 List list = new ArrayList<>(10); Map map = new HashMap<>(16); Set set = new HashSet<>(8); // 错误写法(禁止) List list = new ArrayList<>(); // 未指定初始容量 ``` **容量选择原则**: - 预估元素数量 <= 7:初始容量设为 8 - 预估元素数量 <= 15:初始容量设为 16 - 预估元素数量 <= 31:初始容量设为 32 #### 10.5.4 异常处理规范 **强制要求**:禁止直接抛出 `RuntimeException` / `Exception`,必须使用自定义异常 ```java // 正确写法 throw new ResourceNotFoundException("User", userId); throw new BusinessException("ORDER_EXPIRED", "订单已过期"); throw new ValidationException("phone", "手机号格式不正确"); // 错误写法(禁止) throw new RuntimeException("用户不存在"); throw new Exception("业务异常"); ``` #### 10.5.5 日志规范 **强制要求**:使用参数化日志,禁止字符串拼接 ```java // 正确写法 log.info("用户登录成功,用户ID:{}", userId); log.warn("订单状态异常,订单号:{},状态:{}", orderNo, status); log.error("支付失败,订单ID:{},错误信息:{}", orderId, e.getMessage(), e); // 错误写法(禁止) log.info("用户登录成功,用户ID:" + userId); log.info("用户登录成功,用户ID:" + userId + ",时间:" + System.currentTimeMillis()); ``` #### 10.5.6 方法参数规范 **强制要求**:方法参数不超过 4 个,超过时使用 DTO 封装 ```java // 正确写法 public void createOrder(OrderCreateDTO dto) { ... } // 错误写法(禁止) public void createOrder(Long userId, Long merchantId, BigDecimal amount, String address, String phone, String remark) { ... } ``` #### 10.5.7 魔法数字规范 **强制要求**:魔法数字必须定义为常量 ```java // 正确写法 private static final int MAX_RETRY_COUNT = 3; private static final int TIMEOUT_SECONDS = 30; // 错误写法(禁止) if (retryCount >= 3) { ... } if (timeout > 30) { ... } ``` --- ## 十一、团队协作规范 ### 11.1 代码审核规则 - 所有合并到 clean-base 的代码必须经过至少 1 人审核 - 审核内容包括:代码质量、安全性、命名规范、测试覆盖 - 审核通过后方可合并 ### 11.2 基线同步通知 基线更新后 24 小时内通知所有开发人员: ``` 【基线更新通知】 版本:v1.1.0-clean-base 更新内容:xxx 同步要求:请在 48 小时内同步最新基线 ``` ### 11.3 新人入职流程 1. 阅读本文档 2. 阅读 `项目开发规范&Git工作流规则.md` Git工作流规范 3. 从 `v1.1.0-clean-base` 标签开始熟悉代码 4. 在 `feature/security-enhance` 分支进行开发 5. 导师带教完成第一个功能 ### 11.4 违规处理 | 违规行为 | 处理方式 | |-----------------|-------------| | 直接修改 clean-base | 回滚 + 警告 | | 提交敏感信息 | 立即删除 + 安全审查 | | 未测试部署云端 | 回滚 + 批评教育 | | 多次违规 | 暂停开发权限 + 培训 | --- ## 十二、规则落地保障 ### 12.1 规则执行检查机制 - **规则合规性检查清单**:每周抽检代码/配置是否符合规范 - **CI/CD 自动校验**: - 提交时检查命名规范 - 代码注释覆盖率检查 - 接口规范校验 - 安全漏洞扫描 - 字符集配置校验 - 依赖注入规范校验 ### 12.2 规则更新流程 1. 提出规则修改申请(描述修改原因和内容) 2. 项目负责人 + 技术负责人双确认 3. 更新文档并增加版本号 4. 同步团队培训 5. 更新 CI/CD 校验规则 ### 12.3 例外场景处理 - **规则豁免流程**:特殊业务场景需临时偏离规范,需书面申请 - 记录豁免场景和原因 - 定期复盘(每月),评估是否需要调整规则 --- ## 十三、版本与更新记录 ### 版本信息 - **版本**:v2.2.0 - **生效日期**:2026-06-16 - **适用范围**:风七六本地生活服务平台所有开发团队 ### 版本兼容性 | 组件 | 版本 | 兼容性说明 | |------------|---------|-----------------------------| | Podman | 5.8.1 | Windows WSL2 | | MariaDB | 10.11 | MySQL 8.0 兼容 | | Nacos | 2.4.3 | Spring Cloud Alibaba 2022.x | | Redis | 7.2.4 | - | | RocketMQ | 5.3.1 | - | | Kong | 3.9.0 | - | | Prometheus | v2.54.1 | - | | Grafana | 11.2.0 | - | ### 更新记录 | 日期 | 版本 | 更新内容 | 作者 | |------------|--------|---------------------------|------| | 2026-04-04 | v1.0.0 | 创建技术栈规则文件 | 技术团队 | | 2026-05-11 | v1.1.0 | 添加命名规范章节 | 技术团队 | | 2026-05-12 | v2.0.0 | 合并技术栈和开发规则,全面完善规范 | 技术团队 | | 2026-05-14 | v2.1.0 | 添加后端开发强制规范(字符集、JDBC、依赖注入) | 技术团队 | | 2026-06-16 | v2.2.0 | 对标大厂标准,新增日期时间、集合、SQL、并发、微服务规范 | 技术团队 | --- ## 附录:命名转换对照表 | 旧命名 | 新命名 | |-----------------|--------------------| | `admin-service` | `platform-service` | | `AdminService` | `PlatformService` | | `admin-web` | `platform_web` | | `admin.conf` | `platform.conf` | | `ADMIN_*` | `PLATFORM_*` | --- ## 十四、环境变量管理规范(大厂标准) ### 14.1 核心原则 #### 禁止硬编码原则 - **❌ 禁止**在代码或配置文件中硬编码任何敏感信息(密码、密钥、地址等) - **❌ 禁止**硬编码 IP 地址,必须使用容器别名或 DNS 解析 - **✅ 必须**使用环境变量传递所有配置参数 #### 环境变量命名规范 | 规则 | 说明 | 示例 | |-------|----------------|-----------------------------------| | 全大写 | 所有环境变量必须使用大写字母 | `SPRING_DATASOURCE_URL` | | 下划线分隔 | 单词之间使用下划线分隔 | `REDIS_HOST` | | 前缀区分 | 不同组件使用统一前缀 | `MARIADB_*`, `REDIS_*`, `NACOS_*` | | 语义清晰 | 变量名必须清晰表达含义 | `JWT_SECRET_KEY` | ### 14.2 环境变量分类 #### 基础配置变量 ```bash # 环境标识 ENV=dev ENVIRONMENT_NAME=开发环境 # 时区配置(全局统一) TZ=Asia/Shanghai ``` #### 数据库配置变量 ```bash # MariaDB 配置 MARIADB_HOST=mariadb MARIADB_PORT=3306 MARIADB_DATABASE=fzx_local_life MARIADB_USER=fzx_app MARIADB_PASSWORD=your_secure_password # 连接池配置 DB_POOL_MAX_SIZE=20 DB_POOL_MIN_IDLE=5 DB_CONNECTION_TIMEOUT=30000 ``` #### 缓存配置变量 ```bash # Redis 配置 REDIS_HOST=redis REDIS_PORT=6379 REDIS_PASSWORD=your_redis_password REDIS_DATABASE=0 # 连接池配置 REDIS_POOL_MAX_ACTIVE=8 REDIS_POOL_MAX_IDLE=8 REDIS_TIMEOUT=30000 ``` #### 服务注册配置变量 ```bash # Nacos 配置 NACOS_SERVER_ADDR=nacos:8848 NACOS_NAMESPACE=public NACOS_USERNAME=nacos NACOS_PASSWORD=nacos NACOS_DISCOVERY_ENABLED=true NACOS_CONFIG_ENABLED=true ``` #### 安全配置变量 ```bash # JWT 配置(生产环境必须 >= 32 字符) JWT_SECRET_KEY=your_very_secure_jwt_secret_key_at_least_32_chars JWT_EXPIRE_TIME=86400000 JWT_ISSUER=fengqiliu # 加密密钥 ENCRYPTION_MASTER_KEY=your_secure_encryption_key_32_chars ``` #### 第三方服务配置变量 ```bash # 钉钉告警 DINGTALK_WEBHOOK_URL=https://oapi.dingtalk.com/robot/send?access_token=xxx DINGTALK_SECRET=your_dingtalk_secret # 短信服务 SMS_ACCESS_KEY_ID=your_sms_access_key SMS_ACCESS_KEY_SECRET=your_sms_secret # 云存储 OSS OSS_ACCESS_KEY_ID=your_oss_key OSS_ACCESS_KEY_SECRET=your_oss_secret OSS_BUCKET_NAME=your_bucket OSS_ENDPOINT=oss-cn-beijing.aliyuncs.com # 地图服务 MAP_API_KEY=your_map_api_key ``` ### 14.3 容器网络别名规范 #### 容器别名命名规则 - **基础设施服务**:使用简单名称作为别名 - MariaDB: `mariadb` - Redis: `redis` - Nacos: `nacos` - **业务微服务**:使用 `-service` 后缀作为别名 - 用户服务: `user-service` - 认证服务: `auth-service` - 订单服务: `order-service` #### docker-compose 配置示例 ```yaml services: user-service: container_name: fzx-local-user-service networks: fzx-backend-network: aliases: - user-service # 容器别名,供其他服务访问 ``` ### 14.4 环境变量配置文件管理 #### 配置文件结构 ``` env/ ├── .env.example # 示例配置(提交到版本库) ├── .env.local # 本地开发环境(不提交) ├── .env.dev # 开发环境 ├── .env.test # 测试环境 ├── .env.staging # 预发布环境 └── .env.prod # 生产环境(不提交,仅在服务器上配置) ``` #### .gitignore 配置 ``` # 环境变量文件(敏感信息) .env .env.local .env.prod .env.production # 容器配置 docker-compose.override.yml ``` ### 14.5 多环境配置策略 #### 环境隔离原则 | 环境 | 数据库 | Redis | 端口范围 | 用途 | |-------|------------------|-------|-----------|--------| | 本地开发 | fzx_local_life | 本地容器 | 8080-8099 | 日常开发调试 | | 开发环境 | fzx_aliyun_life | 共享容器 | 8080-8099 | 联调测试 | | 测试环境 | fzx_test_life | 独立容器 | 8180-8199 | 自动化测试 | | 预发布环境 | fzx_staging_life | 独立容器 | 8280-8299 | 灰度验证 | | 生产环境 | fzx_prod_life | 独立集群 | 80/443 | 正式服务 | #### 配置优先级(Spring Boot) 1. 命令行参数(最高优先级) 2. 环境变量 3. Nacos 配置中心 4. application-{profile}.yml 5. application.yml(最低优先级) ### 14.6 容器资源配置规范 #### 单环境运行模式(4核8GB服务器) ```bash # 资源限制配置 RESOURCE_DB_CPU_LIMIT=1.5 RESOURCE_DB_MEMORY_LIMIT=2G RESOURCE_REDIS_CPU_LIMIT=0.5 RESOURCE_REDIS_MEMORY_LIMIT=512M RESOURCE_NACOS_CPU_LIMIT=1.0 RESOURCE_NACOS_MEMORY_LIMIT=1.5G RESOURCE_GATEWAY_CPU_LIMIT=0.75 RESOURCE_GATEWAY_MEMORY_LIMIT=768M RESOURCE_SERVICE_CPU_LIMIT=0.5 RESOURCE_SERVICE_MEMORY_LIMIT=512M ``` #### docker-compose 资源配置示例 ```yaml deploy: resources: limits: memory: "512M" cpus: "0.5" reservations: memory: "256M" cpus: "0.25" ``` ### 14.7 安全最佳实践 #### 敏感信息保护 - **禁止**将敏感配置提交到版本控制 - **必须**使用密钥管理服务(如阿里云 KMS)管理生产环境密钥 - **必须**定期轮换敏感密钥(每季度至少一次) #### 密码复杂度要求 | 类型 | 最小长度 | 复杂度要求 | |--------|------|-------------------| | 数据库密码 | 16 | 大小写字母 + 数字 + 特殊字符 | | JWT 密钥 | 32 | 随机字符串 | | 加密密钥 | 32 | AES-256 标准 | #### 配置验证 - CI/CD 流水线必须验证配置文件格式 - 部署前必须检查所有必需环境变量是否存在 - 敏感配置变更必须经过审批流程 --- ## 十五、服务器访问信息 ### 15.1 阿里云ECS服务器 | 属性 | 值 | |-------------|-------------------------------------| | **IP地址** | 8.140.221.49 | | **SSH密钥文件** | `C:\Users\FZX\.ssh\FzxBdsh-ECS.pem` | | **SSH端口** | 22 | | **登录用户** | root | | **免密码登录** | 已配置 | #### 登录命令 ```bash # Windows PowerShell ssh -i "C:\Users\FZX\.ssh\FzxBdsh-ECS.pem" root@8.140.221.49 # Linux/Mac ssh -i ~/.ssh/FzxBdsh-ECS.pem root@8.140.221.49 ``` #### 服务访问地址 | 服务 | 地址 | 端口 | |-----------|-----------------------------------------|------| | Nexus | http://8.140.221.49:8091 | 8091 | | SonarQube | http://sonar-dev.fengzhongxing.com:9000 | 9000 | | Jenkins | http://8.140.221.49:8080 | 8080 | --- **文档管理** - 本文档为风七六本地生活服务平台唯一官方开发规范 - 所有开发人员必须遵守本文档中的规则 - 规则如有更新,将通过团队会议和文档版本更新同步 - 本文档包含强制性规范,违反将导致服务启动失败或安全漏洞