1. 项目背景与核心需求
网上订餐系统已经成为现代餐饮行业数字化转型的基础设施。作为连接消费者与商家的关键纽带,一个高效的订餐管理系统需要同时满足多终端访问、实时订单处理、库存动态更新等核心需求。我们开发的这套系统采用Java+SSM作为后端主力框架,结合Flask实现特定微服务,形成了完整的技术栈解决方案。
这个系统最显著的特点是采用了混合架构设计。SSM框架(Spring+SpringMVC+MyBatis)提供了稳定的基础服务能力,而Flask则以其轻量级特性负责处理需要快速迭代的业务模块。这种架构选择既保证了系统核心业务的稳定性,又为特定功能模块的灵活扩展提供了可能。
提示:混合架构的关键在于明确服务边界。我们将用户管理、订单处理等核心业务放在SSM端,而像促销活动、推荐算法这类频繁变更的功能则由Flask微服务实现。
2. 技术架构详解
2.1 后端技术选型
SSM框架组合构成了系统的主干:
- Spring 5.x:提供IoC容器和AOP支持,管理各类Bean的生命周期
- SpringMVC:采用RESTful风格设计API接口,前后端分离
- MyBatis 3.x:配合PageHelper插件实现高效数据分页
Flask微服务主要承担以下职责:
- 实时促销计算引擎
- 用户行为分析服务
- 智能推荐系统
// 典型的SSM控制器示例 @RestController @RequestMapping("/api/order") public class OrderController { @Autowired private OrderService orderService; @PostMapping public ResponseResult createOrder(@Valid @RequestBody OrderDTO dto) { return orderService.createOrder(dto); } }2.2 数据库设计
MySQL 8.0作为主数据库,关键表结构设计如下:
| 表名 | 核心字段 | 索引设计 |
|---|---|---|
| t_user | user_id(PK), username, password_hash, phone | phone(unique) |
| t_restaurant | restaurant_id(PK), name, location_geo | location_geo(spatial) |
| t_food | food_id(PK), restaurant_id(FK), price | restaurant_id(index) |
| t_order | order_id(PK), user_id(FK), status | user_id(index), create_time(index) |
特别优化了订单表的读写性能:
- 采用垂直分表将订单主表与订单明细分离
- 热数据使用Redis缓存,减少数据库压力
- 历史订单定期归档到MongoDB
3. 核心功能实现
3.1 多级缓存设计
系统采用三级缓存策略提升响应速度:
- 本地缓存:使用Caffeine缓存餐厅菜单等变化频率低的数据
- 分布式缓存:Redis集群存储用户会话和热门商品
- 数据库缓存:MySQL查询缓存配合适当的索引策略
# Flask中的缓存装饰器示例 from flask_caching import Cache cache = Cache(config={'CACHE_TYPE': 'RedisCluster'}) @app.route('/promotion/<int:restaurant_id>') @cache.cached(timeout=300) def get_promotions(restaurant_id): # 促销计算逻辑3.2 订单状态机实现
订单生命周期管理采用状态模式:
public interface OrderState { void confirm(OrderContext context); void cancel(OrderContext context); void complete(OrderContext context); } // 具体状态实现 public class PendingState implements OrderState { @Override public void confirm(OrderContext context) { context.setState(new ConfirmedState()); // 触发支付流程 } }状态转换规则:
- 待确认 → (确认) → 已确认
- 待确认 → (取消) → 已取消
- 已确认 → (完成) → 已完成
- 已确认 → (超时) → 已取消
4. 安全与性能优化
4.1 安全防护措施
- 认证授权:JWT+Spring Security实现RBAC
- 数据安全:
- 敏感字段AES加密存储
- SQL注入防护:MyBatis使用#{}占位符
- XSS防护:Jackson全局转义HTML标签
- 交易安全:
- 支付密码二次验证
- 交易流水号防重放
4.2 性能调优实践
通过压测发现的典型问题及解决方案:
N+1查询问题:
- 现象:获取订单列表时频繁查询用户信息
- 解决:MyBatis的 标签实现关联查询
缓存穿透:
- 现象:大量请求不存在的餐厅ID
- 解决:布隆过滤器前置校验
分布式锁竞争:
- 现象:秒杀活动时库存扣减冲突
- 解决:Redis+Lua脚本实现原子操作
-- 库存扣减Lua脚本 local stock = tonumber(redis.call('GET', KEYS[1])) if stock > 0 then redis.call('DECR', KEYS[1]) return 1 end return 05. 部署架构与监控
5.1 容器化部署方案
系统采用Docker Compose编排服务:
version: '3' services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} redis: image: redis:6.2 ssm-app: build: ./ssm ports: - "8080:8080" flask-app: build: ./flask ports: - "5000:5000"5.2 监控指标设计
Prometheus采集的关键指标:
- 应用层:QPS、响应时间、错误率
- 系统层:CPU/Memory使用率、GC情况
- 业务层:订单创建成功率、支付超时率
Grafana配置了三种级别的告警:
- Warning:响应时间>500ms
- Error:错误率>1%
- Critical:服务不可用
6. 典型问题排查实录
6.1 跨服务事务问题
现象:用户下单后积分未正常增加 排查过程:
- 检查订单服务日志 - 订单创建成功
- 检查积分服务日志 - 未收到请求
- 检查RabbitMQ - 消息堆积
- 定位到网络ACL规则阻止了5672端口
解决方案:
- 增加本地事务表记录操作状态
- 实现补偿任务定期同步状态
- 添加跨服务事务监控看板
6.2 缓存一致性问题
现象:用户看到的价格与实际不符 根本原因:
- 商品改价后未及时清除缓存
- 缓存过期时间设置过长(30分钟)
最终方案:
- 采用"先更新DB再删除缓存"策略
- 设置合理的缓存过期时间(5分钟)
- 关键操作增加缓存刷新机制
7. 扩展与演进方向
当前系统已经支持的功能:
- 多餐厅管理
- 智能推荐
- 促销计算
- 第三方支付对接
下一步规划:
- 引入Elasticsearch实现菜品搜索
- 使用Kafka重构订单事件流
- 尝试Service Mesh治理跨服务调用
- 开发小程序端提升用户体验
在实际开发中,我们发现Flask和SSM的版本兼容性需要特别注意。建议建立完善的接口契约测试,确保服务间通信的稳定性。同时,对于需要强一致性的业务场景,建议仍然放在SSM主系统中实现。