前言
做了一个地理信息采集系统的项目,项目在部署时为单机环境,没有互联网环境。这就要求地图底图需要离线、导航也需要离线。这篇文章就是记录地图底图离线的方案以及在实现过程中遇到的一些问题。记录这篇文章不是为了探索如何实现离线地图,而是为了记录在大数据量(原始数据大小 1.2T )的底图数据处理中,实现离线地图存在的一些问题。此外这篇文章不记录详细实现步骤,但提供实现方案。实现过程中共采取了以下几种方案:
- 方案一:Geoserver + mbtiles拓展 + 91卫图(用于下载导出mbtiles数据)
- 方案二:Geoserver + GeoWebCache + WTMS(Geoserver切片服务)+ 91卫图
- 方案三:Node + Server(Node的静态资源服务插件) + 91卫图
在实现过程中主要遇到以下几个问题:
- 甲方要求使用天地图的数据,在下载数据时91提供了经纬直投、Web墨卡托投影的数据源,这两个数据源该用哪一个
- 全区域设计1个市区、9个县,要实现像天地图一样的导航效果,需要下载1-18级所有数据,总数大小将近1.2T(这个数据量大的问题也是我在实现过程中,试错成本显著增加的主要原因)
- 如何将下载的数据发布成服务(一开始采用了GeoServer的图层服务,后来采用Geoserver的Tile Cache,最后采用 Node 搭建静态资源服务)
- 其他问题(在讲述以上各个方案时再描述)
一、数据下载耗时情况
实现离线地图底图,前后共计耗时约一个月左右,主要分为数据处理的时间成本、踩坑的时间成本。
1.1 数据源的选择
91提供了经纬直投、Web墨卡托投影的数据源,但是最后我选择了Web墨卡托投影的数据源,因为当使用经纬直投数据源下载的数据,导出mbtiles之后无法在Geoserver正常加载,无法定位问题在什么地方。问91客服,给了一个可能的答案:Geoserver不支持经纬直投的瓦片数据。因为这个,我后面的方案都采用了Web墨卡托投影的数据源。
1.2 数据处理时间成本
91数据下载与导出,底图数据的下载是最耗时的,下面是一张时间成本表,我需要一个市县区域的数据,总共10区域,下表记录了方案三的处理时间,虽没有对方案一、二的情况进行统计,但可以参考这个(时间会大于导出原始瓦片的时间):
使用方案二,还会增加切片的时间成本。Geoserver切片使用的是GeoWebCahce,也是一个开源项目,关于切片的时间我没有记录,此处举例一些数据来做参考。
数据名称 | 数据大小(G) | 切片层级 | 切片数 | 切片时间 |
---|---|---|---|---|
18级影像 | 36.58 | 18 | 约21万 | 约4小时 |
17级影像 | 11.44 | 17 | 约10万 | 约40分钟 |
16级影像 | 2.88 | 16 | 约6万 | 约16分钟 |
以上都是同一区域不同级别的切片任务耗时情况,当切片的层级增加,切片数据量、切片耗时增加,每一级之间数量的差距为,n为层级:
2
n
−
2
n
−
1
2^{n}-2^{n-1}
2n−2n−1
对于数据量增大时,耗时情况无法计算。另外,不同坐标系因切片规则不同,切片数量也不一样。
GeoWebCache支持多任务(就是多线程),在计算机空闲时间下切片效率会有显著提升,但不高,在计算机处于繁忙时间(例如又要做开发,又要下载导出数据),效率不及单任务。
1.3 踩坑成本时间
整过过程踩坑最耗时的是方案二,当时影像数据下载分区域下载,然后交由一个同事处理,在导出数据时按边界裁剪,但没有勾选去黑边,导致Geoserver切片之后黑色背景部分不透明。后来采取了整区域下载,即10个区域一次性下载,数据量在 385G 左右,下载耗时1个多星期,最后导出数据约 50G。可以看出数据出了问题,这个问题还出现在下载电子地图上,问91客服,主要原因有以下几点:
- 天地图数据不支持大范围下载(切记),多大范围呢,测不了,但是下载一个县没问题,下一个市,失败。
- 天地图数据不要频繁请求下载。什么意思呢?即不要图快,同时建立多个下载任务一起下载天地图数据,会被天地图服务器检测而 封禁IP所在网段(不知道物理地址 MAC 封不封,当我发现被封之后选择去网吧包机下载,速度不错),一般 1~3个月 解封。但封禁期间,跟你同处一个网段的下的计算机 都不能使用 天地图的在线服务。客服说高德、百度的不会被封,没试过。
二、切片方案
1.1 方案一 Geoserver + mbtiles 拓展
mbtiles本质是SQLite数据库,更改mbtiles后缀名 .mbtiles 为 .db 即可以SQLite数据库的方式打开查看。
Geoserver本身不支持mbtiles格式数据,需要通过下载安装对应版本 mbtiles的扩展 1。
这个方案是最开始拟定的方案,但是在实现过程中也遇到不少问题,其中最主要的是数据源的坐标系的问题。
此方案应该是较好的方案,原因:
- 91支持导出 mbtiles 文件
- mbtiles与操作系统无关,可移植性强
- mbtiles将切片数据集中存储到数据库,拷贝方便且不耗时
弃用此方案的原因:
- geoserver 无法正确加载 mbtiles中的切片
- 当我的数据很大时,导出 mbtiles也比较大,会导致要么直接读取不了,要么加载速度缓慢的问题,尚未定位问题在哪里。(有幸参与过第三次全国国土调查,当时外野举证的数据包格式为 SQLite数据库,主要存储举证照片等图片数据,后来一个数据包约百G,打开之后,FJ(附件)这张表的查询极其慢)
1.2 方案二 Geoserver + GeoWebCache + WTMS
GeoWebCache是开源项目,用于对影像数据进行切片。
WTMS是Geoserver的切片缓存服务,在Tile Cache菜单下管理。
此方案的没有什么额外操作,安装Geoserver。添加数据源之后即可进行GeoWebCache切片任务,然后在执行多个影像切片合并。
优点:
- geowebcache 是比较成熟的开源项目,而且是 geoserver 内嵌的,不需要进行额外操作
- geowebcae 切片任务是后台进程,不占用主进
缺点:
- 切片耗时(这个跟数据量有关,大多的切片软件都是这个问题)
- 切片进程后台任务,但是没有管理界面
- 切片之后的文件的规则不是标准的OGC TMS服务命名规则,geoserver有自己的命名规则2(其中Geoserver切片路径的计算方式3比较奇怪)
此方案还遇到了原始影像有黑边,导致多个影像切片合并 4 的时候,接边出有黑色不透明的切片。对于此问题曾提出过优化方案:
- 使用 PHOTOMOD 软件合并所有区域影像,去除黑边并切片
此优化方案也弃用了,原因:
- 加载影像构建金字塔及其耗时
- 合并影像越大越耗时,此方案需要执行多次合并
- 合并之后的影像数据切片的工作量评估之后极大
此方案还踩过全区域一起下载的坑,全区域一起下载是不能的,无法完整下载,并且无法正确导出数据,此外还极其耗时。
另外,此方案遇到 3857 的影像数据无法提交切片任务的问题,查看了日志,尚未定位到问题在哪里。后面去看看源码,再来补上。其次,若用 arcgis 打开过 3857 的数据,在添加至 geoserver时,是无法加载的,原因是arcgis 3857坐标系的参数与geoserver 3857参数不一致造成的,arcgis 3857的参数个数比geoserver 3857的多,导致geoserver无法读取。
1.3 方案三 Node + Server插件
此方案是采用 Node + Server 插件,构建静态资源服务器。之所有采用这个方案是出于以下几点:
- node + server 的方式是前端同事提出的推荐方案
- 91卫图能够导出原始瓦片格式,此格式符合 OGC WTMS服务的瓦片命名规则
- 91卫图拉取天地图数据,就是瓦片(PNG)形式 5,无需把瓦片数据下载导出TIF,再用Geoserver切成瓦片
- 项目开始时,曾研究过91卫图原始瓦片的组织结构,有想过写一个图片加载接口来返回对应位置的瓦片
- server插件允许以 http://domain:port/zoom/x/y.png 的方式加载静态资源。值得注意的是,91卫图导出的瓦片路径格式是zoom/y/x。
与上面两种方案对比,这种方案耗时、稳定的综合表现最好。但也存在一些缺陷:
- 原始瓦片的拷贝速度很慢,不是由文件数据大造成的,而是由于瓦片数量太多,拷贝速度固定在几十 kb/s
- 加载速度与计算机性能有关。虽然计算机配置不差,但如果同时运行这多个任务,那切片的加载速度就比较慢。(上面两种方案的加载速度也跟计算机性能有关系)