一、系统架构设计
1. 整体架构
- 前端展示层:用户端APP、骑手端APP、管理后台
- 服务层:订单服务、骑手服务、轨迹服务、地图服务
- 数据层:MySQL(订单/骑手基础数据)、MongoDB(轨迹数据)、Redis(缓存)
- 第三方服务:高德/百度地图API、消息队列(Kafka/RocketMQ)
2. 核心组件
- 轨迹采集服务:负责接收骑手位置上报
- 轨迹处理服务:对原始轨迹数据进行清洗、压缩和存储
- 轨迹查询服务:提供实时轨迹查询接口
- 地图渲染服务:将轨迹数据转换为地图可视化展示
二、技术实现方案
1. 骑手位置上报
```java
// 骑手端位置上报接口示例
@PostMapping("/api/rider/location")
public ResponseEntity<?> uploadLocation(
@RequestBody RiderLocationDTO location,
@RequestHeader("X-Rider-Token") String token) {
// 1. 验证骑手身份
Rider rider = riderAuthService.validateToken(token);
// 2. 构建轨迹点对象
TrajectoryPoint point = new TrajectoryPoint(
rider.getId(),
location.getLng(),
location.getLat(),
location.getTimestamp(),
location.getSpeed(),
location.getDirection()
);
// 3. 发送到消息队列
kafkaTemplate.send("rider-location-topic", point);
return ResponseEntity.ok().build();
}
```
2. 轨迹数据处理
```python
轨迹处理消费者示例
def process_location(message):
point = json.loads(message.value)
1. 数据校验
if not validate_point(point):
return
2. 轨迹压缩(道格拉斯-普克算法)
compressed = compress_trajectory(point[rider_id], [point])
3. 存储到MongoDB
db.trajectories.insert_one({
rider_id: point[rider_id],
order_id: point.get(order_id),
points: compressed,
update_time: datetime.now()
})
4. 更新Redis缓存
redis.hset(f"rider:{point[rider_id]}:last_location",
mapping={
lng: point[lng],
lat: point[lat],
time: point[timestamp]
})
```
3. 实时轨迹查询
```javascript
// 用户端查询骑手实时位置
async function getRiderLocation(orderId) {
// 1. 从Redis获取最新位置
const lastLocation = await redis.hgetall(`order:${orderId}:rider_location`);
if (lastLocation) {
return {
lng: lastLocation.lng,
lat: lastLocation.lat,
updatedAt: lastLocation.time
};
}
// 2. 如果Redis没有,查询MongoDB最新记录
const trajectory = await db.trajectories.findOne(
{ orderId },
{ sort: { points.timestamp: -1 }, limit: 1 }
);
return trajectory?.points?.[0] || null;
}
```
三、关键技术实现
1. 轨迹压缩算法
采用Douglas-Peucker算法减少存储数据量:
```python
def douglas_peucker(points, epsilon):
if len(points) <= 2:
return points
找到最大距离点
dmax = 0
index = 0
for i in range(1, len(points)-1):
d = perpendicular_distance(points[0], points[-1], points[i])
if d > dmax:
index = i
dmax = d
递归处理
if dmax > epsilon:
rec_results1 = douglas_peucker(points[:index+1], epsilon)
rec_results2 = douglas_peucker(points[index:], epsilon)
return rec_results1[:-1] + rec_results2
else:
return [points[0], points[-1]]
```
2. 实时位置推送
使用WebSocket实现实时推送:
```java
// 服务端WebSocket处理
@ServerEndpoint("/ws/rider/{orderId}")
public class RiderLocationWebSocket {
@OnOpen
public void onOpen(Session session, @PathParam("orderId") String orderId) {
// 存储session与orderId的映射
WebSocketManager.addSession(orderId, session);
}
// 当骑手位置更新时调用
public static void pushLocation(String orderId, Location location) {
Session session = WebSocketManager.getSession(orderId);
if (session != null && session.isOpen()) {
session.getAsyncRemote().sendText(
JSONObject.toJSONString(location)
);
}
}
}
```
3. 地图可视化
使用高德地图JS API展示轨迹:
```javascript
// 前端轨迹展示
function showTrajectory(points) {
const map = new AMap.Map(container);
const path = points.map(p => [p.lng, p.lat]);
// 绘制轨迹线
new AMap.Polyline({
map: map,
path: path,
strokeColor: " 3366FF", // 线颜色
strokeWeight: 5 // 线宽
});
// 添加移动的骑手标记
const marker = new AMap.Marker({
map: map,
icon: rider-icon.png,
position: [points[0].lng, points[0].lat]
});
// 动画效果
let i = 0;
const interval = setInterval(() => {
if (i < points.length) {
marker.setPosition([points[i].lng, points[i].lat]);
i++;
} else {
clearInterval(interval);
}
}, 500);
}
```
四、性能优化措施
1. 数据采样:非高峰时段降低上报频率(如每30秒一次)
2. 空间索引:为MongoDB的轨迹数据建立2dsphere索引
3. 缓存策略:
- Redis缓存骑手最后位置(有效期5分钟)
- 本地缓存常用轨迹数据
4. 异步处理:使用消息队列解耦位置上报与处理
5. 数据分片:按骑手ID或日期分片存储轨迹数据
五、安全与隐私考虑
1. 数据加密:位置数据传输使用HTTPS/TLS加密
2. 权限控制:
- 用户只能查看自己订单的骑手位置
- 骑手只能查看自己当前订单的位置
3. 数据脱敏:存储时对经纬度进行微小偏移处理
4. 审计日志:记录所有轨迹查询操作
5. 合规性:符合《个人信息保护法》等相关法规
六、部署方案
1. 容器化部署:使用Docker+Kubernetes
2. 服务发现:通过Nacos或Eureka进行服务注册与发现
3. 监控告警:集成Prometheus+Grafana监控系统
4. 日志收集:使用ELK(Elasticsearch+Logstash+Kibana)收集分析日志
5. 自动扩缩容:根据CPU/内存使用率自动调整Pod数量
七、测试方案
1. 单元测试:JUnit测试各个服务组件
2. 集成测试:Postman测试API接口
3. 压力测试:JMeter模拟高并发位置上报
4. 场景测试:模拟各种异常情况(网络中断、GPS信号丢失等)
5. A/B测试:对比不同轨迹压缩算法的效果
八、扩展功能
1. 预计到达时间(ETA)计算:基于历史轨迹数据和实时路况
2. 异常行为检测:识别骑手长时间静止、偏离路线等异常
3. 热力图分析:展示骑手分布热力图,优化调度
4. 历史轨迹回放:支持查看任意时间段的历史轨迹
5. 多模式导航:根据骑手交通工具(电动车/自行车)推荐最佳路线
通过以上方案,美团买菜系统可以实现高效、准确的骑手轨迹跟踪功能,提升用户体验和运营效率。