简历上出现“苍穹外卖”的项目已经不算新鲜事了,但我面试候选人时最常问的其实只有两句话:如果用户同时点了 5 次下单,你的系统会创建出几笔订单?如果支付回调晚到了 10 秒钟,订单状态到底该听谁的?能把这两个问题说得滴水不漏的人,比能背出一长串框架名字的人少太多了。苍穹外卖这个项目之所以值得从头到尾做一遍,是因为它看起来只是一个“点餐加配送”的业务系统,实际却把订单、支付、并发、缓存、权限和定时任务全部串在了一起。这篇复盘既是写给自己,也是写给正在拿这个项目练手、准备用它当求职作品的同学。
1. 苍穹外卖的需求边界:不是抄美团,而是画清楚外卖闭环
1.1 三类角色加上配送端,才叫真正的业务闭环
很多刚接触苍穹外卖的人,第一反应是把美团 App 的界面拆一遍:首页要有轮播图、分类、店铺列表,详情页要有评价、优惠、起送价。但照着这些功能做下去,很容易变成一个静态页面展示系统,后端只是照着页面堆 CRUD 接口。
我整理需求时先做了一件很朴素的事:把参与这笔外卖生意的人都列出来。最低限度要有四类使用方:
- 用户端:在小程序或 H5 上浏览菜品、加购物车、下单、支付、查看订单、申请售后。
- 商家端:维护门店信息、菜品和库存,接收新订单,执行接单、出餐、配货等操作。
- 配送端:骑手查看可抢订单、抢单、更新取货和送达状态。
- 平台管理端:对用户、商家、订单、活动、问题反馈做统一运营和管理。
把角色列出来后,主流程自然也就清楚了:商家上架菜品,用户浏览下单并完成支付,商家接单备餐,骑手取餐配送,最后用户确认收货。苍穹外卖真正难的地方,并不在于界面多好看,而在于这个流程里的每一个状态跳转都要稳定可靠。用户端下单之后商家能不能立即看到、商家接单之后骑手能不能及时抢到、支付结果和订单状态在并发下会不会错乱,这些才是项目核心。
1.2 MVP 范围怎么定,砍需求的标准是什么
做苍穹外卖这类项目时,最大的坑是“什么都想要”。我见过有人第一版就把拼团、秒杀、好友代付、骑手实时轨迹全部规划进去,结果数据库设计了二十多张表,最后连完整跑通一单的能力都没有。
我在第一个版本里给自己定了三条硬性原则:
- 能跑通完整交易闭环的功能必须最先做,例如菜品、购物车、订单、支付、配送状态。
- 和钱相关的能力必须做完整,例如支付回调、订单超时关闭、退款、对账。
- 只带来流量不直接产生交易结果的功能可以往后放,例如社区种草、直播探店、复杂营销玩法。
按这个标准,第一版苍穹外卖的功能清单聚焦在:用户地址管理、菜品分类与检索、购物车、下单支付、商家接单、骑手抢单配送、订单详情、售后申请、后台数据看板。优惠券和秒杀这类功能虽然我也很想做,但它们的复杂度集中在“防止被薅羊毛”和“防止超发”,不是核心流程必须依赖的,于是被我统一挪到了二期。
需求边界一旦划清楚,后面数据库怎么建、定时任务开几个、接口如何拆,都会变得顺理成章。先做完整闭环,再谈横向扩展,这是我在这个项目上得到的第一条经验。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型复盘:为什么我放弃了微服务架构
2.1 单体多模块起步,比一步拆成微服务省心太多
决定技术栈之前,我先问了自己一个问题:这个项目的用户量到底有没有到必须水平扩展的程度?答案很清醒:没有。
所以我最终选择了单体应用 + 模块化拆分的方案。也就是说,代码在工程上是拆开的,比如 user 模块、product 模块、order 模块、payment 模块、dispatch 模块、stats 模块,但最终被打成一个 Java 工程、部署在同一组实例上。
这样做的理由非常实际。微信小程序、商家后台、骑手 App 共用同一套后端接口,如果一开始就把订单服务、支付服务、用户服务拆成三个独立进程,光是跨服务调用的鉴权、分布式事务、日志追踪就足够把开发进度拖慢一倍。而单体多模块依然可以保持清晰的业务边界,未来万一真的需要把支付或订单模块独立部署,代码层面的迁移成本也会比“所有逻辑揉在一个 service 里”低很多。
2.2 核心组件清单与选型逻辑
苍穹外卖这种业务,最核心的基础设施其实不需要太多。
| 组件 | 用途 | 我选择它的原因 |
|---|---|---|
| MySQL 8.0 | 存储用户、订单、菜品、商家等核心数据 | 关系型数据、事务能力强,InnoDB 支持行锁和条件更新,适合订单状态流转 |
| Redis | 验证码缓存、登录态、菜品缓存、接口幂等、抢单临时状态 | 性能高,支持 SETNX、Lua 脚本,能解决高并发下的重复与原子性场景 |
| RabbitMQ | 订单超时延迟消息、支付结果异步通知、商家接单推送 | 延迟队列能解决“15 分钟未支付自动关单”,消息确认机制保证不丢单 |
| XXL-Job 或 Spri |
