麦瓣健康后端技术架构文档
项目名称: ⻨瓣健康 - 后端微服务架构
技术栈: Spring Boot 3.2 + Spring Cloud 2023 & Alibaba
文档版本: v3.2(章节编号修复版)
最后更新: 2025-11-07
原文档引用: 本文档从 麦瓣健康-APP产品开发方案.md 中的后端技术架构部分独立而来,包含完整的技术选型、架构设计、微服务实现指南等详细内容。
⚠️ 架构风险提示: 本文档基于架构复盘分析进行了优化,重点关注:分布式事务优化、缓存策略完善、降级容灾方案、MVP最小化实施。建议开发前仔细阅读"第二十一章:架构风险与优化建议"。
一、技术架构概览
1.1 架构设计
本项目后端架构采用微服务架构设计模式,结合康护到家业务特点进行定制化开发。
1.2 核心技术栈
微服务框架
- 语言: Java 17
- 框架: Spring Boot 3.2 + Spring Cloud 2023 & Alibaba
- API网关: Spring Cloud Gateway (含限流、熔断、灰度发布)
- 服务注册与发现: Nacos 2.x
- 配置中心: Nacos Config
- 认证授权: Sa-Token (轻量级,替代Spring Security OAuth2)
- API文档: Knife4j (Swagger增强版)
- 服务监控: Spring Boot Admin + Prometheus + Grafana
- 链路追踪: SkyWalking (生产环境必选)
- 限流熔断: Sentinel (流量防护)
数据存储
- 关系数据库: MySQL 8.0 (主从架构,读写分离)
- 数据库连接池: HikariCP (Spring Boot 3默认)
- ORM框架: MyBatis
- 重要约束:必须使用 XML Mapper 配置,禁用 @Select/@Insert/@Update/@Delete 注解
- MyBatis Generator 配置
targetRuntime="MyBatis3"生成 XML 配置 - 所有 SQL 语句统一在 XML 文件中编写,便于维护和审查
- 复杂查询使用动态 SQL(
<if>,<choose>,<foreach>等标签)
- 分页插件: PageHelper
- 缓存: Redis 7.x (⚠️ 生产环境必须集群部署:主从+哨兵或Cluster模式)
- 用途:缓存、分布式锁、GEO位置、消息队列
- 搜索引擎: Elasticsearch 7.17.3 (技师搜索、商品搜索、日志分析)
- NoSQL: MongoDB 5.0 (护理日志、聊天记录)
- 对象存储: 阿里云OSS / MinIO (私有云)
消息与通信
- 消息队列: RabbitMQ 3.10+
- WebSocket: Spring WebSocket
- 短信服务: 阿里云短信
- 邮件服务: Spring Mail
分布式解决方案
- 分布式事务: 本地消息表 + MQ(✅ 推荐方案,详见分布式事务一致性设计方案)
- 推荐场景:订单支付、积分发放、通知推送等大部分场景(80%+)
- 备选方案:Seata AT模式(⚠️ 仅用于资金账户操作:扣款、退款)
- 性能对比:本地消息表(80ms,800 TPS)vs Seata AT(500ms,100 TPS)
- 分布式锁: Redis (护理师抢单、秒杀库存扣减)
- 任务调度: XXL-Job(分布式任务调度,支持故障转移)
DevOps工具
- 容器化: Docker
- 容器编排: Kubernetes (生产环境)
- 容器管理: Portainer
- CI/CD: Jenkins
- 日志收集: ELK (Elasticsearch + Logstash + Kibana)
第三方集成
- 地图服务: 高德地图API (导航、距离计算、位置追踪)
- 支付接口: 微信支付 + 支付宝 (含分账、企业付款)
- 实名认证: 阿里云实人认证
- 人脸识别: 腾讯云/阿里云
- 物流查询: 快递100 / 菜鸟物流API
- AI能力: 通义千问 / OpenAI (体检报告分析、智能推荐)
- 敏感词过滤: 阿里云内容安全 / 腾讯云天御
开发工具
- 代码简化: Lombok
- 代码生成: MyBatisGenerator (MBG)
1.3 基础设施服务端口总览
本项目使用Docker Compose部署基础设施服务,以下为各服务的端口配置:
| 服务名称 | 容器名称 | 版本 | 端口映射 | 说明 | 默认账号 |
|---|---|---|---|---|---|
| MySQL | maiban-mysql | 8.0 | 3306:3306 | 关系数据库 | root / Maiban@2025#Mysql! |
| Redis | maiban-redis | 7-alpine | 6379:6379 | 缓存/分布式锁 | 无密码 |
| Nacos | maiban-nacos | 2.2.3 | 8848:88489848:9848 | 服务注册/配置中心 gRPC通信端口 | nacos / nacos |
| RabbitMQ | maiban-rabbitmq | 3.12 | 5672:567215672:15672 | 消息队列 管理界面 | admin / admin123 |
| Elasticsearch | maiban-es | 7.17.3 | 9200:92009300:9300 | 搜索引擎 节点通信端口 | 无认证 |
| MongoDB | maiban-mongo | 5.0 | 27017:27017 | NoSQL数据库 | admin / admin123 |
| MinIO | maiban-minio | latest | 9000:90009001:9001 | 对象存储API 管理控制台 | minioadmin / minioadmin123 |
| Netdata | maiban-netdata | stable | 19999:19999 | 系统监控 | 无认证 |
基础设施管理界面访问地址:
| 服务 | 访问地址 | 账号密码 | 用途 |
|---|---|---|---|
| Nacos控制台 | http://localhost:8848/nacos | nacos / nacos | 服务注册与配置管理 |
| RabbitMQ管理界面 | http://localhost:15672 | admin / admin123 | 消息队列监控 |
| MinIO控制台 | http://localhost:9001 | minioadmin / minioadmin123 | 对象存储管理 |
| Netdata监控 | http://localhost:19999 | 无需认证 | 系统性能监控 |
| Elasticsearch | http://localhost:9200 | 无需认证 | 搜索引擎API |
1.4 服务文档与管理界面访问地址
📚 API文档访问地址(Knife4j/Swagger):
✅ = 已验证可访问 | ⚠️ = 需要配置 | 测试时间:2025-10-24
| 服务名称 | 文档访问地址 | OpenAPI地址 | 状态 | 说明 |
|---|---|---|---|---|
| 网关聚合文档(推荐) | http://localhost:8201/doc.html | http://localhost:8201/v3/api-docs | ✅ | 所有微服务文档聚合 |
| 认证服务 | http://localhost:8401/doc.html | http://localhost:8401/v3/api-docs | ✅ | 登录注册、Token管理 |
| 用户服务 | http://localhost:8080/doc.html | http://localhost:8080/v3/api-docs | ✅ | 用户信息、家庭成员 |
| 技师服务 | http://localhost:8082/doc.html | http://localhost:8082/v3/api-docs | ✅ | 技师列表、接单管理 |
| 订单服务 | http://localhost:8083/doc.html | http://localhost:8083/v3/api-docs | ✅ | 订单创建、状态查询 |
| 支付服务 | http://localhost:8084/doc.html | http://localhost:8084/v3/api-docs | ✅ | 支付、退款、提现 |
| IM消息服务 | http://localhost:8085/doc.html | http://localhost:8085/v3/api-docs | ✅ | 即时通讯、推送 |
| 健康管理服务 | http://localhost:8087/doc.html | http://localhost:8087/v3/api-docs | ✅ | 健康档案、护理日志 |
| 搜索服务 | http://localhost:8089/doc.html | http://localhost:8089/v3/api-docs | ✅ | 技师搜索、商品搜索 |
| 营销服务 | http://localhost:8090/doc.html | http://localhost:8090/v3/api-docs | ✅ | 优惠券、积分、会员 |
| 商城服务 | http://localhost:8091/doc.html | http://localhost:8091/v3/api-docs | ✅ | 商品、购物车、订单 |
| 后台管理服务 | http://localhost:8180/doc.html | http://localhost:8180/v3/api-docs | ⚠️ | 需检查Knife4j配置 |
🔍 监控中心访问地址:
✅ = 已验证可访问 | 测试时间:2025-10-24
| 监控服务 | 访问地址 | 账号密码 | 状态 | 说明 |
|---|---|---|---|---|
| Spring Boot Admin | http://localhost:8101 | 无需认证(开发环境) | ✅ | 微服务统一监控面板 |
| Nacos控制台 | http://localhost:8848/nacos | nacos / nacos | ✅ | 服务注册与配置管理 |
| RabbitMQ管理界面 | http://localhost:15672 | admin / admin123 | ✅ | 消息队列监控管理 |
| MinIO控制台 | http://localhost:9001 | minioadmin / minioadmin123 | ✅ | 对象存储管理 |
| Netdata监控 | http://localhost:19999 | 无需认证 | ✅ | 系统性能实时监控 |
| Elasticsearch | http://localhost:9200 | 无需认证 | ✅ | 搜索引擎API |
🏥 健康检查地址(Spring Boot Actuator):
| 服务 | 健康检查地址 | 指标监控地址 |
|---|---|---|
| API网关 | http://localhost:8201/actuator/health | http://localhost:8201/actuator/metrics |
| 监控中心 | http://localhost:8101/actuator/health | http://localhost:8101/actuator/metrics |
| 认证服务 | http://localhost:8401/actuator/health | http://localhost:8401/actuator/metrics |
| 用户服务 | http://localhost:8080/actuator/health | http://localhost:8080/actuator/metrics |
| 技师服务 | http://localhost:8082/actuator/health | http://localhost:8082/actuator/metrics |
| 订单服务 | http://localhost:8083/actuator/health | http://localhost:8083/actuator/metrics |
| 支付服务 | http://localhost:8084/actuator/health | http://localhost:8084/actuator/metrics |
| IM消息服务 | http://localhost:8085/actuator/health | http://localhost:8085/actuator/metrics |
| 健康管理服务 | http://localhost:8087/actuator/health | http://localhost:8087/actuator/metrics |
| 搜索服务 | http://localhost:8089/actuator/health | http://localhost:8089/actuator/metrics |
| 营销服务 | http://localhost:8090/actuator/health | http://localhost:8090/actuator/metrics |
| 商城服务 | http://localhost:8091/actuator/health | http://localhost:8091/actuator/metrics |
| 后台管理服务 | http://localhost:8180/actuator/health | http://localhost:8180/actuator/metrics |
📝 Nacos详细功能入口:
| 功能模块 | 访问地址 | 说明 |
|---|---|---|
| 服务列表 | http://localhost:8848/nacos/#/serviceManagement | 查看所有注册的微服务 |
| 配置管理 | http://localhost:8848/nacos/#/configurationManagement | 管理配置文件 |
| 命名空间 | http://localhost:8848/nacos/#/namespace | 环境隔离管理 |
| 集群管理 | http://localhost:8848/nacos/#/clusterManagement | 查看集群节点状态 |
📊 RabbitMQ详细功能入口:
| 功能模块 | 访问地址 | 说明 |
|---|---|---|
| 队列监控 | http://localhost:15672/#/queues | 查看所有队列状态 |
| 交换机管理 | http://localhost:15672/#/exchanges | 管理交换机 |
| 连接监控 | http://localhost:15672/#/connections | 查看客户端连接 |
| 通道监控 | http://localhost:15672/#/channels | 查看通道状态 |
⚠️ 使用建议:
- 开发调试:优先使用网关聚合文档(http://localhost:8201/doc.html),可以在一个页面查看所有微服务API
- 服务监控:使用Spring Boot Admin(http://localhost:8101)统一监控所有微服务状态
- 配置管理:通过Nacos控制台(http://localhost:8848/nacos)统一管理所有配置
- 系统监控:使用Netdata(http://localhost:19999)实时监控系统资源使用情况
⚠️ 安全提示:
- 生产环境务必修改所有默认密码
- 生产环境应关闭或限制Actuator端点访问
- 建议通过VPN或内网访问管理界面
- API文档在生产环境应设置访问权限或关闭
二、微服务架构设计
2.1 服务拆分原则与边界
拆分原则:
- 业务领域拆分:按DDD领域模型拆分(用户域、订单域、支付域等)
- 数据独立性:每个服务拥有独立数据库,避免跨库事务
- 变化频率隔离:高频变化功能独立服务(营销活动、运营配置)
- 性能隔离:高并发场景独立部署(IM消息、秒杀活动)
边界划分示例:
- 护理日志:元数据(订单ID、技师ID)→ 订单服务;详细内容(体征、照片)→ 健康管理服务
- 优惠券:券模板、库存 → 营销服务;订单使用记录 → 订单服务
- 技师位置:实时位置(Redis GEO)→ 订单服务;历史轨迹 → 健康管理服务
2.2 微服务模块详解
麦瓣健康平台共包含以下模块:
核心基础模块
| 模块 | 职责 | 端口 | 关键功能 |
|---|---|---|---|
| maiban-common | 公共模块 | - | 通用工具类、统一返回封装CommonResult、分页封装CommonPage、自定义注解 |
| maiban-auth | 认证授权 | 8401 | Sa-Token集成、JWT Token生成验证、手机号验证码登录、微信授权 |
| maiban-gateway | API网关 | 8201 | Spring Cloud Gateway、统一路由、限流鉴权、CORS配置、Knife4j文档聚合 |
| maiban-monitor | 服务监控 | 8101 | Spring Boot Admin Server、健康状态监控、JVM监控、日志查看 |
业务微服务模块(10个服务,支撑225个功能点)
| 模块名 | 服务名称 | 端口 | 核心职责 | 关键功能模块 | 关键技术 |
|---|---|---|---|---|---|
| maiban-user | 用户服务 | 8080 | 用户体系管理 | • 注册登录(手机号/微信/实名认证) • 家庭成员管理 • 地址管理 • 个人信息、收藏、浏览历史 • 老带新/邀请好友 | MyBatis、Redis缓存、阿里云实名认证 |
| maiban-nurse | 技师服务 | 8082 | 技师体系管理 | • 技师注册、资质审核 • 在线状态、接单管理 • 技师列表/详情/筛选/搜索 • AI智能推荐算法 • 评分/等级体系 • 师徒关系管理 | Redis分布式锁、Elasticsearch搜索、AI推荐引擎 |
| maiban-order | 订单服务 | 8083 | 订单全流程管理 | • 订单创建、支付、状态流转 • 预约管理(立即/未来/长期) • 实时位置追踪 • 服务延时、取消、退款 • 打卡记录、里程计算 • 套餐卡核销 | 状态机、RabbitMQ延时队列、Redis位置缓存、高德地图API |
| maiban-payment | 支付财务服务 | 8084 | 支付结算体系 | • 微信/支付宝/余额支付 • 回调处理、退款流水 • 佣金计算、分账、提现 • 里程补贴、奖励发放 • 账单汇总、电子发票 | 第三方支付SDK、Seata分布式事务、定时任务 |
| maiban-health-service | 健康管理服务 | 8087 | 健康数据管理 | • 健康档案(病史/用药/过敏) • 护理日志、体征数据 • 体检报告上传/AI分析 • 健康计划、数据对比 • 物联网设备集成、数据同步 • 健康报告生成(PDF) | AES加密、MongoDB存储、阿里云OSS、AI分析引擎 |
| maiban-marketing | 营销服务 | 8090 | 营销运营体系 | • 优惠券(领取/使用/分享/叠加) • 积分系统、会员体系、成长值 • 红包系统(现金/随机/口令/红包雨) • 签到打卡、任务中心 • 运营活动(秒杀/拼团/满减) • 新手引导、新人礼包 | Redis计数、定时任务、规则引擎 |
| maiban-im | IM消息服务 | 8085 | 通讯推送体系 | • 即时通讯IM(文字/图片/语音/位置) • 敏感词过滤、客服介入 • 极光推送/模板消息 • 通知中心(订单/系统/活动/健康) • WebSocket实时通信 | Spring WebSocket、RabbitMQ、极光推送、敏感词库 |
| maiban-mall | 商城服务 | 8091 | 电商业务体系 | • 商品管理、分类 • 购物车、商城订单 • 库存管理、物流跟踪 • 退货退款 • 商品评价 • 护理套餐管理 | Redis库存、物流API |
| maiban-search | 搜索服务 | 8089 | 搜索引擎体系 | • 技师搜索 • 商品搜索 • 搜索建议 • 热门搜索 • 搜索结果排序 | Elasticsearch搜索引擎 |
| maiban-admin | 运营管理服务 | 8180 | 后台管理体系 | • 用户/技师审核 • 订单管理、财务统计 • 内容审核(社区/评价) • 数据报表、业绩分析 • RBAC权限管理 • 客服系统、投诉处理 | RBAC权限、ECharts报表、Elasticsearch日志分析 |
三、服务边界与依赖约束
3.1 微服务依赖管理原则
核心原则:业务微服务间零直接依赖
为了保证微服务架构的独立性和可维护性,必须严格控制微服务间的依赖关系,避免出现复杂的网状依赖和循环依赖。
3.2 依赖隔离约束
禁止事项:
- ❌ 业务微服务 A 直接依赖业务微服务 B 的 jar 包
- ❌ 业务微服务 A 直接引用业务微服务 B 的 Repository、Service、Entity 等类
- ❌ 通过依赖传递绕过依赖限制(如 A 依赖 common,B 依赖 common,A 间接依赖 B)
允许操作:
- ✅ 通过 HTTP/gRPC API 调用对方服务接口
- ✅ 通过消息队列(RabbitMQ)进行异步通信
- ✅ 通过事件总线进行事件发布与订阅
- ✅ 依赖
maiban-common等公共基础库 - ✅ 依赖数据库、缓存、MQ 等基础设施组件
3.3 公共能力沉淀策略
公共模块层级划分:
maiban-common(基础公共模块)
├── 通用工具类(日期、字符串、加密等)
├── 统一返回封装(CommonResult、CommonPage)
├── 自定义注解(@Log、@DataScope等)
├── 通用异常类(BusinessException、SystemException)
├── 通用 DTO(分页请求、基础响应等)
└── 公共常量(状态枚举、错误码等)
各业务微服务
├── maiban-auth(认证授权服务)
├── maiban-user(用户服务)
├── maiban-nurse(技师服务)
├── maiban-order(订单服务)
├── maiban-payment(支付服务)
├── maiban-health-service(健康管理服务)
├── maiban-marketing(营销服务)
├── maiban-im(IM消息服务)
├── maiban-mall(商城服务)
├── maiban-search(搜索服务)
└── maiban-admin(运营管理服务)
依赖方向:
业务微服务 → maiban-common(单向依赖)
业务微服务 ↔ 业务微服务(禁止直接依赖)
3.4 服务间通信方式
同步调用(HTTP/gRPC):
| 场景 | 通信方式 | 说明 | 示例 |
|---|---|---|---|
| 查询类接口 | HTTP RESTful | 实时查询对方服务数据 | 订单服务调用用户服务查询用户信息 |
| 事务性操作 | HTTP RESTful + 幂等性 | 需要保证操作原子性 | 支付服务调用订单服务更新订单状态 |
| 强一致性要求 | gRPC | 高性能、低延迟 | 网关转发高并发请求 |
| 批量查询 | HTTP + 批量接口 | 减少网络开销 | 营销服务批量查询用户积分 |
异步调用(消息队列):
| 场景 | 消息队列 | 说明 | 示例 |
|---|---|---|---|
| 跨服务业务事件 | RabbitMQ | 解耦服务间同步调用 | 订单完成 → 营销服务发放积分 |
| 延时任务 | RabbitMQ + 死信队列 | 处理超时取消场景 | 订单支付超时自动取消 |
| 通知推送 | RabbitMQ | 异步通知,不阻塞主流程 | 订单状态变更 → IM服务推送通知 |
| 数据同步 | RabbitMQ | 最终一致性数据同步 | 用户信息变更 → 各服务缓存更新 |
事件驱动架构:
// 订单服务发布订单完成事件
@Component
public class OrderEventPublisher {
@Autowired
private RabbitTemplate rabbitTemplate;
public void publishOrderCompleted(Order order) {
OrderCompletedEvent event = new OrderCompletedEvent(order);
rabbitTemplate.convertAndSend("order.exchange", "order.completed", event);
}
}
// 营销服务订阅订单完成事件
@Component
public class MarketingEventConsumer {
@RabbitListener(queues = "order.completed.queue")
public void handleOrderCompleted(OrderCompletedEvent event) {
// 发放积分
marketingService.creditPoints(event.getUserId(), event.getOrderAmount());
}
}
3.5 依赖检测与验证机制
本地开发阶段:
1. Maven 依赖树检查
# 在每个微服务目录下执行
mvn dependency:tree > dependency-tree.log
# 检查是否存在业务微服务依赖
grep -E "maiban-(user|nurse|order|payment|health|marketing|im|mall|search|admin)" dependency-tree.log
2. IDE 插件检查
- 安装 Maven Helper 插件
- 实时检查依赖冲突和循环依赖
- 可视化依赖关系图
3. ArchUnit 架构测试
@ArchTest
static final ArchRule service_should_not_depend_on_other_services = noClasses()
.that()
.resideInAPackage("com.maiban.health.user..")
.should()
.dependOnClassesThat()
.resideInAPackage("com.maiban.health.nurse..")
.orShould()
.dependOnClassesThat()
.resideInAPackage("com.maiban.health.order..")
.check();
CI/CD 流水线检查:
1. 依赖白名单校验
# .github/workflows/dependency-check.yml
name: Dependency Check
on: [pull_request]
jobs:
dependency-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Check business service dependencies
run: |
# 提取项目依赖
mvn dependency:tree -DoutputFile=dependencies.txt
# 校验是否存在跨业务服务依赖
if grep -E "com\.maiban\.health\.(user|nurse|order|payment|health|marketing|im|mall|search|admin):" dependencies.txt; then
echo "❌ 检测到跨业务服务依赖!"
exit 1
fi
2. 构建产物扫描
# 扫描 jar 包内容,确保不包含其他服务的类
jar -tf target/maiban-user-*.jar | grep -E "com\.maiban\.health\.(nurse|order|payment)" && {
echo "❌ jar 包中包含其他服务代码!"
exit 1
}
3. 静态代码分析
<!-- pom.xml 配置 -->
<plugin>
<groupId>com.github.ferstl</groupId>
<artifactId>depgraph-maven-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<graphFormat>text</graphFormat>
</configuration>
</plugin>
# 生成依赖关系图,审查是否存在异常依赖
mvn depgraph:graph
3.6 依赖约束违规处理
检测到违规依赖的处理流程:
开发阶段
- 代码 Review 阶段拒绝合并代码
- IDE 提示警告和错误
- 本地构建失败
CI/CD 阶段
- 构建流水线中断
- 生成详细依赖报告
- 通知相关开发人员
生产环境
- 拒绝部署违规服务
- 要求立即整改
- 回滚到上一个合规版本
常见违规场景与解决方案:
| 违规场景 | 错误示例 | 正确方案 |
|---|---|---|
| 直接依赖对方 Service | userService.getUserInfo() | 通过 Feign Client 或 REST API 调用 |
| 共享数据库表 | 同时访问 user 表 | 各服务独立数据库,通过 API 同步数据 |
| 循环依赖 | A 依赖 B,B 依赖 A | 通过消息事件解耦,移除直接依赖 |
| 工具类复制 | 各服务复制相同工具类 | 抽离到 maiban-common 基础库 |
3.7 最佳实践建议
1. 接口设计规范
// ✅ 推荐:清晰的接口定义
@FeignClient(name = "maiban-user")
public interface UserServiceClient {
@GetMapping("/api/v1/user/{userId}")
CommonResult<UserInfoDTO> getUserInfo(@PathVariable Long userId);
}
// ❌ 禁止:直接依赖 Service 类
@Autowired
private UserService userService; // 禁止!
2. 数据一致性处理
// ✅ 推荐:最终一致性
@RabbitListener(queues = "user.updated.queue")
public void handleUserUpdated(UserUpdatedEvent event) {
// 异步更新本地缓存
cacheService.updateUserInfo(event.getUserId(), event.getUserInfo());
}
// ❌ 禁止:同步调用并共享数据库
// userRepository.updateUser(userInfo) // 禁止!
3. 配置管理
# 各服务独立配置文件
maiban-user/src/main/resources/application.yml:
spring:
application:
name: maiban-user # 唯一标识,与 Nacos 服务名一致
# 禁止共享配置类
// ❌ @Configuration + @Bean 跨服务共享
// ✅ 各服务独立配置
四、Nacos配置中心
4.1 部署与配置
Nacos Server 部署:
- 下载Nacos 2.2.3版本,解压后执行
sh startup.sh -m standalone单机启动 - 访问控制台 http://localhost:8848/nacos (默认账号密码: nacos/nacos)
- 生产环境建议集群部署(3个节点以上),使用MySQL存储配置
命名空间设计:
dev: 开发环境test: 测试环境prod: 生产环境
4.2 微服务配置结构
本地配置(application.yml):
- 服务名称:
spring.application.name - Nacos地址:
spring.cloud.nacos.discovery.server-addr - 环境激活:
spring.profiles.active
Nacos配置中心:
- 数据库连接配置
- Redis配置
- 第三方服务密钥(使用环境变量)
配置自动刷新:
- 启用
refresh-enabled: true - 使用
@RefreshScope注解动态刷新Bean
4.3 关键配置项
数据库配置:
- MySQL驱动:
com.mysql.cj.jdbc.Driver - 连接池: HikariCP (Spring Boot 3默认)
- MyBatis映射:
mybatis.mapper-locations
Redis配置:
- 连接配置:
spring.redis.host/port - 密码:
spring.redis.password - 超时设置:
spring.redis.timeout
RabbitMQ配置:
- 主机:
spring.rabbitmq.host - 端口:
spring.rabbitmq.port - 虚拟主机:
spring.rabbitmq.virtual-host
Sa-Token配置:
- Token名称:
sa-token.token-name - 超时时间: 30天 (2592000秒)
- JWT密钥: 使用环境变量
${JWT_SECRET}
日志配置:
- 按包名设置日志级别
- 开发环境:
logging.level.com.health=debug - 生产环境:
logging.level.com.health=info
五、Spring Cloud Gateway
5.1 路由配置策略
自动服务发现:
- 启用
discovery.locator.enabled: true,自动从Nacos发现服务 - 服务ID小写转换:
lower-case-service-id: true
核心路由规则(10个业务服务 + 1个认证服务):
| 前端路径 | 目标服务 | 说明 | 版本 | 优先级 |
|---|---|---|---|---|
/api/v1/auth/** | maiban-auth | 认证授权服务(登录、注册、Token刷新) | v1 | 1 |
/api/v1/user/** | maiban-user | 用户服务(用户信息、家庭成员、地址管理) | v1 | 2 |
/api/v1/nurse/** | maiban-nurse | 技师服务(技师列表、详情、接单管理) | v1 | 3 |
/api/v1/order/** | maiban-order | 订单服务(订单创建、状态流转、预约管理) | v1 | 4 |
/api/v1/payment/** | maiban-payment | 支付财务服务(支付、退款、分账、提现) | v1 | 5 |
/api/v1/health/** | maiban-health-service | 健康管理服务(健康档案、护理日志、体检报告) | v1 | 6 |
/api/v1/marketing/** | maiban-marketing | 营销服务(优惠券、积分、会员、红包) | v1 | 7 |
/api/v1/im/** | maiban-im | IM消息服务(即时通讯、推送通知) | v1 | 8 |
/api/v1/mall/** | maiban-mall | 商城服务(商品、购物车、商城订单) | v1 | 9 |
/api/v1/search/** | maiban-search | 搜索服务(技师搜索、商品搜索) | v1 | 10 |
/api/v1/admin/** | maiban-admin | 运营管理服务(后台管理、数据报表) | v1 | 11 |
路由规则说明:
- 所有路由统一使用
/api/v1/前缀,便于后续版本迭代(v2、v3...) - 路由转发时去掉
/api/v1前缀,保留业务路径 - 优先级按照业务重要性排序,数字越小优先级越高
- 认证服务优先级最高,保证登录注册等核心功能优先匹配
版本管理策略:
- v1: 当前稳定版本,兼容所有客户端
- v2: 未来版本,支持新功能,逐步迁移
- 旧版本保留至少6个月,给客户端充足的升级时间
- 重大变更需要版本升级,小修复可在当前版本热更新
限流配置:
- 使用Redis实现分布式限流
replenishRate: 10(每秒补充10个令牌)burstCapacity: 20(桶容量20个令牌)
5.2 完整Gateway配置示例
application.yml 配置文件 (maiban-gateway/src/main/resources/application.yml):
spring:
application:
name: maiban-gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
# 服务发现配置
discovery:
locator:
enabled: true # 启用服务发现
lower-case-service-id: true # 服务名小写
# 路由规则配置
routes:
# 1. 认证授权服务
- id: maiban-auth
uri: lb://maiban-auth
predicates:
- Path=/api/v1/auth/**
filters:
- StripPrefix=2 # 去掉/api/v1前缀
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 20
redis-rate-limiter.burstCapacity: 40
# 2. 用户服务
- id: maiban-user
uri: lb://maiban-user
predicates:
- Path=/api/v1/user/**
filters:
- StripPrefix=2
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
# 3. 技师服务
- id: maiban-nurse
uri: lb://maiban-nurse
predicates:
- Path=/api/v1/nurse/**
filters:
- StripPrefix=2
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
# 4. 订单服务
- id: maiban-order
uri: lb://maiban-order
predicates:
- Path=/api/v1/order/**
filters:
- StripPrefix=2
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 15
redis-rate-limiter.burstCapacity: 30
# 5. 支付财务服务
- id: maiban-payment
uri: lb://maiban-payment
predicates:
- Path=/api/v1/payment/**
filters:
- StripPrefix=2
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
# 6. 健康管理服务
- id: maiban-health-service
uri: lb://maiban-health-service
predicates:
- Path=/api/v1/health/**
filters:
- StripPrefix=2
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
# 7. 营销服务
- id: maiban-marketing
uri: lb://maiban-marketing
predicates:
- Path=/api/v1/marketing/**
filters:
- StripPrefix=2
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 15
redis-rate-limiter.burstCapacity: 30
# 8. IM消息服务
- id: maiban-im
uri: lb://maiban-im
predicates:
- Path=/api/v1/im/**
filters:
- StripPrefix=2
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 20
redis-rate-limiter.burstCapacity: 40
# 9. 商城服务
- id: maiban-mall
uri: lb://maiban-mall
predicates:
- Path=/api/v1/mall/**
filters:
- StripPrefix=2
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
# 10. 搜索服务
- id: maiban-search
uri: lb://maiban-search
predicates:
- Path=/api/v1/search/**
filters:
- StripPrefix=2
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 15
redis-rate-limiter.burstCapacity: 30
# 11. 运营管理服务
- id: maiban-admin
uri: lb://maiban-admin
predicates:
- Path=/api/v1/admin/**
filters:
- StripPrefix=2
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 5
redis-rate-limiter.burstCapacity: 10
# 全局CORS配置
globalcors:
cors-configurations:
'[/**]':
allowedOriginPatterns: "*" # 生产环境改为具体域名
allowedMethods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
allowedHeaders: "*"
allowCredentials: true
maxAge: 3600
# Redis配置(限流使用)
redis:
host: localhost
port: 6379
password: ${REDIS_PASSWORD:}
timeout: 3000ms
server:
port: 8201
# 日志配置
logging:
level:
org.springframework.cloud.gateway: DEBUG
com.maiban.health.gateway: INFO
路由配置说明:
| 配置项 | 说明 | 示例 |
|---|---|---|
id | 路由唯一标识 | maiban-user |
uri | 目标服务地址(lb=负载均衡) | lb://maiban-user |
predicates | 路由匹配规则 | Path=/api/v1/user/** |
filters | 过滤器(转发前处理) | StripPrefix=2 |
replenishRate | 限流速率(每秒令牌数) | 10 |
burstCapacity | 令牌桶容量 | 20 |
5.3 全局过滤器
跨域CORS配置:
- 允许所有来源 (生产环境需指定具体域名)
- 允许方法: GET、POST、PUT、DELETE、OPTIONS
- 允许携带凭证:
allowCredentials: true
认证鉴权过滤器:
- 从请求头提取Authorization token
- 白名单路径: /login、/register、/captcha (直接放行)
- 非白名单路径: 验证Token有效性,失败返回401
- 过滤器优先级: -100 (最高优先级)
日志过滤器:
- 记录请求路径、方法、IP、耗时
- 异常请求详细日志记录
- 慢请求告警(>2秒)
六、Sa-Token认证授权
6.1 登录认证流程
手机号验证码登录:
- 验证验证码正确性(Redis存储,5分钟有效期)
- 根据手机号查询或创建用户
- 调用
StpUtil.login(userId)完成登录 - 获取Token:
StpUtil.getTokenValue() - 返回用户信息+Token给客户端
微信授权登录:
- 使用微信code换取openid
- 根据openid查询或创建用户(绑定手机号)
- Sa-Token登录生成Token
- 返回用户信息
Token管理:
- Token有效期: 30天
- 刷新机制:
StpUtil.renewTimeout(2592000) - 登出:
StpUtil.logout()清除Token
6.2 权限控制方案
基于角色的权限控制:
@SaCheckRole("admin"): 仅管理员可访问@SaCheckRole({"admin", "operator"}, mode = SaMode.OR): 管理员或运营均可访问- 角色存储在Redis,支持动态更新
自定义权限验证:
- 检查当前登录用户ID:
StpUtil.getLoginIdAsLong() - 业务逻辑验证: 只能查看本人或下属数据
- 抛出
BusinessException进行权限拦截
权限缓存策略:
- 角色权限缓存10分钟
- 权限变更实时刷新缓存
- 登出清除所有权限缓存
七、OpenFeign服务间通信
7.1 Feign Client设计
接口定义约定:
@FeignClient(name = "服务名", fallbackFactory = 降级工厂类)- 服务名必须与Nacos注册的服务名一致
- 接口方法与被调用服务的Controller方法签名一致
核心接口示例:
- 用户服务Client: 查询用户信息、批量查询、扣减余额
- 护理师服务Client: 查询护理师、更新在线状态、评分计算
- 支付服务Client: 创建支付单、查询支付状态、退款
降级策略:
- 实现
FallbackFactory接口 - 服务不可用时返回友好提示: "XXX服务暂时不可用"
- 记录失败日志,便于排查问题
- 避免降级中执行复杂逻辑
6.2 服务调用场景
订单创建场景:
- 调用用户服务查询用户信息(验证用户状态)
- 调用护理师服务查询护理师信息(验证可接单状态)
- 本地创建订单记录
- 调用消息服务发送订单通知
订单支付场景:
- 调用支付服务创建支付流水
- 调用用户服务扣减余额(余额支付)
- 更新订单状态为已支付
- 调用消息服务通知护理师
调用优化:
- 批量接口减少网络开销(批量查询用户、护理师)
- 合理设置超时时间(默认1秒,复杂查询3秒)
- 启用请求压缩减少带宽
- 使用连接池复用连接
八、RabbitMQ异步消息
8.1 延时队列实现订单超时取消
队列设计:
- 延时交换机: order.delay.exchange
- 延时队列: order.delay.queue (设置死信交换机)
- 取消交换机: order.cancel.exchange
- 取消队列: order.cancel.queue
工作流程:
- 创建订单后发送延时消息到延时队列,过期时间15分钟
- 消息过期后自动转发到死信交换机
- 死信交换机路由到取消队列
- 消费者监听取消队列,检查订单状态
- 如果仍是"待支付",自动取消订单
配置要点:
- 延时队列设置:
x-dead-letter-exchange指定死信交换机 - 消息过期时间:
setExpiration("900000")(15分钟) - 消费者幂等性: 检查订单状态防止重复取消
7.2 消息可靠性保证
生产者确认:
- 启用
publisher-confirms: true - 发送失败重试3次
- 记录失败消息到数据库
消费者ACK:
- 手动ACK模式
- 消费成功后确认
- 消费失败重新入队(最多3次)
死信队列:
- 消费失败超过3次进入死信队列
- 人工介入处理异常消息
九、服务依赖关系与核心场景
9.1 服务依赖关系图
用户端/技师端/管理后台
↓
API网关 (maiban-gateway)
↓
┌────────────────────────────────┐
│ 业务微服务层(10个) │
├────────────────────────────────┤
│ 用户服务 ← → 技师服务 │
│ ↓ ↓ │
│ 订单服务 ← → 支付财务服务 │
│ ↓ ↓ │
│ 健康管理 ← → 营销服务 │
│ ↓ ↓ │
│ IM消息 ← → 商城服务 │
│ ↓ │
│ 运营管理服务 │
└────────────────────────────────┘
↓
基础设施层
(Nacos/Redis/MySQL/MongoDB/RabbitMQ/Elasticsearch)
8.2 核心业务场景调用链
场景1: 用户下单预约护理服务
1. 用户服务: 验证用户身份和实名认证状态
2. 技师服务: 查询可用技师列表(支持AI推荐)
3. 订单服务: 创建订单、计算价格(含优惠)
4. 营销服务: 计算优惠券/积分/会员折扣
5. 支付财务服务: 创建支付单、调用微信/支付宝
6. 订单服务: 更新订单状态为"已支付"
7. IM消息服务: 推送订单通知给技师
8. 技师服务: 技师接单、更新状态
9. IM消息服务: 推送接单成功通知给用户
场景2: 技师完成服务提交护理日志
1. 订单服务: 验证订单状态、打卡记录
2. 健康管理服务: 保存护理日志、体征数据
3. 对象存储(OSS): 上传护理照片
4. 订单服务: 更新订单状态为"已完成"
5. 支付财务服务: 触发分账、佣金计算
6. 技师服务: 更新技师完单数、评分
7. 营销服务: 发放完单奖励、积分
8. IM消息服务: 推送服务完成通知给用户
场景3: 用户购买会员享受权益
1. 用户服务: 验证用户身份
2. 营销服务: 创建会员订单(99元/年)
3. 支付财务服务: 完成支付
4. 营销服务: 开通会员权益、发放专属优惠券
5. 健康管理服务: 激活AI体测权益(每月1次)
6. 商城服务: 更新商品显示价格(会员折扣)
7. IM消息服务: 推送会员开通成功通知
场景4: 技师通过老带新邀请徒弟
1. 技师服务: 生成专属邀请码
2. 用户服务: 新技师注册(通过邀请码)
3. 技师服务: 建立师徒关系
4. 营销服务: 发放邀请奖励(师傅50元、徒弟阶段性奖励)
5. 支付财务服务: 奖励金入账
6. IM消息服务: 推送奖励到账通知
7. (后续)订单服务: 徒弟完单触发师傅提成(2%)
8. 支付财务服务: 提成计算、每日结算
场景5: 运营创建限时秒杀活动
1. 运营管理服务: 创建秒杀活动
2. 商城服务: 配置秒杀商品、库存
3. Redis: 预热商品库存到缓存
4. IM消息服务: 推送活动通知
5. (用户抢购)商城服务: Redis扣减库存
6. 订单服务: 创建秒杀订单
7. 支付财务服务: 完成支付
8. 商城服务: 异步扣减数据库库存
8.3 服务拆分原则
| 原则 | 说明 | 应用示例 |
|---|---|---|
| 业务领域 | 按DDD领域拆分 | 用户域、技师域、订单域独立 |
| 数据一致性 | 强一致性数据放同一服务 | 订单状态+支付状态在订单服务 |
| 变化频率 | 高频变化功能独立服务 | 营销活动独立,避免影响核心服务 |
| 团队组织 | 按团队边界拆分 | 前端团队→用户服务,运营团队→营销服务 |
| 性能隔离 | 高并发场景独立部署 | IM消息服务独立,避免消息风暴影响订单 |
8.4 服务通信方式
| 场景 | 通信方式 | 说明 |
|---|---|---|
| 同步查询 | OpenFeign | 查询用户信息、技师详情 |
| 异步通知 | RabbitMQ | 订单状态变更、支付回调 |
| 实时推送 | WebSocket | 订单实时更新、IM消息 |
| 定时任务 | XXL-Job | 订单超时取消、每日结算 |
| 事件驱动 | RabbitMQ | 订单完成→触发分账+奖励+通知 |
十、数据一致性方案
📘 完整设计方案: 麦瓣健康-微服务分布式事务一致性设计方案
本章节为概要说明,详细的生产级实现方案(含完整代码、SQL、监控配置)请参考上述文档。
9.1 分布式事务使用原则
⚠️ 重要原则:优先使用最终一致性,避免过度使用分布式事务
性能对比:
| 方案 | 响应时间 | 吞吐量 | 一致性 | 推荐场景 |
|---|---|---|---|---|
| 本地事务 | 50ms | 1000 TPS | 强一致 | 单服务操作 |
| 本地消息表 | 80ms | 800 TPS | 最终一致 | ✅ 大部分场景(80%+) |
| Saga模式 | 100ms | 500 TPS | 最终一致 | ✅ 需要补偿的流程 |
| Seata AT | 500ms | 100 TPS | 强一致 | ⚠️ 仅资金操作(<5%) |
9.2 推荐方案:本地消息表 + MQ
📘 详细设计文档: 麦瓣健康-微服务分布式事务一致性设计方案
该文档包含完整的生产级实现方案,包括:
- 系统架构设计:微服务全景架构、分布式事务流程、数据流与状态机
- 数据库设计:本地消息表、持久幂等表、死信队列表(含完整SQL)
- 生产级代码实现:RabbitMQ配置(Publisher Confirms)、并发扫描(SKIP LOCKED)、手动ACK消费
- 幂等性保证:持久去重表、业务唯一索引、外部调用幂等键、状态机、Redis短期锁
- 失败重试策略:发布端重试(抖动算法)、消费端重试(延迟队列+DLX)、DLQ处理
- 监控告警与运维:核心指标(Prometheus)、告警规则、运维Runbook、链路追踪、Grafana面板
适用场景:订单支付、积分发放、通知推送等大部分场景
实现流程:
1. 本地事务:更新订单状态 + 插入消息表(事务表)
2. 定时任务:扫描消息表,发送MQ消息(Publisher Confirms保证可靠)
3. 消费者:幂等处理业务(积分发放、通知)+ 手动ACK
4. 消费成功:更新消息状态为已处理 + 持久去重表防重
5. 失败重试:最多3次(指数退避+抖动),超过则进入DLQ人工介入
优势:
- ✅ 性能好:接近本地事务性能(响应时间80ms,吞吐量800 TPS)
- ✅ 可靠性高:消息不丢失(Publisher Confirms + 手动ACK)
- ✅ 解耦:服务间松耦合
- ✅ 可运维:完整监控告警体系,支持故障快速定位
9.3 Seata分布式事务(谨慎使用)
⚠️ 仅用于以下场景:
- 余额扣减:用户服务扣减余额 + 订单服务创建订单
- 退款操作:支付服务退款 + 用户服务增加余额
使用示例(简化):
@GlobalTransactional(name = "refund-order-tx", rollbackFor = Exception.class)
public void refundOrder(Long orderId) {
// 1. 更新订单状态
orderMapper.updateStatus(orderId, REFUNDED);
// 2. 创建退款记录
paymentService.createRefund(orderId);
// 3. 增加用户余额(跨服务调用)
userService.addBalance(userId, amount);
}
性能优化要点:
- 控制事务粒度,避免长事务(<3秒)
- 非关键流程异步化(如发送通知)
- 监控事务耗时,超时告警
9.4 TCC模式(高级场景)
适用场景:需要精确控制资源的场景(库存扣减、秒杀)
三阶段说明:
- Try:冻结资源(库存预扣,写入冻结表)
- Confirm:确认扣减(实际扣除库存)
- Cancel:取消回滚(释放冻结库存)
实现要点:幂等性处理 + 唯一流水号防重
9.5 数据对账机制
每日对账任务:
1. 对比订单表 vs 支付流水表
2. 识别差异订单:
- 订单已支付但无支付流水 → 订单异常
- 支付流水存在但订单未更新 → 补偿更新
3. 生成对账报告,差异订单人工介入
关键指标监控:
- 对账差异率:< 0.1%
- 补偿成功率:> 99%
十一、Docker + Kubernetes部署
10.1 Docker镜像构建
Dockerfile最佳实践:
- 基础镜像: openjdk:17-slim (精简版)
- 多阶段构建减小镜像体积
- 使用
.dockerignore排除无关文件 - 健康检查:
HEALTHCHECK CMD curl -f http://localhost:{PORT}/actuator/health
镜像分层优化:
- 依赖层(pom.xml依赖)单独缓存
- 业务代码层独立,提高构建速度
- 镜像大小控制在200MB以内
10.2 Kubernetes部署
资源配置:
- Deployment: 每个微服务独立部署,副本数2-3
- Service: ClusterIP类型,内部服务间通信
- Ingress: 暴露API网关,统一入口
- ConfigMap: 存储配置文件
- Secret: 存储敏感信息(数据库密码、密钥)
资源限制:
- Request: CPU 500m、内存512Mi
- Limit: CPU 2000m、内存2Gi
- 根据实际负载动态调整
滚动更新:
strategy: RollingUpdatemaxSurge: 1(最多额外启动1个Pod)maxUnavailable: 0(保证服务不中断)
健康检查:
- Liveness Probe: 检查服务是否存活
- Readiness Probe: 检查服务是否就绪接收流量
- 探测路径:
/actuator/health
十二、监控与日志
12.1 Spring Boot Admin服务监控
监控指标:
- JVM内存使用率、GC次数
- 线程池状态(活跃线程数、队列长度)
- HTTP请求量、响应时间
- 数据库连接池状态
- 缓存命中率
告警配置:
- 内存使用率>80%告警
- 响应时间>2秒告警
- 错误率>5%告警
- 发送通知: 邮件、钉钉、企业微信
11.2 ELK日志收集
日志采集:
- Logstash收集各微服务日志
- 日志格式统一JSON格式
- 包含: 时间戳、服务名、日志级别、TraceId、消息
日志存储:
- Elasticsearch存储,按天创建索引
- 保留周期: 最近30天
- 冷数据归档到OSS
日志查询:
- Kibana可视化查询
- 按TraceId追踪完整请求链路
- 错误日志聚合分析
11.3 SkyWalking链路追踪
追踪范围:
- HTTP请求链路
- RPC调用(OpenFeign)
- 数据库查询
- Redis操作
- 消息队列
性能分析:
- 慢请求分析(>2秒)
- SQL慢查询定位
- 服务依赖拓扑图
- 接口性能趋势
十三、数据库设计
详细数据库设计文档: 请参见 数据库设计文档-完整版.md
该文档包含完整的数据库架构设计、12张核心表详细结构、订单状态机、索引优化策略、数据备份恢复、数据安全与合规等详细内容。
13.1 数据库技术栈
| 技术组件 | 版本/方案 | 用途说明 | |
|---|---|---|---|
| 数据库 | MySQL 8.0 | 主数据库,支持JSON字段类型 | |
| 连接池 | HikariCP | Spring Boot 3默认连接池 | |
| ORM框架 | MyBatis | 对象关系映射,XML配置 | |
| 缓存层 | Redis 7.x | 热点数据缓存 | |
| NoSQL | MongoDB 5.0 | 护理日志非结构化数据 | |
| 主从架构 | MySQL Master-Slave | 读写分离,提升性能 |
十四、第三方服务集成
14.1 微信支付配置
配置步骤:
- 登录微信商户平台获取商户号
- 下载商户私钥证书apiclient_key.pem
- 设置APIv3密钥(32字节随机字符串)
- 获取证书序列号
- 配置支付回调域名白名单
环境变量配置:
WX_PAY_MERCHANT_ID: 商户号WX_PAY_API_V3_KEY: APIv3密钥WX_PAY_CERT_SERIAL_NO: 证书序列号
13.2 支付宝支付配置
配置步骤:
- 登录支付宝开放平台创建应用
- 生成RSA2密钥对
- 上传应用公钥,获取支付宝公钥
- 配置授权回调地址和支付回调地址
- 提交应用审核上线
环境变量配置:
ALIPAY_APP_ID: 应用IDALIPAY_PRIVATE_KEY: 应用私钥ALIPAY_PUBLIC_KEY: 支付宝公钥
13.3 高德地图配置
服务端Web API:
- 申请Web服务API Key
- 配置IP白名单
- 使用: 地理编码、逆地理编码、距离计算、路径规划
环境变量配置:
AMAP_API_KEY: 高德地图API Key
13.4 极光推送配置
Flutter端配置:
- 申请Android和iOS应用
- 下载配置文件
- 集成JPush SDK
环境变量配置:
JPUSH_APP_KEY: 极光推送AppKeyJPUSH_MASTER_SECRET: MasterSecret
13.5 阿里云OSS配置
配置步骤:
- 登录阿里云OSS控制台创建Bucket
- 设置Bucket访问权限(推荐私有读写,通过签名URL访问)
- 创建RAM子账号,授予OSS读写权限
- 配置跨域规则CORS允许前端直传
- 设置生命周期规则自动删除过期文件
环境变量配置:
ALIYUN_OSS_ENDPOINT: 节点域名ALIYUN_OSS_BUCKET_NAME: Bucket名称ALIYUN_OSS_ACCESS_KEY_ID: AccessKey IDALIYUN_OSS_ACCESS_KEY_SECRET: AccessKey Secret
13.6 阿里云短信服务配置
配置步骤:
- 登录阿里云短信服务控制台
- 申请短信签名(需企业资质,2-3个工作日审核)
- 申请短信模板(不同场景需不同模板)
- 创建RAM子账号,授予短信发送权限
- 购买短信套餐包
环境变量配置:
ALIYUN_SMS_ACCESS_KEY_ID: AccessKey IDALIYUN_SMS_ACCESS_KEY_SECRET: AccessKey SecretALIYUN_SMS_SIGN_NAME: 短信签名ALIYUN_SMS_TEMPLATE_CODE: 短信模板CODE
13.7 实名认证配置(阿里云)
配置步骤:
- 登录阿里云实人认证控制台
- 开通实人认证服务
- 选择认证方案(人脸识别+身份证OCR)
- 配置回调地址
- 购买认证次数包(按次计费)
环境变量配置:
ALIYUN_VERIFY_ACCESS_KEY_ID: AccessKey IDALIYUN_VERIFY_ACCESS_KEY_SECRET: AccessKey Secret
13.8 第三方服务成本预估
| 服务 | 计费方式 | 预估成本(月) |
|---|---|---|
| 微信支付 | 0.6%手续费 | 按交易额计算 |
| 支付宝 | 0.6%手续费 | 按交易额计算 |
| 高德地图API | 按调用次数 | 500-1000元 |
| 极光推送 | 按推送条数 | 300-500元 |
| 阿里云OSS | 按存储+流量 | 200-300元 |
| 阿里云短信 | 0.045元/条 | 500-800元 |
| 实名认证 | 0.3-1元/次 | 300-500元 |
| 合计 | - | 2000-3600元 |
成本优化建议:
- 高德地图API使用缓存,减少重复调用
- OSS配置生命周期,自动清理过期文件
- 短信验证码添加图形验证码前置,防止恶意刷短信
- 推送服务区分重要通知和普通通知,降低推送频率
十五、编码标准
15.1 代码标准
命名约定:
- 包名: com.maiban.health.{模块名}
- 类名: 大驼峰命名法
- 方法名: 小驼峰命名法
- 常量: 全大写下划线分隔
注释要求:
- 类级别注释: 说明类的职责
- 方法级别注释: 说明参数、返回值、异常
- 关键业务逻辑注释
14.1.1 MyBatis 编码规范(重要)
强制要求:必须使用 XML Mapper 配置
为什么使用 XML 配置而非注解:
| 对比维度 | XML 配置 | 注解方式 | 推荐 |
|---|---|---|---|
| 复杂 SQL | 清晰易读,支持格式化 | 字符串拼接,难维护 | ✅ XML |
| 动态 SQL | 完整标签支持 | 受限,需要拼接 | ✅ XML |
| 代码审查 | SQL 变更一目了然 | 混在代码中,易遗漏 | ✅ XML |
| 性能优化 | ResultMap 灵活映射 | 配置受限 | ✅ XML |
| SQL 管理 | 集中管理,便于 DBA 审查 | 分散在各个类中 | ✅ XML |
| 接口简洁性 | 接口只有方法声明 | 接口被注解污染 | ✅ XML |
MyBatis Generator 配置要求:
<!-- generatorConfig.xml 配置示例 -->
<generatorConfiguration>
<context id="MaibanContext" targetRuntime="MyBatis3">
<!-- ✅ 正确:使用 MyBatis3 生成 XML 配置 -->
<!-- ❌ 错误:不要使用 MyBatis3Simple 或 MyBatis3DynamicSql -->
<!-- 生成 Model 类 -->
<javaModelGenerator targetPackage="com.maiban.health.nurse.mbg.model"
targetProject="src/main/java"/>
<!-- 生成 XML Mapper 文件 -->
<sqlMapGenerator targetPackage="com.maiban.health.nurse.mbg.mapper"
targetProject="src/main/resources"/>
<!-- 生成 Mapper 接口(仅方法声明,无注解) -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.maiban.health.nurse.mbg.mapper"
targetProject="src/main/java"/>
</context>
</generatorConfiguration>
Mapper 接口规范(禁止使用注解):
// ✅ 正确示例:接口简洁,无注解
public interface NurseMapper {
/**
* 根据 ID 查询技师信息
*/
Nurse selectByPrimaryKey(Long id);
/**
* 根据条件查询技师列表
*/
List<Nurse> selectByExample(NurseExample example);
/**
* 插入技师信息
*/
int insert(Nurse record);
/**
* 更新技师信息
*/
int updateByPrimaryKey(Nurse record);
}
// ❌ 错误示例:禁止使用注解
public interface NurseMapper {
@Select("SELECT * FROM nurses WHERE id = #{id}") // ❌ 禁止
Nurse selectByPrimaryKey(Long id);
@Insert("INSERT INTO nurses ...") // ❌ 禁止
int insert(Nurse record);
}
XML Mapper 规范:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.maiban.health.nurse.mbg.mapper.NurseMapper">
<!-- ResultMap 定义 -->
<resultMap id="BaseResultMap" type="com.maiban.health.nurse.mbg.model.Nurse">
<id column="id" property="id" jdbcType="BIGINT"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<result column="phone" property="phone" jdbcType="VARCHAR"/>
<!-- 更多字段映射... -->
</resultMap>
<!-- 基础查询 SQL -->
<sql id="Base_Column_List">
id, name, phone, gender, status, created_at, updated_at
</sql>
<!-- 简单查询 -->
<select id="selectByPrimaryKey" parameterType="java.lang.Long"
resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List"/>
FROM nurses
WHERE id = #{id,jdbcType=BIGINT}
</select>
<!-- 动态 SQL 示例 -->
<select id="selectByExample" parameterType="com.maiban.health.nurse.mbg.model.NurseExample"
resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List"/>
FROM nurses
<where>
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="status != null">
AND status = #{status}
</if>
<if test="cityId != null">
AND city_id = #{cityId}
</if>
</where>
ORDER BY created_at DESC
</select>
<!-- 批量插入示例 -->
<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO nurses (name, phone, gender, status)
VALUES
<foreach collection="list" item="item" separator=",">
(#{item.name}, #{item.phone}, #{item.gender}, #{item.status})
</foreach>
</insert>
<!-- 复杂联表查询示例 -->
<select id="selectNurseWithCertificates" resultMap="NurseWithCertificatesMap">
SELECT
n.id, n.name, n.phone,
c.id as cert_id, c.cert_name, c.cert_no
FROM nurses n
LEFT JOIN nurse_certificates c ON n.id = c.nurse_id
WHERE n.id = #{nurseId}
</select>
<resultMap id="NurseWithCertificatesMap" type="com.maiban.health.nurse.dto.NurseWithCertificatesDTO">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="phone" property="phone"/>
<collection property="certificates" ofType="com.maiban.health.nurse.mbg.model.NurseCertificate">
<id column="cert_id" property="id"/>
<result column="cert_name" property="certName"/>
<result column="cert_no" property="certNo"/>
</collection>
</resultMap>
</mapper>
动态 SQL 常用标签:
| 标签 | 用途 | 示例 |
|---|---|---|
<if> | 条件判断 | <if test="name != null">AND name = #{name}</if> |
<choose> | 多条件分支 | <choose><when><otherwise> |
<where> | 智能 WHERE 子句 | 自动去除多余的 AND/OR |
<set> | 智能 SET 子句 | UPDATE 时自动处理逗号 |
<foreach> | 循环遍历 | 批量插入、IN 查询 |
<trim> | 去除前后缀 | 灵活处理 SQL 片段 |
<sql> | SQL 片段复用 | 定义公共字段列表 |
包路径规范:
项目结构:
src/main/java/com/maiban/health/{service}/
├── mbg/
│ ├── model/ # MyBatis Generator 生成的实体类
│ │ ├── Nurse.java
│ │ └── NurseExample.java
│ └── mapper/ # MyBatis Generator 生成的 Mapper 接口
│ └── NurseMapper.java
├── mapper/ # 自定义 Mapper 接口(扩展)
│ └── NurseExtMapper.java
└── service/
└── NurseService.java
src/main/resources/com/maiban/health/{service}/mbg/mapper/
├── NurseMapper.xml # MyBatis Generator 生成的 XML
└── NurseExtMapper.xml # 自定义 Mapper 的 XML
代码检查清单:
- [ ] ✅ Mapper 接口中无任何注解(@Select/@Insert/@Update/@Delete)
- [ ] ✅ 所有 SQL 语句都在 XML 文件中
- [ ] ✅ 复杂查询使用了动态 SQL 标签
- [ ] ✅ ResultMap 定义清晰,字段映射完整
- [ ] ✅ 使用
<sql>标签复用公共 SQL 片段 - [ ] ✅ XML 文件格式化规范,缩进一致
- [ ] ✅ SQL 语句可读性好,关键字大写
14.2 接口标准
统一返回格式:
返回成功:
- code: 200
- message: "成功"
- data: 业务数据
返回失败:
- code: 错误码
- message: 错误描述
- data: null
分页返回格式:
- pageNum: 当前页
- pageSize: 每页数量
- total: 总记录数
- list: 数据列表
14.3 异常处理
异常分类:
- BusinessException: 业务异常(可预期)
- SystemException: 系统异常(不可预期)
全局异常处理:
- 使用
@RestControllerAdvice统一处理 - 记录错误日志
- 返回友好错误提示
14.4 日志标准
日志级别:
- ERROR: 严重错误,需立即处理
- WARN: 警告信息,需关注
- INFO: 一般信息,业务流程关键节点
- DEBUG: 调试信息,仅开发环境
日志内容:
- 包含: 时间戳、日志级别、类名、方法名、消息
- 敏感信息脱敏(手机号、身份证号)
十六、上线检查清单
16.1 代码检查
- [ ] 代码标准检查(阿里巴巴Java编码标准)
- [ ] 代码review完成
- [ ] 单元测试覆盖率>80%
- [ ] 集成测试通过
- [ ] 性能测试通过
15.2 配置检查
- [ ] 生产环境配置正确
- [ ] 敏感信息使用环境变量
- [ ] 数据库连接池配置合理
- [ ] Redis连接池配置合理
- [ ] 日志级别配置为INFO
15.3 部署检查
- [ ] Docker镜像构建成功
- [ ] Kubernetes配置正确
- [ ] 健康检查配置正确
- [ ] 资源限制配置合理
- [ ] 滚动更新策略配置
15.4 监控检查
- [ ] Spring Boot Admin监控正常
- [ ] ELK日志收集正常
- [ ] SkyWalking链路追踪正常
- [ ] 告警配置正确
- [ ] 告警通知渠道正常
十七、Redis缓存策略详解
17.1 缓存更新策略
Cache-Aside Pattern(推荐):
| 操作 | 执行顺序 | 说明 |
|---|---|---|
| 读操作 | 1. 查缓存 → 2. 缓存Miss → 3. 查数据库 → 4. 写缓存 | 标准读取流程 |
| 写操作 | 1. 更新数据库 → 2. 删除缓存 | ⚠️ 先更新DB,再删缓存 |
为什么删除缓存而不是更新?
- 避免并发更新导致脏数据
- 减少缓存写入次数(读多写少场景)
- 下次读取时自动回填最新数据
16.2 缓存雪崩/击穿/穿透防护
三大问题对比:
| 问题 | 原因 | 影响 | 解决方案 |
|---|---|---|---|
| 雪崩 | 大量key同时过期 | DB瞬间压力激增 | 过期时间加随机值(30±5分钟) |
| 击穿 | 热点key过期瞬间 | 大量请求打到DB | 互斥锁(SETNX)或永不过期 |
| 穿透 | 查询不存在的数据 | 缓存无效,每次都查DB | 布隆过滤器 + 缓存空值 |
实现方案:
1. 防穿透:布隆过滤器 + 缓存空值
流程:
1. 布隆过滤器判断用户是否存在
2. 不存在 → 直接返回null(不查DB)
3. 存在 → 查缓存 → 缓存Miss → 查DB
4. DB也没有 → 缓存空对象5分钟
2. 防击穿:分布式锁
热点key(如热门技师):
1. 缓存Miss时,尝试获取分布式锁
2. 获取成功 → 查DB → 回填缓存 → 释放锁
3. 获取失败 → 等待100ms后重试(最多3次)
3. 防雪崩:过期时间随机化
// 基础过期时间30分钟,加上0-5分钟随机值
int expireTime = 1800 + RandomUtils.nextInt(0, 300);
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
16.3 缓存分层策略
| 层级 | 技术 | 场景 | TTL | 命中率 |
|---|---|---|---|---|
| L1 本地缓存 | Caffeine | 技师资质、服务项目配置 | 10分钟 | 95% |
| L2 Redis缓存 | Redis | 用户信息、技师详情 | 30分钟 | 85% |
| L3 数据库 | MySQL | 持久化数据 | - | - |
本地缓存 + Redis两级缓存:
- 减少Redis网络开销(L1命中率95%)
- 适合读多写少的配置数据
- 注意:更新时需清理两级缓存
16.4 Redis高可用方案
开发环境:单机模式
成本:1台服务器
可用性:99%
适用:开发、测试环境
生产环境方案一:主从 + 哨兵(推荐初期)
架构:1主2从 + 3哨兵
成本:3台服务器
可用性:99.9%
故障恢复:自动切换(<30秒)
适用:日活<10万
生产环境方案二:Redis Cluster(推荐中后期)
架构:6节点(3主3从)
成本:6台服务器
可用性:99.99%
性能:数据分片,QPS提升3倍
适用:日活>10万或数据量>100GB
16.5 缓存监控指标
| 指标 | 健康值 | 告警阈值 | 处理方式 |
|---|---|---|---|
| 缓存命中率 | >80% | <70% | 优化缓存策略 |
| 内存使用率 | <70% | >85% | 扩容或清理 |
| 慢查询 | <10ms | >50ms | 优化数据结构 |
| 连接数 | <500 | >800 | 检查连接泄漏 |
十八、降级容灾方案
18.1 服务降级策略
限流降级(Sentinel):
| 服务 | 限流阈值 | 降级策略 | 恢复时间 |
|---|---|---|---|
| 订单服务 | 1000 QPS | 返回"系统繁忙" | 实时监控 |
| 支付服务 | 500 QPS | 排队等待 | 自动恢复 |
| IM消息 | 2000 QPS | 延迟推送 | 1分钟 |
| 营销服务 | 300 QPS | 关闭活动入口 | 5分钟 |
实现方案(注解式):
@SentinelResource(
value = "createOrder",
blockHandler = "createOrderBlockHandler", // 限流降级
fallback = "createOrderFallback" // 异常降级
)
public Order createOrder(OrderDTO dto) {
// 正常业务逻辑
}
// 限流时的降级方法
public Order createOrderBlockHandler(OrderDTO dto, BlockException e) {
throw new BusinessException("当前下单人数过多,请稍后再试");
}
// 服务异常时的降级方法
public Order createOrderFallback(OrderDTO dto, Throwable e) {
// 记录到本地消息表,异步重试
return Order.pending(dto);
}
17.2 依赖服务降级
外部依赖降级优先级:
| 依赖服务 | 重要性 | 降级方案 | 影响 |
|---|---|---|---|
| Redis | 高 | 降级到DB查询 | 性能下降50% |
| Elasticsearch | 中 | 降级到MySQL搜索 | 搜索功能受限 |
| 支付宝/微信支付 | 高 | 切换备用通道 | 无影响 |
| 高德地图API | 中 | 使用缓存数据 | 位置可能不准 |
| 极光推送 | 低 | 记录日志,稍后重试 | 通知延迟 |
Redis降级示例:
public User getUserById(Long userId) {
try {
// 优先查Redis
return redisTemplate.get("user:" + userId);
} catch (RedisException e) {
log.warn("Redis故障,降级到数据库查询");
// 降级到数据库
return userMapper.selectById(userId);
}
}
17.3 熔断器配置
熔断状态机:
关闭(Closed) → 打开(Open) → 半开(Half-Open) → 关闭
↓ ↓ ↓
正常请求 快速失败 尝试恢复
熔断参数配置:
| 服务 | 失败率阈值 | 熔断时间 | 半开请求数 |
|---|---|---|---|
| 用户服务 | 50% | 30秒 | 5个 |
| 支付服务 | 30% | 60秒 | 3个 |
| 技师服务 | 50% | 30秒 | 5个 |
17.4 容灾演练计划
演练场景:
| 场景 | 频率 | 验证内容 |
|---|---|---|
| MySQL主库宕机 | 每季度 | 主从自动切换,业务不中断 |
| Redis集群故障 | 每季度 | 降级方案生效,性能可接受 |
| 单个微服务宕机 | 每月 | 其他服务正常,自动剔除故障节点 |
| API网关故障 | 每季度 | 备用网关接管流量 |
十九、安全设计方案
19.1 接口安全
防刷策略(多层防护):
| 层级 | 方案 | 限制 | 场景 |
|---|---|---|---|
| L1 IP限流 | Nginx限流 | 同IP 100次/分钟 | 防爬虫 |
| L2 用户限流 | Sentinel | 同用户 50次/分钟 | 防刷单 |
| L3 验证码 | 图形/短信验证码 | 敏感操作必须验证 | 防机器人 |
| L4 风控规则 | 异常行为识别 | 封禁异常账号 | 防羊毛党 |
实现示例(注解式):
// 接口级别限流
@RateLimit(limit = 10, window = 60, key = "#phone")
public Result sendSms(String phone) {
// 60秒内同一手机号最多10次
}
18.2 数据安全
敏感数据加密:
| 数据类型 | 加密方式 | 存储格式 | 解密场景 |
|---|---|---|---|
| 手机号 | AES-256 | 加密存储 | 显示时脱敏 |
| 身份证号 | AES-256 | 加密存储 | 实名认证时 |
| 银行卡号 | AES-256 | 加密存储 | 提现时 |
| 健康数据 | AES-256 | 加密存储 | 查看详情时 |
| 用户密码 | BCrypt | 不可逆加密 | 不解密,仅校验 |
数据脱敏规则:
手机号:138****1234
身份证:510***********1234
银行卡:6222************1234
邮箱:abc***@qq.com
18.3 认证授权增强
Token安全:
- Token有效期:30天(可配置)
- 刷新机制:距离过期7天内自动续期
- 双Token机制:AccessToken(短期) + RefreshToken(长期)
- 异地登录检测:同账号不同地区登录告警
权限控制:
角色层级:
- 超级管理员:所有权限
- 运营人员:订单管理、用户管理
- 客服人员:订单查看、客诉处理
- 财务人员:财务报表、提现审核
18.4 SQL注入与XSS防护
SQL注入防护:
- 使用MyBatis预编译(#{}而非${})
- 禁止拼接SQL
- 数据库账号最小权限原则
XSS防护:
- 输入过滤:过滤
<script></iframe>等标签 - 输出转义:显示时HTML转义
- CSP策略:Content-Security-Policy响应头
18.5 安全检查清单
上线前必检项:
| 检查项 | 要求 | 检查方式 |
|---|---|---|
| HTTPS | 全站HTTPS | 证书有效期检查 |
| 敏感信息 | 不能硬编码 | 代码扫描 |
| SQL注入 | 无拼接SQL | 代码审查 |
| XSS漏洞 | 输入过滤+输出转义 | 渗透测试 |
| 权限校验 | 所有接口鉴权 | 自动化测试 |
二十、关键技术实现方案
20.1 AI智能推荐系统
技师推荐算法:
推荐分数 = 距离分(40%) + 评分分(30%) + 专业匹配度(20%) + 完单数(10%)
距离分:
- 1km内: 100分
- 1-3km: 80分
- 3-5km: 60分
- 5-10km: 40分
- >10km: 0分
评分分:
- 5.0分: 100分
- 4.5-4.9分: 80分
- 4.0-4.4分: 60分
- <4.0分: 0分
专业匹配度:
- 主专业匹配: 100分
- 次专业匹配: 70分
- 不匹配: 30分
完单数加成:
- >1000单: 100分
- 500-1000单: 80分
- 100-500单: 60分
- <100单: 40分
体检报告AI分析:
- 集成通义千问API
- OCR识别体检报告文字
- AI解读指标含义、识别异常
- 生成通俗易懂的健康评估报告
- 推荐适合的护理项目
19.2 即时通讯IM系统
架构设计(支持水平扩展):
┌─────────────────────────────────────────┐
│ 客户端层(用户端/技师端) │
└─────────────────┬───────────────────────┘
│ WebSocket连接
┌─────────────────▼───────────────────────┐
│ 负载均衡(Nginx) │
│ - 基于IP Hash分配连接 │
└─────────────────┬───────────────────────┘
│
┌─────────────────▼───────────────────────┐
│ IM服务集群(多实例,可水平扩展) │
│ - 每个实例维护本地连接表 │
│ - 订阅Redis Pub/Sub接收消息 │
└─────────────────┬───────────────────────┘
│
┌─────────────────▼───────────────────────┐
│ 消息路由层(Redis Pub/Sub) │
│ - channel: im:user:{userId} │
│ - 消息广播到所有IM实例 │
└─────────────────┬───────────────────────┘
│
┌─────────────────▼───────────────────────┐
│ 消息存储层(MongoDB) │
│ - 聊天记录持久化(保留30天) │
│ - 离线消息队列 │
└─────────────────────────────────────────┘
关键设计要点:
| 问题 | 解决方案 | 说明 |
|---|---|---|
| 水平扩展 | Redis Pub/Sub + 连接路由 | 用户上线记录在Redis:user:{id}→{server_ip},消息通过Pub/Sub广播 |
| 消息必达 | ACK机制 + 离线队列 | 客户端收到消息回复ACK,未收到存离线队列,上线后拉取 |
| 消息去重 | 消息唯一ID | 每条消息生成UUID,客户端和服务端都做去重 |
| 敏感词过滤 | 本地敏感词库 + 云端API | 高频词本地匹配(性能),低频词调用阿里云API |
消息流程(优化版):
1. 用户A发送消息 → IM服务实例1
2. 敏感词过滤(本地词库 + 阿里云API)
3. 保存MongoDB(异步,不影响发送速度)
4. 查询Redis:用户B在哪个实例?
5. 在线 → 通过Redis Pub/Sub推送到实例2 → WebSocket推送
6. 离线 → 存离线队列 + 极光推送通知
7. 用户B上线 → 拉取离线消息(最近100条)
消息类型支持:
- 文字消息:纯文本 + 表情
- 图片消息:上传OSS → 返回缩略图URL + 原图URL
- 语音消息:上传OSS → 返回URL + duration(支持语音转文字)
- 位置消息:lat/lng坐标 + 地址描述
- 订单卡片:order_id关联,显示订单摘要
19.3 优惠券系统
优惠券叠加规则引擎:
// 优惠券计算顺序
1. 先应用折扣券 (如9折)
2. 再应用满减券 (如满200减30)
3. 再应用会员折扣 (如会员9折)
4. 最后应用无门槛券
// 示例计算
原价: 300元
折扣券9折: 300 * 0.9 = 270元
满减券满200减30: 270 - 30 = 240元
会员折扣9折: 240 * 0.9 = 216元
优惠券防刷策略:
- 领取限制: 每人每张优惠券限领1次
- IP限制: 同IP每日领取限制10次
- 设备指纹: 防止模拟器批量领取
- 风控系统: 异常领取行为风控拦截
19.4 红包系统
红包雨实现:
1. Redis预热红包池:
- key: red_packet_rain:{activity_id}
- value: List<{amount, id}>
2. 用户点击抢红包:
- Redis LPOP弹出一个红包
- 成功 → 写入user_red_packets表
- 失败(池空) → 返回"手慢了"
3. 防止超抢:
- 使用Redis原子操作
- 每个用户限抢N次(Redis计数)
随机红包算法:
// 二倍均值法
总金额: 100元
总个数: 10个
平均值: 10元
每次随机: random(0.01, 平均值 * 2)
第1个: random(0.01, 20) = 15元, 剩余85元, 平均9.44元
第2个: random(0.01, 18.88) = 8元, 剩余77元, 平均9.625元
...
19.5 拼团系统
拼团状态机:
发起拼团 → 等待成团 → 成团成功 → 订单支付 → 订单完成
↓
超时未成团 → 自动退款
成团逻辑:
- Redis存储拼团进度:
pintuan:{团ID} → {已参团人数} - 每人参团时 Redis INCR 原子递增
- 达到要求人数 → 发送成团通知
- 24小时未成团 → 定时任务自动退款
19.6 秒杀系统
高并发秒杀方案:
1. 缓存预热:
- 秒杀开始前将商品库存加载到Redis
- key: seckill:stock:{商品ID} → 库存数
2. 库存扣减:
- Redis DECR原子递减
- 扣减成功 → 允许下单
- 扣减失败(库存<0) → 返回"已抢光"
3. 异步下单:
- 发送消息到RabbitMQ
- 消费者异步创建订单
- 扣减数据库库存
4. 防止超卖:
- Redis原子操作保证
- 数据库库存二次校验
- 分布式锁保护
19.7 实时位置追踪
技术方案:
- 技师端: 每10秒上报位置(lat/lng)
- 后端存储: Redis GEO数据结构
- 用户端查询:
- APP: 每30秒轮询
- APP: WebSocket实时推送
Redis GEO命令:
// 技师上报位置
GEOADD nurses:location 116.404 39.915 nurse:123
// 查询技师位置
GEOPOS nurses:location nurse:123
// 计算距离
GEODIST nurses:location nurse:123 user:456 km
19.8 老带新师徒系统
提成计算逻辑:
-- 徒弟完单时触发
1. 查询师徒关系:
SELECT * FROM nurse_mentor_relations
WHERE apprentice_id = #{徒弟ID}
2. 计算提成:
提成金额 = 订单金额 * 提成比例
- 前6个月: 2%
- 6-12个月: 1%
- 12个月后: 0%
3. 师傅账户入账:
INSERT INTO settlement_records
(nurse_id, amount, type, order_id)
VALUES (师傅ID, 提成金额, 'MENTOR_COMMISSION', 订单ID)
4. 推送通知师傅
邀请奖励发放:
- 事件驱动: 徒弟达成条件 → 发送MQ消息
- 营销服务消费消息 → 发放奖励
- 支付财务服务 → 奖励金入账
19.9 物联网设备集成
设备数据同步:
1. 设备端:
- 蓝牙/WiFi连接APP
- 上报数据: {device_id, type, value, timestamp}
2. 后端处理:
- 健康管理服务接收数据
- 存储到MongoDB (时序数据)
- Redis缓存最新数据
3. 异常预警:
- 规则引擎判断异常 (如心率>120)
- 触发预警 → RabbitMQ消息
- IM消息服务 → 推送通知用户
支持设备类型:
- 智能手环/手表: 心率、步数、睡眠
- 血压计: 血压数据
- 血糖仪: 血糖数据
- 血氧仪: 血氧饱和度
- 体温计: 体温数据
二十一、常见问题FAQ
Q1: 如何选择AT模式还是TCC模式? A: AT模式适用于大多数场景,简单易用;TCC模式适用于需要精确控制资源的场景,如余额扣减、库存扣减。
Q2: 如何保证消息队列的可靠性? A: 生产者确认、消费者手动ACK、死信队列三重保障。
Q3: 如何处理分布式事务超时? A: 控制事务粒度,避免长事务;非关键流程改用本地消息表+定时补偿。
Q4: 如何优化服务间调用性能? A: 批量接口、合理超时时间、请求压缩、连接池复用。
Q5: 如何保证配置安全? A: 敏感信息使用环境变量,Nacos配置加密,定期审计。
Q6: 如何快速定位线上问题? A: SkyWalking链路追踪+ELK日志查询+Spring Boot Admin监控。
Q10: 10个微服务如何支撑225个功能点? A: 通过合理的领域拆分和服务聚合,每个服务承载相关业务功能:
- 用户服务(20+功能): 账户、家庭成员、地址、收藏等
- 技师服务(25+功能): 技师管理、AI推荐、师徒关系等
- 订单服务(25+功能): 订单、预约、追踪、打卡等
- 支付财务(20+功能): 支付、退款、分账、提现、发票等
- 健康管理(20+功能): 档案、日志、体检AI、物联网等
- 营销服务(45+功能): 优惠券、积分、会员、红包、活动等
- IM消息(15+功能): 即时通讯、推送、通知等
- 商城服务(20+功能): 商品、购物车、订单、物流等
- 搜索服务(5+功能): 技师搜索、商品搜索、热门搜索等
- 运营管理(30+功能): 后台管理、审核、数据报表等
二十二、架构风险与优化建议(重要)
22.1 架构风险评估
已识别的高风险问题:
| 风险项 | 风险等级 | 影响 | 优化建议 | 优先级 |
|---|---|---|---|---|
| 分布式事务过度使用 | 高 | 性能降低10倍 | 改用本地消息表+MQ | P0 |
| 支付回调幂等性缺失 | 高 | 可能重复扣款 | 增加唯一索引+分布式锁 | P0 |
| Redis单点故障 | 高 | 服务不可用 | 部署Redis集群 | P0 |
| 缓存策略不完善 | 中 | 缓存穿透/击穿 | 布隆过滤器+互斥锁 | P1 |
| 服务边界模糊 | 中 | 耦合度高 | 明确数据归属 | P1 |
| IM架构不清晰 | 中 | 无法水平扩展 | Redis Pub/Sub方案 | P2 |
风险影响评估:
如果不解决P0问题,预计每月损失:
- 支付问题导致纠纷:5-10万
- Redis故障停服:10万/次
- 性能问题导致用户流失:20-30万
总计:50-100万/月(按GMV 1000万计算)
21.2 性能优化建议
响应时间优化目标:
| 接口类型 | 当前预估 | 优化目标 | 优化方案 |
|---|---|---|---|
| 用户登录 | 300ms | 100ms | 缓存用户信息 |
| 技师列表 | 500ms | 150ms | Redis预计算+ES搜索 |
| 创建订单 | 1000ms | 300ms | 去掉分布式事务 |
| 支付接口 | 2000ms | 500ms | 异步处理 |
数据库优化:
- 读写分离:读操作占80%,分离后主库压力降低80%
- 索引优化:关键查询字段添加索引(订单号、用户ID、技师ID)
- 分页优化:避免深分页(offset>10000),使用游标分页
缓存优化:
- 命中率目标:>80%(当前可能<50%)
- 本地缓存+Redis两级缓存
- 缓存预热:系统启动时加载热点数据
21.3 成本优化建议
当前成本:约18,000元/月
优化方案:
| 项目 | 当前成本 | 优化后 | 节省 | 优化方式 |
|---|---|---|---|---|
| 服务器 | 13,300元 | 8,000元 | 40% | Kubernetes混合部署 |
| 数据库 | 1,500元 | 1,200元 | 20% | 冷热数据分离 |
| 第三方服务 | 2,400元 | 1,600元 | 33% | 缓存优化+防刷 |
| 合计 | 18,000元 | 12,000元 | 33% | - |
具体措施:
- 服务器:Kubernetes按需分配资源,非高峰期缩容
- 高德地图:缓存常用路线,减少60%调用
- 短信服务:图形验证码前置,减少40%恶意请求
- OSS存储:生命周期管理,30天后归档
二十三、架构总结与建议
23.1 架构优势
业务覆盖完整: 10个服务合理支撑225个功能点,无遗漏
技术栈现代化: Spring Boot 3.2 + JDK 17,未来5年不过时
运维复杂度可控: 10个服务运维成本合理,不会过度膨胀
性能可扩展: 关键服务(订单/IM/商城/搜索)可独立扩容
数据安全合规: 健康数据加密、实名认证、隐私保护完善
22.2 分期开发建议(优化版)
⚠️ 重要调整:MVP范围缩小,快速验证市场
第一期(1.5-2个月): MVP最小化(推荐)
🎯 核心目标:2个月内上线,快速验证核心业务闭环
服务范围(4个简化服务):
用户服务(简化版)
- 手机号登录
- 基本信息管理
- 地址管理(1个地址即可)
- ❌ 暂不实现:家庭成员、实名认证、收藏、浏览历史
技师服务(简化版)
- 技师列表查询
- 技师详情
- 基础筛选(距离、价格、评分)
- ❌ 暂不实现:AI推荐、在线状态、师徒关系
订单服务(含基础IM)
- 创建订单
- 订单支付
- 状态流转(待支付→已支付→服务中→已完成)
- 基础IM(文字消息,集成在订单服务内)
- ❌ 暂不实现:位置追踪、套餐卡、长期预约
支付财务服务(简化版)
- 微信支付
- 支付回调
- ❌ 暂不实现:分账、提现、支付宝
交付目标:
- ✅ 用户能下单预约护理服务
- ✅ 技师能接单提供服务
- ✅ 完成支付流程
- ✅ 基本的文字沟通
- 🎯 总功能点:约60个(砍掉73%)
团队配置: 后端3人、前端2人、测试1人
第二期(1.5-2个月): 体验完善
服务扩展: 5. IM独立服务 - 从订单服务拆分,支持图片、语音 6. 健康管理服务(简化版) - 护理日志、基础健康档案 7. 营销服务(简化版) - 优惠券(无叠加)、基础积分
功能增强:
- 订单服务:位置追踪、评价
- 技师服务:在线状态、接单管理
- 用户服务:实名认证、家庭成员
交付目标:
- ✅ 完整IM体验
- ✅ 护理日志记录
- ✅ 基础营销能力
- 🎯 总功能点:约120个
第三期(2-3个月): 运营增长
服务完善: 8. 商城服务 - 套餐购买、商品销售 9. 运营管理服务 - 后台管理、数据报表
功能增强:
- 营销服务:会员体系、红包、签到
- 健康管理:AI体检分析
- 技师服务:老带新、师徒关系
- 支付服务:分账、提现、支付宝
交付目标:
- ✅ 完整运营能力
- ✅ 商城业务闭环
- ✅ 后台管理系统
- 🎯 总功能点:约200个
第四期(按需迭代): 智能化升级
高级功能:
- AI智能推荐
- 物联网设备集成
- 拼团、秒杀等复杂活动
- 完整财务报表
分期对比:
| 方案 | 第一期周期 | 服务数量 | 功能点 | 风险 | 推荐度 |
|---|---|---|---|---|---|
| 原方案 | 3-4个月 | 5个完整服务 | 100+ | 高(战线长,难验证) | ⚠️ 不推荐 |
| 优化方案 | 1.5-2个月 | 4个简化服务 | 60 | 低(快速上线) | ✅ 强烈推荐 |
服务器成本(月)
开发环境:
- ECS 4核8G × 3台 = 1500元
- MySQL/Redis/RabbitMQ = 800元
- 小计: 2300元/月
生产环境:
- ECS 8核16G × 6台 (10服务+基础设施) = 6000元
- RDS MySQL主从 = 1500元
- Redis集群 = 1200元
- MongoDB = 800元
- RabbitMQ集群 = 1000元
- Elasticsearch = 1500元
- 负载均衡SLB = 500元
- OSS对象存储 = 300元
- CDN流量 = 500元
- 小计: 13,300元/月
第三方服务成本(月):
- 高德地图API = 500元
- 极光推送 = 300元
- 阿里云短信 = 500元
- 实名认证 = 300元
- 通义千问API = 800元
- 支付手续费(按交易额) = 动态
- 小计: 2,400元/月
总月成本: 约 18,000元/月
22.5 风险控制
| 风险类型 | 应对措施 |
|---|---|
| 技术风险 | 核心技术采用成熟方案(Spring Cloud Alibaba),降低技术风险 |
| 性能风险 | 关键路径(订单/支付)压测,Redis缓存,异步处理 |
| 数据风险 | 主从备份,定期备份,异地容灾 |
| 安全风险 | 数据加密、权限控制、WAF防护、漏洞扫描 |
| 人员风险 | 代码标准、文档完善、知识传承 |
22.6 关键指标监控
业务指标:
- DAU(日活)、订单量、GMV
- 支付成功率、订单完成率
- 技师在线率、接单响应时间
- 用户复购率、技师留存率
技术指标:
- API响应时间(P95 < 1秒)
- 服务可用性(>99.9%)
- 错误率(<0.1%)
- 数据库慢查询(< 1秒)
22.7 后续优化方向
第一阶段(上线前):
- 完成核心功能开发
- 压力测试和性能优化
- 安全测试和漏洞修复
第二阶段(上线后3个月):
- 数据驱动优化(基于埋点数据)
- 根据用户反馈迭代
- 性能监控和容量规划
第三阶段(上线后6个月):
- AI能力增强(智能推荐、智能客服)
- 多城市扩展
- 生态合作(保险、医院)
二十四、参考资料
文档版本: v3.3 (新增服务边界约束章节) 最后更新: 2025-12-03 架构设计: 微服务架构最佳实践 + 架构复盘优化 服务规模: 10个微服务,支撑225个功能点 技术栈: Spring Boot 3.2 + Spring Cloud Alibaba + JDK 17 维护者: 麦瓣健康技术团队
v3.3 更新内容 (2025-12-03):
- ✅ 新增"第三章:服务边界与依赖约束"
- ✅ 明确微服务 jar 依赖隔离原则
- ✅ 规范服务间通信方式(HTTP/gRPC、消息队列、事件总线)
- ✅ 定义公共能力下沉策略(maiban-common 基础库)
- ✅ 完善依赖检测与验证机制(本地检查 + CI/CD 验证)
- ✅ 统一调整后续所有章节编号(章节总数从23章增至24章)
v3.2 更新内容 (2025-11-07):
- ✅ 修复章节编号重复问题(第892行"九"改为"十")
- ✅ 统一调整后续所有章节编号(十→十一,十一→十二,...,二十二→二十三)
- ✅ 更新章节交叉引用(架构风险提示指向第二十一章)
- ✅ 移除maiban-mbg微服务模块(仅保留作为开发工具)
v3.1 更新内容 (2025-10-24):
- ✅ 新增"1.3 基础设施服务端口总览"章节
- ✅ 补充完整的基础设施服务端口配置表(MySQL、Redis、Nacos等8个服务)
- ✅ 添加服务访问地址快速参考表
- ✅ 修正搜索服务端口配置(8086 → 8089)
- ✅ 增加安全提示说明
v3.0 更新内容 (2025-10-18):
- ✅ 补充Redis缓存策略详解(防穿透/击穿/雪崩)
- ✅ 补充降级容灾方案(限流、熔断、容灾演练)
- ✅ 补充安全设计方案(防刷、加密、权限)
- ✅ 优化分布式事务方案(优先最终一致性)
- ✅ 优化IM架构设计(支持水平扩展)
- ✅ 调整MVP分期建议(第一期2个月上线)
- ✅ 新增架构风险评估章节
- ✅ 新增性能优化和成本优化建议
