1. 项目背景与核心定位
"苍穹外卖"这个命名本身就透露着宏大愿景——它不是一个简单的外卖下单工具,而是试图重构餐饮行业的数字化生态。从技术架构来看,这个项目明显采用了"微服务+中台"的现代架构思想,DAY1-3的开发周期安排也体现了互联网产品典型的敏捷开发节奏。
我参与过多个外卖平台的从零搭建,深知前三天要完成的核心基建包括:
- 用户鉴权体系的建立(涉及JWT/OAuth2选型)
- 餐厅/菜品数据模型的构建(关系到后续扩展性)
- 基础订单流程的实现(状态机设计是关键)
2. 技术栈选型解析
2.1 后端架构设计
现代外卖平台普遍采用的技术组合:
// 典型Spring Cloud微服务架构示例 @SpringBootApplication @EnableDiscoveryClient public class OrderService { public static void main(String[] args) { SpringApplication.run(OrderService.class, args); } }数据库选型建议:
- 主业务库:MySQL 8.0(事务型操作)
- 餐厅/菜单:MongoDB(非结构化数据友好)
- 缓存层:Redis 6.x+(支持Stream做消息队列)
2.2 前端技术考量
移动端优先策略下需要关注:
- Flutter跨平台方案(节省30%开发成本)
- 小程序WebView混合开发(快速覆盖微信生态)
- H5餐厅页面的SSR渲染(SEO优化关键)
3. 核心业务模块实现
3.1 用户认证系统
JWT实现中的安全要点:
// 增强版JWT生成逻辑 String token = Jwts.builder() .setSubject(username) .setExpiration(new Date(System.currentTimeMillis() + 3600000)) .signWith(SignatureAlgorithm.HS512, "your-256-bit-secret".getBytes()) .claim("role", "customer") // 自定义声明 .compact();关键安全措施:必须配置HTTPS、设置合理的token过期时间、实现refresh token轮换机制
3.2 餐厅数据建模
MongoDB文档设计示例:
{ "_id": ObjectId("5f8d..."), "name": "川味坊", "cuisine": ["川菜", "火锅"], "delivery": { "min_order": 20, "fee": 5, "time": "30-45分钟" }, "menu": [ { "category": "主菜", "items": [ { "name": "水煮鱼", "price": 68, "spicy_level": 3 } ] } ] }3.3 订单状态机设计
使用状态模式实现订单流转:
public interface OrderState { void confirm(OrderContext context); void cancel(OrderContext context); void deliver(OrderContext context); } // 具体状态实现 public class PaidState implements OrderState { @Override public void deliver(OrderContext context) { context.setState(new DeliveringState()); // 触发配送系统通知... } }状态转换示意图:
[待支付] → [已支付] → [配送中] → [已完成] ↓ ↓ [已取消] ←──┘4. 性能优化实战技巧
4.1 高并发下单设计
采用分级库存策略:
- Redis缓存库存(应对秒杀场景)
- 数据库真实库存(最终一致性)
- 本地缓存库存(减少Redis压力)
分布式锁实现示例:
public boolean tryLock(String lockKey, long expireSeconds) { return redisTemplate.opsForValue() .setIfAbsent(lockKey, "locked", expireSeconds, TimeUnit.SECONDS); }4.2 智能配送算法
基于GeoHash的餐厅匹配:
import geohash def find_nearby_restaurants(user_loc, radius_km): precision = 6 # 约1.2km精度 neighbor_hashes = geohash.expand(geohash.encode(*user_loc, precision)) return Restaurant.objects.filter(geo_hash__in=neighbor_hashes)5. 踩坑实录与解决方案
5.1 支付超时陷阱
典型问题场景:
- 用户支付成功但系统未收到回调
- 第三方支付延迟导致订单状态不一致
我们的解决方案:
- 建立支付流水表记录所有请求
- 定时任务补偿查询(间隔5/15/30分钟)
- 人工干预通道(后台管理系统)
5.2 缓存雪崩预防
多级缓存策略:
- 本地缓存(Caffeine):5秒过期
- Redis集群:30分钟过期+随机抖动
- 数据库:最终数据源
缓存击穿处理:
public Product getProduct(String id) { // 布隆过滤器前置校验 if (!bloomFilter.mightContain(id)) { return null; } // 后续查询逻辑... }6. 监控体系搭建
6.1 业务指标监控
核心Metrics配置:
- 订单成功率(>99.5%)
- 平均响应时间(<500ms)
- 支付回调延迟(<3s)
Prometheus配置示例:
- job_name: 'order_service' metrics_path: '/actuator/prometheus' scrape_interval: 15s6.2 分布式追踪
SkyWalking的OAL脚本:
order_success_rate = from(Service.latency) .filter(status == 'success') .percent();7. 安全防护体系
7.1 常见攻击防御
SQL注入防护:
@Repository public interface OrderRepository extends JpaRepository<Order, Long> { @Query("SELECT o FROM Order o WHERE o.userId = :userId") // 使用参数化查询 List<Order> findByUser(@Param("userId") String userId); }7.2 数据加密方案
敏感字段加密:
@Convert(converter = CryptoConverter.class) private String phoneNumber; // 自定义转换器 public class CryptoConverter implements AttributeConverter<String, String> { private static final String KEY = "your-256-bit-key"; public String convertToDatabaseColumn(String attribute) { return AES.encrypt(attribute, KEY); } }经过多个外卖项目的实战验证,前三天的开发质量直接决定了后续迭代的天花板。特别是在领域模型设计阶段,一定要预留足够的扩展字段,比如我们在餐厅模型中就预埋了"commercial_type"字段,后期顺利接入了企业订餐业务而无需重构。另一个深刻教训是关于分布式事务的选择——初期为了快速上线使用了本地消息表,当日均订单突破10万时出现了严重的性能瓶颈,后来不得不迁移到Seata框架,这个改造过程耗费了整整两周。