事情起源于一个特别离谱的Bug。
后台用户分布地图上。
国内密密麻麻一大片。
然后南极洲孤零零一个点。
特别显眼。
运营截图发群里:
这位用户是在南极科考站下单的吗?
大家笑了半天。
最后定位到原因:
经纬度写反了。
本来以为改一行代码就结束了。
结果越查越发现事情没那么简单。
第一个问题:到底有多少脏数据?
我写了个脚本扫数据库。
结果比想象中夸张。
除了南极。
还有:
- 太平洋
- 非洲撒哈拉
- 印度洋
甚至还有经纬度是:
{
"lat": 999,
"lng": 999
}
的数据。
那一刻我意识到:
问题不是一条数据错了。
而是整个位置系统没有边界。
第二个问题:每个接口返回格式都不一样
项目这些年接过不少位置服务。
有些返回:
{
"lat": 30.57,
"lng": 104.06
}
有些返回:
{
"latitude": 30.57,
"longitude": 104.06
}
还有:
{
"x": 104.06,
"y": 30.57
}
每个开发写接口的时候。
都在自己转换。
没人统一。
第三个问题:没人知道坐标系是什么
最开始我以为:
经纬度不就是经纬度吗?
后来才发现。
国内位置服务至少有:
- WGS84
- GCJ02
- BD09
三套。
有的接口返回GCJ02。
有的返回WGS84。
有人直接存库。
有人转换之后再存。
几年下来。
数据库已经没人能说清楚:
到底存的是什么。
我们干脆做了一层 Location Gateway
后来索性重构。
所有位置数据必须经过一个统一入口。
LocationGateway
负责:
- 坐标系统一
- 格式统一
- 数据校验
- Provider切换
业务层禁止直接调用第三方API。
数据进库前先过四道关
第一关:
经纬度范围校验
lat ∈ [-90,90]
lng ∈ [-180,180]
第二关:
坐标系转换
统一转GCJ02。
第三关:
可信度检查
{
"confidence": 92
}
低于阈值直接丢弃。
第四关:
来源记录
{
"provider": "lts"
}
以后出问题能追溯。
为什么最后选了统一Provider
重构过程中发现。
业务真正需要的能力其实不多:
- 地理编码
- 逆地理编码
- 坐标转换
- IP定位
- 行政区划
以前不同能力接不同服务。
出了问题根本不知道找谁。
后来统一收敛到了:
主要原因很简单:
接口比较全。
不用维护一堆适配层。
重构后的一个意外收获
以前每次排查定位问题:
查接口
查日志
查数据库
半小时起步。
现在看到一条位置数据。
直接知道:
{
"provider": "lts",
"coordsType": "GCJ02",
"confidence": 95
}
来源、坐标系、可信度一眼看完。
排查效率高了很多。
最后
那个南极用户后来找到了。
其实就在成都高新区。
但那次事故让我意识到:
位置服务最难的不是定位。
而是数据治理。
很多团队觉得:
save(lat, lng)
就算完成了位置功能。
实际上真正的工作。
从这里才刚刚开始。