目录

  1. 前言
  2. 变化情况介绍
  3. 总结

一、前言

       之前版本是0.9或者0.10.1、0.10.2,最近发现更新成为1.0.0-2077839。1.0应该也能称之为正式版了吧。发现其中有很多变化,在这里为大家简单介绍。

二、变化情况介绍

2.1 数据导入变化

       之前数据导入参数基本都要写在命令行,刚查看之前写的博客发现没有介绍数据导入的,只有一个老版的调用本地数据的,本文就在这里简单介绍Geotrellis的数据导入。

       Geotrellis可以将数据(Tiff)从本地、HDFS、S3中导入到本地、HDFS、Accumulo、HBASE、CASSANDRA、S3等,可选方式很多,而且是通过Spark集群并行处理,其实相当于Geotrellis已经实现了分布式的瓦片切割。老版的命令如下:

spark-submit --class geotrellis.Ingest --driver-memory=2G jarpath
--input hadoop --format geotiff --cache NONE -I path=filepath
--output accumulo -O instance=accumuloinstance table=tablename user=username
password=password zookeeper=zookeeper --layer layername --crs EPSG:3857 --layoutScheme floating

       其中geotrellis.Ingest是一个调用Geotrellis内部数据导入的类,就是调用了ETL类进行数据自动上传。代码如下:

implicit val sc = SparkUtils.createSparkContext("Ingest", new SparkConf(true))
Etl.ingest[ProjectedExtent, SpatialKey, Tile](args, ZCurveKeyIndexMethod)
sc.stop()

       如果是多波段数据将Tile换成MultibandTile即可。接着说上面的脚本,input表示数据输入方式,如果是本地和HDFS就写hadoop,如果是S3就写s3。format是数据类型,单波段tiff为geotiff,多波段tiff为multiband-geotiff。path为数据存放路径。output指定输出存放位置。后面是该位置的一些配置。具体非常复杂,可以参考https://github.com/pomadchin/geotrellis/blob/master/docs/spark-etl/spark-etl-intro.md

       上面的数据导入配置看上去是不是很乱,并且完全没有组织,1.0版进行了很大的改进,将配置信息基本都写在了json文件里。1.0版数据导入命令如下:

spark-submit \
--class geotrellis.dataimport.DataIngest --driver-memory=2G $JAR \
--input "file:///input.json" \
--output "file://output.json" \
--backend-profiles "file://backend-profiles.json"

       看上去是不是很清爽,将配置信息写在了三个文件里,下面逐一介绍这三个文件。

       input表示输入信息的配置,其json文件如下:

[
{
"name": "landsat",
"format": "geotiff",
"backend": {
"type": "hadoop",
"path": "file:///datapath/"
},
"cache": "NONE"
}
]

       这是一个json数组可以写多个。name相当于旧版的layername,format不变,type相当于旧版的input,path不变。

       output表示输出信息的配置,其json文件如下:

{
"backend": {
"type": "accumulo",
"path": "through",
"profile": "accumulo-201"
},
"reprojectMethod": "buffered",
"cellSize": {
"width": 256.0,
"height": 256.0
},
"tileSize": 256,
"pyramid": true,
"resampleMethod": "nearest-neighbor",
"keyIndexMethod": {
"type": "zorder"
},
"layoutScheme": "zoomed",
"cellType":"int8",
"crs": "EPSG:3857"
}

       大部分意思与旧版相同,主要是backend中的信息,type相当于旧版的output,path相当于table,profile表示accumulo或其他输出方式的配置,具体写在backend-profiles.json文件中。

       backend-profiles中存放数据库等配置信息,其json文件如下:

{
"backend-profiles": [
{
"name": "accumulo-201",
"type": "accumulo",
"zookeepers": "zookeeper",
"instance": "accumulo-instance",
"user": "username",
"password": "password"
},
{
"name": "cassandra-local",
"type": "cassandra",
"allowRemoteDCsForLocalConsistencyLevel": false,
"localDc": "datacenter1",
"usedHostsPerRemoteDc": 0,
"hosts": "localhost",
"replicationStrategy": "SimpleStrategy",
"replicationFactor": 1,
"user": "",
"password": ""
}
]
}

       backend-profiles节点下可以存放多个数据库配置信息,其中name就是output.json文件中的backend.profile。

2.2 性能提升

       1.0版本明显做了很多优化,代码也变的更整洁清晰,带来的结果是性能明显提升。比如数据导入之前导入数据比较费时,且经常失败,1.0版更加稳定,并且速度明显提升。数据读取以及处理的速度也有所提升,我的系统中原来需要90ms处理的数据,现在可能只需要60ms左右,原来需要600ms处理的现在也只需要300ms左右。其实下面要讲的更是一个性能方面的提升。

2.3 LayerReader读取整层数据的变化

       比如我们希望能够实现用户选择任意区域数据(以SRTM为例)并能够自动拼接、下载该区域的SRTM数据,首先我们需要将全球的SRTM数据导入Geotrellis中,然后当有用户请求的时候读出SRTM的数据,进行拼接等操作。旧版的时候我们就需要将整层数据读出,然后根据用户输入的范围调用mask方法进行掩码操作。而新版大大改进了这一点,我们可以直接取出用户输入范围内的数据。下面我为大家介绍使用LayerReader读取整层数据的三种实现方式。

       第一种方式直接读取整层数据。代码如下:

reader.read[SpatialKey, Tile, TileLayerMetadata[SpatialKey]](layerId)

       其中reader是FilteringLayerReader[LayerId]对象,下同,从名字就能看出应该是1.0版新加的带有过滤的层读取类(旧版为AccumuloLayerReader类),layerId为读取的层的信息,下同。适用该方式就会将该layerId的整层数据读出。

       第二种方式为read方法添加一个LayerQuery对象。实现代码如下:

reader.read[SpatialKey, Tile, TileLayerMetadata[SpatialKey]](layerId, new LayerQuery[SpatialKey, TileLayerMetadata[SpatialKey]].where(Intersects(polygon)))

       其实就是用where语句加了一个过滤条件,Intersects(polygon)表示条件是与polygon相交,polygon是用户选择的范围,并且需要跟原始数据采用同一投影,此处有个小bug,就是仅支持MultiPolygon,如果是Polygon对象需要使用MultiPolygon(polygon)进行简单封装,下同。这样就能实现只读取该层中的与polygon相交的数据。

       第三种方式就是第二种方式的语法糖,写起来更加简单方法。代码如下:

reader.query[SpatialKey, Tile, TileLayerMetadata[SpatialKey]](layerId).where(Intersects(polygon)).result

       以上就是实现整层数据读取的三种方式,如果需要处理的上述业务需求,最好采用后两种方式,进行实际测试,效率提高10倍左右。但是后两种方式有个小bug:如果polygon与层中的数据相交的瓦片(源数据在Accumulo等数据库中存放的方式是256*256的瓦片)是较小的区域,可能该瓦片不会被取出,即会被过滤掉,Geotrellis毕竟是一个新的框架,我们应该包容其中的BUG,寻找合适的方式绕过BUG实现我们的需求。

三、总结

       本文简单介绍了1.0版Geotrellis中的变化,不难看出Geotrellis正在快速的向前推进,我相信假以时日,一定会变的更加完善、更加好用,我对Geotrellis的未来充满信心。

04-14 23:57