Geo Atlas Cache,一个精简的GWC组件

前言 瓦片缓存组件是绝大部分瓦片服务所应该有的模块之一,而Geo Atlas同样实现了其瓦片缓存模块。本文用于描述Geo Atlas中的Cache模块的设计与实现过程。 什么是GAC? GAC,全称是Geo Atlas Cache,是Geo Atlas类库中的Cache模块,用于提供矢量瓦片的缓存功能。GAC源自GWC(GeoWebCache),是在GWC的基础上进行了适应性的调整而来。目前支持基于内存、文件系统两种缓存方式,且此两种缓存方式可任意组合。对于瓦片缓存处理策略,目前支持Seed、Reseed、Truncate三种,与GWC保持一致。 GAC的基本理念 GWC中声明并强调TileLayer的概念,并基于此抽象,用以适配数据来源与瓦片存储(缓存)。也就如同GeoServer中,一个图层如果需要拥有缓存能力,那么还需要创建一个TileLayer;也就是说,一个拥有缓存的图层,将会同时持有两个Layer,一个是 Map Layer(FeatureType),另一个是TileLayer。 TileLayer中进行瓦片存储相关内容的配置,可以随意配置存储容器对象(文件系统、对象存储、数据库等)。 而目前Geo Atlas Cache的实现则将大大简化这一操作,没有TileLayer对象,全局共用同一个存储容器对象,无需繁琐的存储配置,通过自动装配快速启用缓存,我认为这是中小项目中所需要的。 目前对于瓦片缓存(Tile Cache)的清理,也就是同GWC中提供的Seed、Reseed、Truncate一般。Truncate只需持有BlobStore的句柄即可完成,但Seed和Reseed则需前往数据的源端获取瓦片,进而才可完成操作,也就是需要持有获取源端瓦片Generate的句柄才可。或许这就是为什么GWC中提出TileLayer的原因之一也未可知 😮。 不过,我却由此认为GWC的边界不清晰,我认为缓存就做缓存的事情就可以了,应当把Layer、TileMatrixSet(GridSet)和Cache分开。但如此,若想要支持Seed和Reseed这两种给策略的话,至少需要提供一个拓展点才可。我在此将其命名为TileSource,是为Cache与Source(源端瓦片)之间的适配组件。其实,这不也是一种等同TileLayer的存在,但我并不通过Layer来进行关联控制,也没有TileLayer的概念,缓存就是缓存。 GAC的设计与实现 因为GeoServer沉重的历史包袱以及大而全的臃肿,所以有了Geo Atlas项目。GAC也将延续此理念,去除Cache特定于Layer的概念,无需为图层单独配置缓存,因为绝大部分情况下,都是使用相同的缓存配置。同时,他应该是可以被快速集成,且易于配置的。为了提升缓存组件的易用性、兼容性及稳定性,至少应该提供两种不同的缓存存储对象,且其中一种应该是基于内存的,另外一种是支持持久化的。当数据量很少时,可以关闭缓存或仅开启内存缓存;当数据量较大时,可以仅开启持久化缓存或同时开启内存缓存。内存缓存与可持久化缓存可自由搭配,任意组合。当两者全开启时,可形成两级缓存,此时需注意两级缓存间数据的同步。 GAC的需求与设计 接下来,再次确定一下GAC的需求: 支持矢量瓦片缓存 提供两类缓存存储对象,其中一种应该是基于内存的,另外一种是支持持久化的,且两者可任意组合,同时开启可形成二级缓存结构 提供Seed、Reseed、Truncate此三种瓦片缓存清理策略 全局共用同一个缓存存储对象,提供快速集成能力 其中,二级缓存是此前没有接触过的内容。结合自我臆想,给出了如下设想 🫣: 此二级缓存,可自行确定组合方式,并非需要两者同时开启。难点:状态同步(数据一致性) 一级缓存(基于内存): Local Mem Cache + LRU Guava Caffeine 二级缓存(可持久化):Outer Cache Redis File System Database GeoPackage 每一个Level一个gpkg文件,提升并发读写能力(支持配置为所有Level用一个gpkg,但是不推荐) PostGIS 不过,在经过一番调研之后,还是决定抄GeoWebCache的作业 😧。一是确实有一定的难度,二是目前时间有限,GAP中的我早已瑟瑟发抖 🙄。最重要的是,GeoWebCache中的MemoryBlobStore已经实现了上述二级缓存的需求呀 🫡,如此操作可直接覆盖掉前三个需求。而此时二级缓存的实现确定为: 基于内存的缓存(Guava) 基于文件系统的缓存 需要特别注意的是,此MemoryBlobStore二级缓存是可拓展架构,后续可自行拓展不同的Provider。 💡 对于Seed与Reseed的处理,则与GAC的理念中所述一致,通过TileSource对外提供拓展。也就是默认情况下,Cache模块只提供Seed与Reseed的声明,无法提供具体实现(无法直接与Source进行链接)。 那么此刻只剩下最后一个需求了,其主旨围绕快速配置、易用。在此基于GeoWebCache中的DefaultStorageBroker 类进行缓存存储对象的代理,其符合GWC中缓存存储对象设计架构,也为后续提供了更多的拓展点,同时将其暴露给全局,即全局共用的缓存存储对象。对于快速集成能力,此处将结合Spring Boot的AutoConfiguration特性,为GAC提供自动装配能力。与此同时,将缓存存储对象的可设置属性通过配置的方式暴露出来,可直接在application.yml或application.properties中进行配置。具体可配置内容如下所示: geo-atlas.cache.enabled=false(是否启用缓存,默认为false) geo-atlas.cache.inner-caching-enabled=false(是否启用内存缓存,默认为false) geo-atlas.cache.inner.storage.provider=guava(可选值:guava,暂不支持,保留) geo-atlas.cache.inner.storage.memory-limit=16(内存大小限制,单位MB,默认16) geo-atlas.cache.inner.storage.concurrency-level=4(缓存并发级别的默认值,默认为4) geo-atlas.cache.inner.storage.eviction-policy=null(缓存驱逐政策,即缓存淘汰算法,可选值:NULL、LRU、LFU、EXPIRE_AFTER_WRITE、EXPIRE_AFTER_ACCESS,默认值为NULL) 💡 LRU、LFU暂时不支持...

July 13, 2024 · 7 min · Fuyi