Google Maps — 地图服务
V1「做个配送点标记地图」
Section titled “V1「做个配送点标记地图」”你在一家社区团购公司实习,组长让你做一个内部工具:把所有配送点标在地图上,方便调度员一眼看到今天要送哪些地方。目前配送点信息存在一个 Excel 表里,大概 30 个点。组长说”先做个能看的,不用后端,本地跑起来就行”。你决定用 Leaflet.js + OpenStreetMap 做一个纯前端的标记地图。
你要解决什么
Section titled “你要解决什么”把配送点数据展示在交互式地图上,支持点击查看详情和手动添加新标记。
给 AI 的 Prompt
Section titled “给 AI 的 Prompt”做一个配送点标记地图,要求:
技术栈:单个 HTML 文件,引入 Leaflet.js CDN,使用 OpenStreetMap 瓦片图层数据:页面内嵌 JSON 数组,每个配送点包含 name、address、lat、lng、daily_orders 字段,预置 15 个上海市区的配送点功能:1. 页面加载后在地图上显示所有配送点 Marker2. 点击 Marker 弹出 Popup,显示名称、地址、日均单量3. 点击地图空白处可添加新标记,弹出表单填写名称和地址4. 新添加的标记保存到 localStorage,刷新页面不丢失5. 左侧面板列出所有配送点,点击列表项地图飞到对应位置6. 支持按日均单量筛选(高/中/低)
地图默认中心:上海市中心 [31.23, 121.47],缩放级别 12Marker 用不同颜色区分单量等级:红色 > 100单,橙色 50-100单,绿色 < 50单- 打开 HTML 文件,地图正常加载,能看到 OpenStreetMap 底图
- 15 个配送点 Marker 全部显示,颜色按单量等级区分
- 点击 Marker 弹出信息气泡,内容正确
- 点击空白处能添加新标记,刷新后仍在
- 左侧列表点击后地图平滑飞到对应位置
- 筛选功能正常工作
你学到了什么
Section titled “你学到了什么”- 前端地图渲染原理:瓦片加载 + 坐标系统 → M13(网络与内容分发)
- localStorage 作为零成本本地持久化方案 → M2(数据存储)
- GeoJSON 数据格式基础 → M9(数据处理)
V2「司机说要规划送货路线,不只是看标记点」
Section titled “V2「司机说要规划送货路线,不只是看标记点」”配送点标记地图上线后,调度员很满意,但司机师傅提了新需求:“我每天要跑 8-10 个点,能不能帮我算一下最优路线?不然我全靠经验走,有时候绕远路。“你意识到路线规划需要调用路由算法,纯前端做不了。组长说可以用 OSRM(开源路线规划引擎),它有免费的 demo API。但 OSRM API 响应较慢,同一条路线重复查询会浪费时间。
你要解决什么
Section titled “你要解决什么”搭建后端调用 OSRM API 实现路线规划,并缓存计算结果避免重复请求。
给 AI 的 Prompt
Section titled “给 AI 的 Prompt”在 V1 地图基础上增加路线规划功能,要求:
后端:Go + Gin1. POST /api/route 接收 waypoints(经纬度数组),调用 OSRM demo API(http://router.project-osrm.org/route/v1/driving/...)获取路线2. 返回 GeoJSON 格式的路线数据,包含总距离(km)和预计时间(分钟)3. 用内存 map 缓存路线结果,key 为 waypoints 排序后的 hash,TTL 30 分钟4. GET /api/route/cache/stats 返回缓存命中率统计
前端:在 Leaflet 地图上1. 用户从列表中勾选 2-10 个配送点作为途经点2. 点击"规划路线"按钮,调用后端 API3. 在地图上用 Polyline 绘制路线,蓝色线条,宽度 4px4. 显示总距离和预计用时5. 支持拖拽调整途经点顺序
OSRM API 格式:GET http://router.project-osrm.org/route/v1/driving/{lng1},{lat1};{lng2},{lat2}?overview=full&geometries=geojson- 选择 3 个配送点,点击规划路线,地图上画出蓝色路径
- 显示的总距离和时间合理
- 相同路线第二次请求明显更快(命中缓存)
- /api/route/cache/stats 返回命中率数据
- 拖拽调整途经点顺序后重新规划,路线变化
你学到了什么
Section titled “你学到了什么”- 服务端代理外部 API 调用,隐藏第三方依赖 → M1(API 设计)
- 内存缓存策略:hash key 设计 + TTL 过期 → M4(缓存策略)
- GeoJSON 作为地理数据交换标准格式 → M13(网络与内容分发)
- 请求合并与去重的基本思路 → M9(数据处理)
V3「司机抱怨路线不考虑实时路况,早高峰绕远路」
Section titled “V3「司机抱怨路线不考虑实时路况,早高峰绕远路」”路线规划功能用了一个月,司机们反馈:“你这个路线是死的,早上 8 点走中山路堵成狗,它还让我走中山路。“你发现 OSRM 默认不考虑实时路况,返回的是静态最短路径。老板说这个问题不解决,司机会继续用手机导航而不是你的系统。你需要接入实时路况数据,让路线规划能感知拥堵,并在司机送货过程中动态调整路线。同时,所有司机同时在线查询路线,缓存系统也需要升级。
你要解决什么
Section titled “你要解决什么”接入实时路况数据实现动态路线规划,支持在途中重新路由和实时推送路线更新。
给 AI 的 Prompt
Section titled “给 AI 的 Prompt”在 V2 基础上增加实时路况感知和动态路线更新,要求:
后端:Go + Gin + PostgreSQL + Redis1. 路况数据模拟: - 用 goroutine 每 30 秒生成模拟路况数据(路段ID、拥堵等级 1-5、平均速度) - 存入 Redis Hash:traffic:{segment_id} → {level, speed, updated_at},TTL 5 分钟2. 路线规划升级: - POST /api/route/realtime 在调用 OSRM 后,查询途经路段的实时路况 - 根据拥堵等级计算加权时间:level 4-5 的路段时间乘以 2.5 倍 - 如果加权后存在更优路线(时间差 > 15%),返回备选路线3. 实时推送: - GET /api/route/live/:driver_id 使用 SSE 推送 - 当司机当前路线上的路况变化超过阈值,推送重新路由建议 - 包含变化路段、新预计时间、建议绕行路线4. 路线历史: - PostgreSQL 存储每次路线规划记录(司机、途经点、选择路线、实际用时) - GET /api/route/history/:driver_id 返回历史路线
前端:1. 路线 Polyline 根据路况着色:绿色通畅、黄色缓行、红色拥堵2. 实时接收 SSE 推送,弹出"路况变化,建议绕行"通知3. 用户可一键接受新路线或忽略4. 显示历史路线对比(计划时间 vs 实际时间)- 路线 Polyline 上能看到不同颜色标注的路况段
- 模拟路况变化后,SSE 推送到达前端,弹出绕行建议
- 点击”接受新路线”后地图路线更新
- Redis 中能查到 traffic:* 键,数据在 5 分钟内过期
- 路线历史 API 返回正确的规划记录
- 高拥堵路段的预计时间明显长于通畅路段
你学到了什么
Section titled “你学到了什么”- Redis 作为实时数据的临时存储层,TTL 自动清理过期路况 → M4(缓存策略)
- SSE 实现服务端到客户端的实时单向推送 → M13(网络与内容分发)
- 数据加权与动态决策:路况权重影响路线选择 → M9(数据处理)
- 写入 PostgreSQL 做持久化,Redis 做热数据,冷热分离 → M2(数据存储)
- 后台 goroutine 定时任务模拟真实数据源 → M5(消息与事件)
V4「配送员要实时上报位置,调度员要看所有人在哪」
Section titled “V4「配送员要实时上报位置,调度员要看所有人在哪」”配送团队扩大到近千人,老板要求上线实时调度功能:“调度员必须能在大屏上看到每个司机的实时位置,司机端每隔几秒自动上报 GPS 坐标。“这意味着你需要处理大量高频位置上报(1000 个司机 × 每 5 秒一次 = 每秒 200 条写入),普通 HTTP 轮询扛不住,需要 WebSocket 保持长连接。同时调度员看的是全量司机位置,查询也要快。位置数据还需要保留历史轨迹,方便事后回溯配送路线。
你要解决什么
Section titled “你要解决什么”实现配送员实时位置上报(WebSocket)、调度大屏实时展示所有司机位置、以及位置历史轨迹查询。
给 AI 的 Prompt
Section titled “给 AI 的 Prompt”在 V3 基础上增加实时位置追踪系统,要求:
后端:Go + Gin + PostgreSQL + Redis1. WebSocket 位置上报: - WS /ws/location/:driver_id — 司机端连接后每 5 秒发送 {lat, lng, speed, heading, timestamp} - 服务端收到后写入 Redis GEO:GEOADD driver_locations {lng} {lat} {driver_id} - 同时写入 Redis Hash:driver:{driver_id}:status → {lat, lng, speed, heading, last_seen, status} - 在线/离线判定:超过 30 秒未上报标记为离线2. 调度大屏 API: - GET /api/dispatch/drivers — 返回所有在线司机的实时位置列表 - GET /api/dispatch/drivers/nearby?lat=&lng=&radius=5 — 查询指定坐标半径内的司机(GEORADIUS) - GET /api/dispatch/live — SSE 推送,每 3 秒推送位置有变化的司机列表(增量更新)3. 位置历史轨迹: - 后台 goroutine 每 30 秒将 Redis 中的位置数据批量写入 PostgreSQL - 表:location_history(id, driver_id, lat, lng, speed, heading, recorded_at) - 添加索引:(driver_id, recorded_at) - GET /api/drivers/:id/trail?date=2024-01-15 — 返回某司机某天的完整轨迹4. 位置数据缓存策略: - 实时位置只在 Redis 中,TTL 5 分钟 - 历史轨迹在 PostgreSQL,按月分区 - 调度大屏的全量快照缓存 3 秒
前端:1. 调度大屏:Leaflet 地图上显示所有在线司机图标,实时移动2. 司机图标根据状态着色:配送中绿色、空闲蓝色、离线灰色3. 点击司机图标显示详情:姓名、当前速度、最后更新时间4. 支持查看历史轨迹:选择日期后在地图上绘制轨迹线5. 调度员可在地图上画圈,查询范围内的可用司机- WebSocket 连接成功,模拟 10 个司机持续上报位置,大屏地图实时更新
- 30 秒无上报的司机自动变为离线状态(灰色图标)
- GEORADIUS 查询返回半径内的司机,距离排序正确
- SSE 增量推送正常工作,只推送位置变化的司机
- 历史轨迹 API 返回完整的一天轨迹数据
- PostgreSQL 中有批量写入的位置记录,时间戳正确
- 调度员画圈查询范围内可用司机功能正常
你学到了什么
Section titled “你学到了什么”- WebSocket 实现高频双向通信,相比 HTTP 轮询大幅降低开销 → M13(网络与内容分发)
- Redis GEO 数据结构:GEOADD/GEORADIUS 实现地理围栏查询 → M4(缓存策略)
- 实时数据的冷热分离:Redis 存热数据、PostgreSQL 存历史 → M2(数据存储)
- 批量写入降低数据库压力:内存聚合 + 定时刷盘 → M5(消息与事件)
- SSE 增量推送 vs 全量推送的权衡 → M8(可扩展性)
V5「路线规划API调用费太贵,很多重复路线」
Section titled “V5「路线规划API调用费太贵,很多重复路线」”用户量突破一万,每天调用外部路线规划 API 数万次,账单越来越高。运营分析发现,70% 的路线请求是重复的——同一个仓库到同一批配送点的组合,每天早上司机们都在查一样的路线。更要命的是,高峰期 API 调用超时导致司机等半天出不了路线。你需要大幅减少外部 API 调用,把钱花在刀刃上。
你要解决什么
Section titled “你要解决什么”通过激进的路线缓存策略、热门路线预计算、多站点批量优化和成本监控来大幅降低外部 API 调用量和响应时间。
给 AI 的 Prompt
Section titled “给 AI 的 Prompt”在 V4 基础上优化路线规划的成本和性能,要求:
后端:Go + Gin + PostgreSQL + Redis + 消息队列1. 激进路线缓存: - 缓存 key 设计:将起终点坐标四舍五入到小数点后 3 位(约 100 米精度),相近路线共享缓存 - Redis 缓存 TTL 分级:热门路线 24 小时,普通路线 2 小时 - 缓存预热:每天凌晨根据前一天的热门路线 Top 100 预计算并缓存2. 热门路线预计算: - 统计最近 7 天高频路线组合(起点-终点对),存入 PostgreSQL - 定时任务每天凌晨 3 点批量调用 API 预计算 Top 200 路线 - GET /api/routes/popular — 返回热门路线列表,前端可直接展示3. 多站点批量优化: - POST /api/route/optimize — 接收一组配送点,返回最优访问顺序(TSP 近似解) - 使用贪心算法(最近邻)生成初始解,减少 API 调用 - 只对最终优化后的路线调用外部 API 获取精确导航4. 成本监控仪表盘: - 记录每次外部 API 调用:时间、响应时长、费用 - GET /api/admin/route-costs — 返回日/周/月 API 调用量、费用、缓存命中率 - 设置告警阈值:日调用量超过 5000 次触发告警日志5. 多实例部署支持: - 路线缓存统一存 Redis,多个后端实例共享 - 预计算任务用 Redis 分布式锁防止重复执行 - Nginx 负载均衡配置示例
前端:1. 路线规划结果标注"缓存命中"或"实时计算"2. 管理后台显示成本监控图表:每日 API 调用量趋势、缓存命中率趋势3. 热门路线推荐:司机输入起点后推荐常用终点- 相近起终点(100 米内)的路线查询命中同一缓存
- 凌晨预计算任务执行后,热门路线查询直接命中缓存
- 多站点优化返回合理的访问顺序,API 调用次数明显减少
- 成本监控 API 返回正确的调用量和费用统计
- 日调用量超过阈值时日志中出现告警
- 两个后端实例共享同一份 Redis 缓存,数据一致
- 分布式锁生效:两个实例不会同时执行预计算任务
你学到了什么
Section titled “你学到了什么”- 缓存 key 的模糊匹配策略:坐标精度截断实现”近似命中” → M4(缓存策略)
- 缓存预热与冷启动优化:用历史数据预测未来热点 → M4(缓存策略)
- 外部 API 成本优化:减少调用量比优化单次调用更有效 → M1(API 设计)
- 分布式锁防止定时任务重复执行 → M6(事务与一致性)
- 水平扩展基础:无状态应用 + 共享缓存 + 负载均衡 → M8(可扩展性)
- TSP 近似算法在实际工程中的应用 → M9(数据处理)
V6「全国配送,地图瓦片加载慢,路况数据量巨大」
Section titled “V6「全国配送,地图瓦片加载慢,路况数据量巨大」”公司业务扩展到全国 50 个城市,十万+配送员同时在线。新的问题全面爆发:地图瓦片加载慢,尤其是偏远地区用户首次打开要等 5 秒以上;路况数据从一个城市变成全国路网,数据量增长百倍,单机 Redis 已经存不下;高峰期位置上报 QPS 过万,单个 WebSocket 服务器连接数到达瓶颈;路线规划请求来自全国各地,单数据中心延迟差异大。你需要从根本上重新架构整个地图服务。
你要解决什么
Section titled “你要解决什么”构建全国级地图服务架构:地图瓦片 CDN 加速、路况数据按区域分片、流式处理实时路况聚合、以及基于历史数据的预测性路线规划。
给 AI 的 Prompt
Section titled “给 AI 的 Prompt”在 V5 基础上构建全国级地图服务架构,要求:
基础设施层:1. 地图瓦片服务与 CDN: - 自建瓦片服务器(基于 OpenMapTiles),生成矢量瓦片(.pbf) - 三级缓存:CDN 边缘节点(TTL 7天)→ 区域缓存服务器(TTL 1天)→ 瓦片源站 - 按缩放级别分级缓存策略:低缩放(全国)永久缓存,高缩放(街道)每日更新 - CDN 配置:全国 6 大区域节点,支持就近访问2. 路况数据按区域分片: - 将全国路网划分为 8 大区域,每个区域独立的 Redis 实例 - 路况数据分片 key:traffic:{region}:{segment_id} - 跨区域路线查询:并行查询多个分片,合并结果 - 分片路由中间件:根据坐标自动路由到对应 Redis 分片
后端微服务拆分:1. 地图瓦片服务(map-tile-service): - 瓦片生成、缓存管理、CDN 回源2. 位置服务(location-service): - WebSocket 网关集群:多实例部署,Nginx 按 driver_id hash 分配 - 位置上报写入区域 Redis + Kafka - 支持 10 万+ 并发 WebSocket 连接3. 路况聚合服务(traffic-service): - Kafka Consumer 消费位置数据流 - 滑动窗口聚合:每 30 秒计算每条路段的平均速度和拥堵等级 - 聚合结果写入区域 Redis + 时序数据库(用于历史分析)4. 路线规划服务(routing-service): - 自建 OSRM 集群(按区域部署),不再依赖外部 API - 预测性路由:根据历史同时段路况数据预测未来 30 分钟拥堵趋势 - 多级降级策略:自建 OSRM → 缓存历史路线 → 直线距离估算
数据层:1. PostgreSQL 读写分离 + 按区域分库 - 写库:主库处理位置写入和订单 - 读库:2 个副本处理轨迹查询和报表 - 按区域分库:华东、华南、华北各一个库2. 时序数据库(TimescaleDB): - 存储历史路况数据,支持时间范围聚合查询 - 自动压缩 7 天前的数据3. Kafka 消息管道: - topic: driver-locations(位置上报原始数据) - topic: traffic-updates(聚合后的路况更新) - topic: route-events(路线规划事件,用于分析)
监控与可观测性:1. 全链路追踪:从瓦片请求到路线规划的完整链路2. 各服务 QPS/延迟/错误率大盘3. 区域级热力图:实时显示各区域负载分布4. 告警规则:瓦片加载 P95 > 1s、路线规划 P95 > 3s、WebSocket 连接数 > 80%
前端:1. 矢量瓦片渲染(MapLibre GL),替代栅格瓦片,流量减少 80%2. 瓦片预加载:根据用户位置预加载周边区域瓦片3. 调度大屏按区域切换视图,支持全国总览和单区域详情4. 路线规划显示"预测拥堵"信息,提前建议出发时间- 不同区域用户加载地图瓦片命中最近的 CDN 节点,P95 < 500ms
- 路况数据正确分片到对应区域的 Redis 实例
- 跨区域路线查询(如北京到上海)正确合并多个分片的路况数据
- Kafka 消费端正常聚合位置数据,路况更新延迟 < 1 分钟
- WebSocket 网关集群承受 1 万并发连接压测,消息不丢失
- 自建 OSRM 路线规划结果正确,降级策略按预期触发
- 时序数据库历史路况查询性能合理,7 天前数据自动压缩
- 全链路追踪能看到一个路线请求的完整调用链
- 预测性路由在历史拥堵时段给出合理的绕行建议
你学到了什么
Section titled “你学到了什么”- CDN + 边缘缓存 + 源站三级架构:地理分布式内容加速 → M13(网络与内容分发)
- 数据按区域分片:降低单节点负载,就近服务 → M8(可扩展性)
- 流式处理(Kafka + 滑动窗口):将海量位置数据实时聚合为路况信息 → M9(数据处理)
- 微服务拆分:按领域职责拆分独立部署,各自扩缩容 → M17(基础设施)
- 读写分离 + 区域分库:数据库层的水平扩展方案 → M3(数据复制)
- 时序数据库处理时间序列数据的优势 → M2(数据存储)
- 预测性路由:历史数据驱动的智能决策 → M9(数据处理)
- 全链路可观测性:分布式系统的”上帝视角” → M15(可观测性)
- 多级降级策略:保证核心功能在局部故障时仍可用 → M16(DevOps)