1. 项目背景与核心目标
"苍穹外卖-day02"是一个典型的外卖配送系统开发项目中的第二天任务模块。作为连续开发日志的一部分,这个阶段通常聚焦在系统核心功能的实现与优化上。根据行业惯例,外卖系统开发的第二天往往会涉及以下关键任务:
- 用户端功能完善(如购物车逻辑、优惠券系统)
- 骑手端基础功能搭建(接单/导航模块)
- 后台管理系统开发(订单处理看板)
- 基础架构优化(数据库索引、API响应速度)
实际开发中,第二天往往是系统从原型转向可用版本的关键转折点,需要处理好业务逻辑与技术实现的平衡。
2. 技术架构解析
2.1 主流技术选型方案
现代外卖系统通常采用微服务架构,day02阶段建议的技术栈组合:
| 技术层级 | 推荐方案 | 替代方案 | 选择理由 |
|---|---|---|---|
| 前端框架 | Vue3 + Vant | React + Ant Design | 组件库成熟,开发效率高 |
| 后端语言 | Java17 | Go1.20 | 生态完善,人才储备充足 |
| 微服务框架 | Spring Cloud Alibaba | Dubbo | 阿里系组件集成度高 |
| 数据库 | MySQL8.0 + Redis7 | PostgreSQL + MongoDB | 事务支持完善,缓存性能优异 |
| 消息队列 | RocketMQ | Kafka | 阿里云原生支持,延迟更低 |
2.2 核心服务拆分
在day02阶段建议完成以下微服务的基础搭建:
订单服务(Order-Service)
- 处理下单/支付/状态变更
- 需实现本地事务+消息表方案
- 关键表结构:
CREATE TABLE `orders` ( `id` bigint NOT NULL AUTO_INCREMENT, `user_id` bigint NOT NULL COMMENT '用户ID', `total_amount` decimal(10,2) NOT NULL COMMENT '订单总额', `status` tinyint NOT NULL DEFAULT '0' COMMENT '0待支付 1已支付 2已接单...', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_user_status` (`user_id`,`status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
配送服务(Delivery-Service)
- 骑手调度算法
- 实时位置追踪
- 集成高德/百度地图API
商户服务(Merchant-Service)
- 菜品管理
- 营业统计
- 接单处理
3. 关键功能实现
3.1 购物车模块开发
核心逻辑流程图:
- 用户添加商品 → 2. 校验库存 → 3. 计算优惠 → 4. 持久化存储
代码实现要点:
// 购物车项DTO @Data public class CartItemDTO { private Long skuId; // 商品规格ID private Integer quantity; // 购买数量 private Boolean selected; // 是否选中结算 } // 购物车服务接口 public interface CartService { // 添加商品到购物车 Result<Void> addToCart(Long userId, CartItemDTO item); // 获取完整购物车 Result<CartVO> getFullCart(Long userId); }性能优化技巧:
- 使用Redis Hash结构存储购物车数据
- 本地缓存商品基本信息减少DB查询
- 批量查询优惠信息避免多次RPC调用
3.2 订单创建流程
分布式事务方案对比:
| 方案 | 适用场景 | day02推荐度 | 原因 |
|---|---|---|---|
| 本地消息表 | 中等并发量 | ★★★★★ | 实现简单,无需额外组件 |
| Seata AT | 复杂事务链 | ★★★☆☆ | 学习成本较高 |
| TCC | 高一致性要求 | ★★☆☆☆ | 开发工作量过大 |
实操示例(本地消息表方案):
@Transactional public Result<OrderVO> createOrder(OrderCreateDTO dto) { // 1. 校验商品库存 checkInventory(dto.getItems()); // 2. 生成订单(主事务) Order order = buildOrder(dto); orderMapper.insert(order); // 3. 扣减库存(本地消息) InventoryMessage message = new InventoryMessage(order.getId(), dto.getItems()); messageMapper.insert(message); // 4. 发送MQ消息(异步任务处理) sendInventoryMessage(message); return Result.success(convertToVO(order)); }4. 典型问题排查指南
4.1 订单重复创建问题
现象: 用户快速点击下单按钮时生成多个相同订单
解决方案:
- 前端防抖处理(300ms间隔)
- 后端幂等控制:
@PostMapping("/create") public Result<OrderVO> createOrder( @RequestBody OrderCreateDTO dto, @RequestHeader("X-Request-Id") String requestId) { // 基于requestId实现幂等 if (redisTemplate.opsForValue().setIfAbsent( "order:req:" + requestId, "1", 5, TimeUnit.MINUTES)) { return orderService.createOrder(dto); } throw new BusinessException("请勿重复提交订单"); }
4.2 地理位置漂移问题
原因分析: 不同地图API的坐标系差异:
- 高德:GCJ-02
- 百度:BD-09
- GPS设备:WGS-84
坐标转换工具类:
public class CoordinateUtils { private static final double X_PI = Math.PI * 3000.0 / 180.0; // GCJ-02转BD-09 public static double[] gcjToBd(double lat, double lng) { double z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * X_PI); double theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * X_PI); return new double[]{ z * Math.sin(theta) + 0.006, z * Math.cos(theta) + 0.0065 }; } }5. 性能优化实践
5.1 数据库优化
索引优化方案:
-- 订单表常用查询场景 ALTER TABLE orders ADD INDEX idx_user_time (user_id, create_time DESC); ALTER TABLE order_items ADD INDEX idx_order_sku (order_id, sku_id); -- 慢查询监控(day02建议配置) SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 1;连接池配置建议:
# application.yml spring: datasource: hikari: maximum-pool-size: 20 minimum-idle: 5 idle-timeout: 30000 max-lifetime: 1800000 connection-timeout: 30005.2 缓存策略设计
多级缓存架构:
本地缓存(Caffeine):高频访问的基础数据
@Bean public CacheManager cacheManager() { CaffeineCacheManager manager = new CaffeineCacheManager(); manager.setCaffeine(Caffeine.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) .maximumSize(1000)); return manager; }Redis缓存:业务数据缓存
@Cacheable(value = "menu", key = "#shopId") public List<DishVO> getShopMenu(Long shopId) { // DB查询逻辑 }CDN缓存:静态资源加速
6. 安全防护措施
6.1 常见攻击防护
XSS防护方案:
@Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.headers() .xssProtection() .and() .contentSecurityPolicy("script-src 'self'"); } }SQL注入防护:
- 强制使用MyBatis参数绑定
- 禁止字符串拼接SQL
- 定期执行SQL注入扫描
6.2 敏感数据保护
数据脱敏处理:
public class DataMaskUtil { // 手机号脱敏 public static String maskPhone(String phone) { if (StringUtils.isEmpty(phone)) return ""; return phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"); } // 地址脱敏 public static String maskAddress(String address) { if (StringUtils.isEmpty(address)) return ""; return address.substring(0, 6) + "******"; } }7. 监控与报警体系
7.1 基础监控配置
Spring Boot Actuator集成:
management: endpoints: web: exposure: include: health,info,metrics,prometheus metrics: export: prometheus: enabled: true关键监控指标:
- 订单创建TPS
- 平均响应时间
- 错误率
- 数据库连接池使用率
7.2 业务监控设计
自定义指标采集:
@RestController public class OrderController { private final Counter orderCounter; public OrderController(MeterRegistry registry) { this.orderCounter = registry.counter("order.create.count"); } @PostMapping("/order") public Result createOrder() { orderCounter.increment(); // 业务逻辑 } }报警规则示例:
- alert: HighErrorRate expr: rate(http_server_requests_errors_total[1m]) > 0.05 for: 5m labels: severity: critical annotations: summary: "High error rate on {{ $labels.instance }}"8. 持续集成方案
8.1 GitLab CI配置
.gitlab-ci.yml示例:
stages: - build - test - deploy build-job: stage: build image: maven:3.8-jdk-11 script: - mvn clean package -DskipTests artifacts: paths: - target/*.jar test-job: stage: test image: maven:3.8-jdk-11 script: - mvn test needs: ["build-job"] deploy-job: stage: deploy image: alpine/k8s:1.22 script: - kubectl apply -f k8s/deployment.yaml only: - master8.2 代码质量门禁
SonarQube配置:
# sonar-project.properties sonar.projectKey=sky-takeaway sonar.projectName=苍穹外卖系统 sonar.java.binaries=target/classes sonar.sources=src/main/java sonar.test.sources=src/test/java sonar.exclusions=**/model/**,**/config/**9. 压测方案设计
9.1 JMeter测试计划
关键测试场景:
- 用户登录并发测试
- 购物车添加压力测试
- 订单创建峰值测试
线程组配置建议:
- 阶梯式加压:50 → 100 → 200线程
- 持续时间:每个阶梯维持5分钟
- 思考时间:300-500ms随机
9.2 性能瓶颈分析
Arthas诊断命令:
# 查看方法调用耗时 watch com.example.service.OrderService createOrder '{params,returnObj}' -x 3 -b # 监控JVM内存 dashboard -i 5000 # 追踪慢SQL trace javax.sql.DataSource * '#cost>100'10. 移动端适配要点
10.1 响应式布局方案
CSS媒体查询示例:
/* 小屏设备 */ @media (max-width: 576px) { .dish-card { width: 100%; margin-bottom: 10px; } .cart-panel { position: fixed; bottom: 0; } }10.2 手势操作优化
触摸事件处理:
// 滑动删除购物车项 let startX = 0; cartItem.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; }); cartItem.addEventListener('touchmove', (e) => { const diff = e.touches[0].clientX - startX; if (diff < -50) { this.showDeleteButton(); } });11. 项目进度管理
11.1 每日站会要点
day02重点检查项:
- [ ] 订单创建流程联调完成
- [ ] 购物车Redis缓存实现
- [ ] 基础监控系统搭建
- [ ] 数据库索引优化验证
11.2 风险控制表
| 风险项 | 可能性 | 影响程度 | 应对措施 |
|---|---|---|---|
| 第三方支付接口延迟 | 中 | 高 | 添加异步回调+轮询补偿机制 |
| 地图API配额不足 | 低 | 中 | 申请提高配额+添加备用服务商 |
| 数据库连接泄漏 | 高 | 严重 | 引入Druid监控+定期连接检查 |
12. 团队协作规范
12.1 Git分支策略
day02推荐流程:
- 从master拉取feature/day02基础分支
- 开发人员基于feature/day02创建个人分支
git checkout -b feature/day02-order-module - 每日下班前合并到feature/day02分支
- day02结束时发起MR到master
12.2 代码审查清单
重点检查项:
- 是否使用魔法数字
- 有无完善的单元测试
- 敏感信息是否硬编码
- 日志输出是否规范
- 异常处理是否完备
13. 技术债务管理
13.1 已知待优化项
day02技术债务登记:
- 订单状态机需要重构(当前if-else实现)
- 地理围栏查询性能待优化
- 优惠券计算未做缓存
13.2 债务跟踪方案
JIRA看板配置:
- 新建"Technical Debt"项目
- 设置优先级(Blocker/Critical/Major)
- 每周专项会议讨论解决方案
14. 用户反馈收集
14.1 埋点设计方案
关键埋点事件:
// 购物车添加事件 trackEvent('cart_add', { sku_id: '123', quantity: 2, price: 38.00 }); // 订单创建成功事件 trackEvent('order_create', { order_id: 'ORD202308011234', amount: 89.00, payment_method: 'alipay' });14.2 反馈分析维度
day02重点关注数据:
- 购物车放弃率
- 订单创建平均时长
- 支付成功率
- 错误集中页面
15. 后续演进规划
15.1 day03重点任务
- 支付系统集成(微信/支付宝)
- 订单状态机重构
- 智能调度算法原型
- 压力测试报告分析
15.2 技术预研方向
- 地理围栏优化:R树索引
- 推荐系统:协同过滤算法
- 流量治理:Sentinel降级规则
- 数据同步:Canal+ES方案
在实际开发中,day02的顺利完成对整个项目进度至关重要。我们团队在实施过程中发现,尽早建立完善的监控体系(特别是业务指标监控)能大幅降低后期运维成本。另外建议在day02结束时进行一次完整的API文档同步更新,这对后续前端联调工作会有很大帮助。