Java实战篇06-外卖配送系统(Spring Cloud Alibaba)
本文基于Spring Cloud Alibaba技术栈,详细介绍了如何构建一个功能完整的外卖配送系统。文章首先分析了外卖系统的核心业务流程和角色,然后设计了微服务架构方案,重点讲解了Nacos服务注册、Sentinel流量控制、Seata分布式事务等关键组件。通过环境准备、项目结构搭建和代码示例,展示了从零开始实现系统的完整过程。文章适合具备Spring Boot基础的开发者,通过典型的电商场景实

👋 大家好,欢迎来到我的技术博客!
💻 作为一名热爱 Java 与软件开发的程序员,我始终相信:清晰的逻辑 + 持续的积累 = 稳健的成长。
📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。
🎯 本文将围绕一个常见的开发话题展开,希望能为你带来一些启发或实用的参考。
🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!
文章目录
- 🍔 Java 实战:外卖配送系统(Spring Cloud Alibaba)
🍔 Java 实战:外卖配送系统(Spring Cloud Alibaba)
在当今快节奏的生活中,外卖平台已成为人们日常饮食的重要组成部分。从美团、饿了么到达达、闪送,背后都离不开一套高效、稳定、可扩展的分布式系统架构。
本文将带你使用 Spring Cloud Alibaba 技术栈,从零构建一个功能完整的外卖配送系统。我们将深入讲解:
- 🛵 配送流程设计
- 🏗️ 微服务拆分与架构
- 🧩 Nacos 服务注册与配置中心
- 🌐 OpenFeign 服务调用
- 📊 Sentinel 流量控制与熔断
- 📦 Seata 分布式事务
- 📈 Prometheus + Grafana 监控
- 💬 WebSocket 实时订单状态推送
💡 适合读者:具备 Spring Boot 基础的 Java 开发者,希望通过实战掌握 Spring Cloud Alibaba 在真实业务场景中的应用。
🍕 外卖系统核心流程
一个典型的外卖配送系统包含以下几个核心角色:
- 👤 用户:下单、支付、查看订单状态
- 🍳 商家:接单、准备餐品
- 🚴 配送员:接单、取餐、送达
- 🧠 系统:订单调度、路径规划、状态管理
🔄 核心业务流程图
🏗️ 系统架构设计
我们采用 微服务架构,将系统拆分为多个独立服务,通过 Spring Cloud Alibaba 实现服务治理。
📐 整体架构图
- Nacos:服务注册与发现 + 配置中心
- Sentinel:流量控制、熔断降级
- Seata:分布式事务(AT 模式)
- Prometheus + Grafana:系统监控
- WebSocket:实时推送订单状态
🔗 推荐阅读:
🛠️ 环境准备
1. 启动 Nacos Server
# 下载 Nacos 2.4.1
wget https://github.com/alibaba/nacos/releases/download/2.4.1/nacos-server-2.4.1.tar.gz
tar -zxvf nacos-server-2.4.1.tar.gz
cd nacos/bin
# 单机模式启动
sh startup.sh -m standalone
访问:http://localhost:8848/nacos
默认账号:nacos / nacos
2. 启动 Sentinel Dashboard
# 下载 Sentinel 控制台
wget https://github.com/alibaba/Sentinel/releases/download/1.8.8/sentinel-dashboard-1.8.8.jar
# 启动
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.8.jar
访问:http://localhost:8080
账号:sentinel / sentinel
3. 启动 Seata Server
# 下载 Seata
wget https://github.com/seata/seata/releases/download/v2.0.0/seata-server-2.0.0.tar.gz
tar -zxvf seata-server-2.0.0.tar.gz
# 启动
sh seata-server.sh -p 8091 -m db
⚠️ Seata 使用
db模式需提前配置 MySQL 数据库,并导入script/server/db/*.sql。
🏗️ 项目结构
外卖系统
├── gateway-api # API 网关
├── service-user # 用户服务
├── service-merchant # 商家服务
├── service-order # 订单服务
├── service-delivery # 配送服务
├── service-payment # 支付服务
└── common-utils # 公共工具类
🚀 创建父工程与依赖管理
pom.xml(父工程)
<properties>
<java.version>17</java.version>
<spring-boot.version>3.3.3</spring-boot.version>
<spring-cloud.version>2023.0.3</spring-cloud.version>
<spring-cloud-alibaba.version>2023.0.3.0</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
🧱 用户服务(service-user)
负责用户注册、登录、信息管理。
1. 引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
2. 配置文件 bootstrap.yml
spring:
application:
name: service-user
cloud:
nacos:
discovery:
server-addr: localhost:8848
config:
server-addr: localhost:8848
file-extension: yaml
3. User 实体
@Data
@TableName("t_user")
public class User {
private Long id;
private String username;
private String phone;
private String address;
private Integer type; // 1-普通用户, 2-配送员
}
4. UserController
@RestController
@RequestMapping("/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping("/{id}")
public Result<User> getUserById(@PathVariable Long id) {
return Result.success(userService.getById(id));
}
@PostMapping
public Result<User> createUser(@RequestBody User user) {
userService.save(user);
return Result.success(user);
}
}
🔗 MyBatis-Plus 官网:https://baomidou.com/
🍔 商家服务(service-merchant)
管理餐厅、菜品、接单状态。
1. MerchantController
@RestController
@RequestMapping("/merchants")
@RequiredArgsConstructor
public class MerchantController {
private final MerchantService merchantService;
@GetMapping("/{id}")
public Result<Merchant> getMerchant(@PathVariable Long id) {
return Result.success(merchantService.getById(id));
}
@PostMapping("/notify")
public Result<String> notifyOrderReady(@RequestBody OrderNotifyDTO dto) {
// 商家通知餐品已准备好
log.info("商家 {} 餐品已准备好,订单ID: {}", dto.getMerchantId(), dto.getOrderId());
return Result.success("通知成功");
}
}
📦 订单服务(service-order)
核心服务,负责订单创建、状态流转、调用支付与配送。
1. 订单状态机
public enum OrderStatus {
CREATED, // 已创建
PAID, // 已支付
CONFIRMED, // 商家已接单
READY, // 餐品已备好
DELIVERING, // 配送中
DELIVERED, // 已送达
CANCELLED // 已取消
}
2. Order 实体
@Data
@TableName("t_order")
public class Order {
private Long id;
private Long userId;
private Long merchantId;
private BigDecimal amount;
private String address;
private Integer status;
private LocalDateTime createTime;
}
3. 使用 OpenFeign 调用支付服务
@FeignClient(name = "service-payment")
public interface PaymentClient {
@PostMapping("/payments/create")
Result<Payment> createPayment(@RequestBody PaymentRequest request);
}
4. 创建订单(含分布式事务)
@Service
@RequiredArgsConstructor
public class OrderService {
private final PaymentClient paymentClient;
private final DeliveryClient deliveryClient;
@GlobalTransactional // Seata 分布式事务
public Result<Order> createOrder(OrderDTO orderDTO) {
// 1. 保存订单
Order order = new Order();
order.setUserId(orderDTO.getUserId());
order.setMerchantId(orderDTO.getMerchantId());
order.setAmount(orderDTO.getAmount());
order.setStatus(OrderStatus.CREATED.getCode());
save(order);
// 2. 调用支付服务
PaymentRequest payReq = new PaymentRequest(order.getId(), order.getAmount());
Result<Payment> payResult = paymentClient.createPayment(payReq);
if (!payResult.isSuccess()) {
throw new RuntimeException("支付失败");
}
// 3. 更新订单状态为已支付
order.setStatus(OrderStatus.PAID.getCode());
updateById(order);
// 4. 调用配送服务派单
DeliveryOrderDTO deliveryDTO = new DeliveryOrderDTO(order.getId(), order.getUserId(), order.getMerchantId());
Result<String> deliveryResult = deliveryClient.assignDelivery(deliveryDTO);
if (!deliveryResult.isSuccess()) {
throw new RuntimeException("派单失败");
}
// 5. 更新订单为配送中
order.setStatus(OrderStatus.DELIVERING.getCode());
updateById(order);
return Result.success(order);
}
}
✅
@GlobalTransactional注解开启 Seata 的 AT 模式分布式事务,保证订单、支付、配送三个操作的最终一致性。
🚴 配送服务(service-delivery)
负责配送员管理、订单调度、状态更新、实时推送。
1. 配送调度算法(简化版)
@Service
public class DispatchService {
public DeliveryOrder dispatch(Order order) {
// 简化逻辑:查找最近的空闲配送员
List<DeliveryOrder> availableCouriers = courierRepository.findAvailableCouriers();
DeliveryOrder bestCourier = null;
double minDistance = Double.MAX_VALUE;
for (DeliveryOrder courier : availableCouriers) {
double distance = calculateDistance(order.getMerchantAddress(), courier.getCurrentLocation());
if (distance < minDistance) {
minDistance = distance;
bestCourier = courier;
}
}
if (bestCourier != null) {
bestCourier.setOrderId(order.getId());
bestCourier.setStatus("ASSIGNED");
courierRepository.save(bestCourier);
}
return bestCourier;
}
private double calculateDistance(String addr1, String addr2) {
// 实际项目应调用高德/百度地图 API
return Math.random() * 10; // 模拟距离
}
}
🔗 高德地图 API:https://lbs.amap.com/
🔗 百度地图 API:https://lbsyun.baidu.com/
2. WebSocket 实时推送
@Component
@ServerEndpoint("/ws/delivery/{orderId}")
public class DeliveryWebSocket {
private static final Map<Long, Session> sessions = new ConcurrentHashMap<>();
@OnOpen
public void onOpen(@PathParam("orderId") Long orderId, Session session) {
sessions.put(orderId, session);
log.info("订单 {} 建立 WebSocket 连接", orderId);
}
@OnClose
public void onClose(@PathParam("orderId") Long orderId) {
sessions.remove(orderId);
log.info("订单 {} 断开连接", orderId);
}
public static void sendStatusUpdate(Long orderId, String status) {
Session session = sessions.get(orderId);
if (session != null && session.isOpen()) {
try {
session.getBasicRemote().sendText(status);
} catch (IOException e) {
log.error("推送失败", e);
}
}
}
}
3. 更新配送状态并推送
@PutMapping("/status")
public Result<String> updateStatus(@RequestBody DeliveryStatusDTO dto) {
DeliveryOrder order = deliveryOrderService.getById(dto.getOrderId());
order.setStatus(dto.getStatus());
deliveryOrderService.updateById(order);
// 实时推送
DeliveryWebSocket.sendStatusUpdate(dto.getOrderId(), dto.getStatus());
return Result.success("状态更新成功");
}
前端接收:
const ws = new WebSocket('ws://localhost:8080/ws/delivery/1001');
ws.onmessage = function(event) {
console.log('订单状态更新:', event.data);
// 更新 UI
};
🧾 支付服务(service-payment)
模拟支付流程。
@RestController
@RequestMapping("/payments")
public class PaymentController {
@PostMapping("/create")
public Result<Payment> createPayment(@RequestBody PaymentRequest request) {
Payment payment = new Payment();
payment.setOrderId(request.getOrderId());
payment.setAmount(request.getAmount());
payment.setStatus("SUCCESS");
payment.setPayTime(LocalDateTime.now());
// 模拟支付成功
return Result.success(payment);
}
}
🌐 API 网关(gateway-api)
使用 Spring Cloud Gateway 统一入口、路由、限流。
1. 依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2. 配置路由
spring:
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: user_service
uri: lb://service-user
predicates:
- Path=/users/**
- id: order_service
uri: lb://service-order
predicates:
- Path=/orders/**
- id: delivery_service
uri: lb://service-delivery
predicates:
- Path=/delivery/**
✅ lb:// 表示从 Nacos 获取服务实例并负载均衡。
🛡️ Sentinel 流量控制
1. 在订单服务中引入 Sentinel
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2. 配置 Sentinel 控制台地址
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
3. 定义降级逻辑
@FeignClient(name = "service-merchant", fallback = MerchantClientFallback.class)
public interface MerchantClient {
@PostMapping("/notify")
Result<String> notifyOrderReady(@RequestBody OrderNotifyDTO dto);
}
@Component
public class MerchantClientFallback implements MerchantClient {
@Override
public Result<String> notifyOrderReady(OrderNotifyDTO dto) {
log.warn("调用商家服务失败,启用降级逻辑,订单ID: {}", dto.getOrderId());
return Result.success("商家通知已跳过(降级)");
}
}
4. 在 Sentinel 控制台设置规则
- 流控规则:
/orders/createQPS > 10 时限流 - 降级规则:异常比例 > 50% 时降级
- 热点参数:用户 ID 频繁下单时限制
📊 系统监控(Prometheus + Grafana)
1. 在各服务中启用 Actuator + Prometheus
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
management:
endpoints:
web:
exposure:
include: prometheus,health,metrics
metrics:
export:
prometheus:
enabled: true
访问:http://localhost:8080/actuator/prometheus
2. 配置 Prometheus
prometheus.yml
scrape_configs:
- job_name: 'delivery-service'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['localhost:8081']
- job_name: 'order-service'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['localhost:8082']
3. 启动 Prometheus
docker run -d -p 9090:9090 -v /path/to/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus
4. 启动 Grafana
docker run -d -p 3000:3000 grafana/grafana
访问:http://localhost:3000
导入 Spring Boot 监控模板(ID: 12000)
🧪 系统测试流程
1. 启动所有服务
确保 Nacos、Sentinel、Seata、Prometheus、Grafana 已启动。
依次启动:
- service-user
- service-merchant
- service-order
- service-delivery
- service-payment
- gateway-api
2. 创建订单(通过网关)
curl -X POST http://localhost:8080/orders/create \
-H "Content-Type: application/json" \
-d '{
"userId": 1,
"merchantId": 1,
"amount": 58.5,
"address": "北京市朝阳区xxx"
}'
3. 查看 Nacos 服务列表
访问:http://localhost:8848/nacos
应看到所有服务注册成功。
4. 查看 Sentinel 实时监控
访问:http://localhost:8080
查看 OrderController.createOrder 的 QPS、响应时间。
5. 模拟配送状态更新
curl -X PUT http://localhost:8080/delivery/status \
-H "Content-Type: application/json" \
-d '{"orderId": 1001, "status": "DELIVERING"}'
前端 WebSocket 应收到 "DELIVERING" 消息。
🛠️ 生产环境优化建议
| 优化项 | 建议 |
|---|---|
| 🚀 性能 | 使用 Redis 缓存热点数据(如商家信息) |
| 🔐 安全 | API 签名、HTTPS、敏感信息加密 |
| 📈 扩展性 | 服务横向扩展,K8s 部署 |
| 🔄 高可用 | 多节点部署 Nacos、Sentinel、Seata |
| 📊 日志 | ELK 收集日志,便于排查问题 |
| 🔄 CI/CD | Jenkins/GitLab CI 自动化部署 |
📈 未来可扩展功能
- 🧠 AI 智能调度:基于历史数据预测配送时间
- 🚗 骑手 App:GPS 实时定位、接单、导航
- 💬 消息中心:短信、推送通知
- 📊 数据分析:订单量、配送时长、用户画像
- 🌐 多语言支持:国际化外卖平台
- 🤖 无人配送:无人机/机器人配送集成
📚 总结
通过本文的实战,我们使用 Spring Cloud Alibaba 成功构建了一个高可用、可扩展的外卖配送系统,涵盖了:
✅ 微服务拆分与治理
✅ 服务注册与配置(Nacos)
✅ 服务调用(OpenFeign)
✅ 流量控制与熔断(Sentinel)
✅ 分布式事务(Seata)
✅ 实时通信(WebSocket)
✅ 系统监控(Prometheus + Grafana)
这套架构不仅适用于外卖系统,也可用于电商、物流、打车等复杂业务场景。
🔗 延伸学习:
🎉 恭喜你,已经掌握了使用 Spring Cloud Alibaba 构建复杂分布式系统的能力!
现在,你可以将这套架构应用于实际项目,打造高性能、高可用的企业级应用。继续探索,不断精进!🚀🍽️🛵
🙌 感谢你读到这里!
🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。
💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友!
💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿
🔔 关注我,不错过下一篇干货!我们下期再见!✨
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)