分类:后端开发 / 架构设计 / 经验总结
去年做一次位置服务迁移的时候,我统计了一下公司所有地图能力的调用情况。
结果有点离谱:
订单系统 → 高德逆地理编码
骑手系统 → 腾讯POI搜索
运营后台 → 百度地址解析
小程序 → 地图SDK直接调用
IoT设备 → GPS原始坐标
刚看到的时候我甚至觉得没什么问题。
毕竟业务都跑得好好的。
直到后面连续踩了几个坑。
我才意识到:
地图能力和支付能力一样,本质上应该是一种基础设施。
而不是散落在各个业务系统里的工具函数。
第一次事故:骑手明明到了,地图却显示还差300米
事情发生在一个配送项目。
某天运营反馈:
骑手已经到门口了
地图却显示还差300米
第一反应是:
GPS漂移?
客户端排查了半天。
后端也查了半天。
最后发现问题出在坐标系。
订单系统存的是:
GCJ02
设备系统上传的是:
WGS84
新来的同学做轨迹展示时,直接把数据库里的经纬度拿出来渲染。
结果:
同一张地图
三种坐标系
最终导致:
位置稳定偏移
方向稳定偏移
误差数百米
这种问题特别恶心。
因为数据看起来完全正常。
直到你意识到:
原来大家说的根本不是同一种坐标
第二次事故:换服务商差点改崩整个系统
后来高德套餐续费。
老板问:
有没有别的方案?
于是开始评估迁移成本。
结果统计出来:
订单系统 12处调用
骑手系统 9处调用
运营后台 7处调用
小程序 14处调用
合计40多处
更麻烦的是:
每个系统写法还不一样。
有人封装SDK。
有人直接HTTP请求。
有人甚至把API Key写在代码里。
最终:
一个简单的服务商迁移
做了将近一周
那时候我就意识到。
问题根本不在于:
选高德
选腾讯
还是选百度
问题在于:
业务代码直接依赖地图服务商
第三个问题:钱花哪去了没人知道
后来财务问过一个问题:
地图服务为什么这个月贵了30%?
没人回答得出来。
因为调用太分散了。
订单系统调一点。
骑手系统调一点。
后台调一点。
小程序再调一点。
最后只能看总账单。
根本不知道:
谁花的钱最多
哪类接口最贵
哪里最值得优化
很多团队的位置服务成本越来越高。
其实不是接口贵。
而是根本没有统计。
后来我们抽了一层 Location Service
架构变成这样:
订单系统
骑手系统
运营后台
小程序
│
▼
Location Service
├── Geocode
├── ReverseGeocode
├── CoordConvert
├── POISearch
├── Cache
├── Metrics
├── ProviderAdapter
│
▼
地图服务商
所有业务系统只能调用:
location.geocode()
location.reverseGeocode()
location.convertCoords()
location.searchNearby()
业务层永远不允许直接访问地图厂商。
Location Service到底解决了什么
1、统一坐标系
这是最重要的一点。
内部统一规定:
所有输出坐标
统一GCJ02
无论数据来源是:
WGS84
BD09
BD09MC
进入系统后全部转换。
业务层永远只拿一种坐标。
以后不会再出现:
地图偏移
轨迹错位
围栏误判
这种问题。
2、服务商可替换
业务层只知道:
location.reverseGeocode()
不知道底层是谁。
今天接:
高德
明天换:
腾讯
后天换:
百度
甚至自建服务。
业务代码完全不用改。
真正变化的只有:
ProviderAdapter
这一层。
3、集中管理Key
很多项目都有这种代码:
const key = 'xxxxxxxx'
然后:
前端有
后台有
测试环境有
开发环境也有
几年之后没人知道哪些还在用。
抽出 Location Service 以后:
Key只存在一个地方
权限管理也简单很多。
4、调用量透明
所有请求经过同一个入口。
统计变得特别容易。
例如:
逆地理编码
120万次/月
POI搜索
38万次/月
坐标转换
15万次/月
现在再问:
为什么账单上涨?
直接查监控就知道。
顺手加一层缓存
很多地址解析其实是重复请求。
例如:
成都天府广场
一天可能被查几万次。
完全没必要每次请求第三方。
可以直接:
Redis
↓
命中返回
未命中
↓
第三方地图服务
很多时候:
成本直接下降30%以上
而且响应速度更快。
什么时候该做这件事
我的建议是:
第一次接地图能力的时候
就应该抽。
不要等到:
坐标系混乱
服务商迁移
账单暴涨
之后再补。
因为那个时候:
业务代码已经长得到处都是。
改起来会非常痛苦。
最后
后来我们把位置能力统一收敛到了 Location Service。
底层接的是 LTS。
正逆地理编码、坐标转换、POI搜索这些能力都统一走这一层。
但回头看,这篇文章真正想表达的其实不是:
选哪家地图服务商
而是:
不要让业务代码直接依赖地图服务商。
因为地图能力本质上是一种基础设施。
而基础设施,最好只有一个入口。
这样未来无论是技术演进、成本优化还是服务商迁移,都不会牵一发动全身。