釋出 mbtiles 儲存的向量瓦片

GIS兵器庫發表於2021-09-02

之前我們分享過如何 在本地釋出OSM向量瓦片地圖,裡面介紹了生成的向量瓦片會存放在 .mbtiles 檔案中,然後用 tileserver-gl 軟體釋出。

mbtiles 是基於sqllite資料庫儲存地圖瓦片資料的標準規範,.mbtiles檔案就是實現了這個規範的sqllite資料庫。

最近遇到個相關的問題,專案上需要將這份.mbtiles格式的向量瓦片部署到客戶伺服器上併發布。

之前分享過我在用的 開源GIS解決方案,裡面將 postgis、geoserver、tomcat 都搞成了綠色版,並且可以通過批處理指令碼將它們一鍵註冊成系統服務,這樣就形成了一個套開源GIS的綠色版安裝包,部署時會很方便。

這套安裝包的整體技術架構是偏 java 的,而這次釋出向量瓦片用到的 tileserver-gl 是基於 nodejs 開發的,按上面的思路,需要將 nodejs 也搞成綠色版的,並且可以使用批處理註冊成系統服務。

因為不想把安裝包搞的太大,也不想用太多的技術體系,讓後期維護變得複雜,所以就想能不能在現有的技術體系下搞定 .mbtiles 釋出的問題。

按這個思路,需要去研究有沒有相關的geoserver外掛,或是 java 的軟體或專案。

下面是我研究的具體過程,不想看過程的同學可以直接跳到末尾看總結。

geoserver外掛

先研究了geoserver外掛,還真有。

geoserver有個mbtiles的擴充套件外掛(https://docs.geoserver.org/latest/en/user/community/mbtiles/index.html),支援對.mbtiles檔案的讀寫。

geoserver 安裝 mbtiles 外掛的教程可以參考這篇:https://blog.csdn.net/dyxcome/article/details/98375453

從官網下載外掛,安裝測試後,發現跟想的有點不一樣。

geoserver安裝完外掛後,新建資料來源的介面多了兩個 mbtiles 相關的選項,如下圖,上面的是釋出向量瓦片,下面的是釋出柵格瓦片。

我用第二個紅框,釋出柵格瓦片的選項,釋出了下向量瓦片,會報錯。

用第一個紅框,釋出向量瓦片的選項,可以走的通,但就是過程有點曲折,需要把 pbf 中的圖層再挨個釋出一遍。

.mbtiles 檔案中存的是處理好的 pbf 檔案,按說外掛只需要根據請求引數,從 sqllite 資料庫中查詢 pbf 檔案,返回給前臺就 ok 了。

但 geoserver 不是這麼做的,它是將 .mbtiles 檔案中的 pbf 瓦片作為向量資料來源來使用,類似於讀取 .mdb 檔案。

可以推理出,geoserver 內部的處理方式大概是:

  1. 先將 pbf 瓦片拼起來,讀取拼接後的各圖層原始資料
  2. 把圖層原始資料釋出成 geoserver 的向量瓦片服務
  3. 前臺呼叫向量瓦片服務時,geoserver 把資料處理成 pbf 檔案返回給前臺

怎麼說呢,這麼做和把 pbf 檔案直接扔給前臺相比,結果是一樣的,但就是感覺 geoserver 的戲太足,內耗太嚴重,還有就是這個發服務的操作過程也很麻煩。

只能說,這個外掛針對向量瓦片的設計,僅是用來讀取原始資料的,不適合用來發布資料。

java專案

再看 java 這邊。

在 github上搜了一下,找到了這個專案:mbtiles4j(https://github.com/jtreml/mbtiles4j)。

是個現成的 java 工程,拉取下來研究了一下,邏輯很簡單,就是直接讀取 mbtiles 中的瓦片返回給前臺,這一點很符合要求,美中不足的是,這個專案是針對柵格瓦片的,預設只支援 .png 檔案,不支援 .pbf

這個好說,有原始碼,改改就是了。

改完後發現,前端地圖不顯示,瓦片請求地址報 404 ,

將請求地址中的瓦片編號和 mbtiles 庫中的瓦片編號對了一下,確實沒有。

為啥呢?

哈哈,這個我有經驗,持續關注我們的同學還記不記的,我之前分享過關於 如何讓 maputinik 支援 geoserver 的問題,裡面最關鍵的一點就是設定 mapboxgl 請求瓦片的模式 scheme,模式包括 xyztms,預設使用 xyz

難道 openmaptile 生成的這個 mbtiles 檔案是按 tms 儲存的?試一下就知道了

果然 ~ 沒那麼簡單,地圖還是沒有出來,但瓦片可以請求到了,看來確實是 tms 的。

事後簡單翻了一下 mbtiles 規範,裡面有明確寫到,資料來源是以 tms 格式來儲存的。

看來還是要多研究標準規範和說明文件。

但為啥地圖還是沒有出來呢?

對比了下 tileserver-gl(下圖左) 和 mbtiles4j(下圖右) 的返回引數,發現了問題所在。

pbf 檔案是採用 gzip 壓縮過的,需要在返回引數中明確告知返回內容的型別是 gzip,而剛才將 mbtiles4j 中的png 改成 pbf 後,沒有加這個設定。

加上試試,哈哈,搞定。

這個通了,剩下的就簡單了,工程編譯成 war 包,直接扔到tomcat下就可以了。

大比例時地圖顯示

本來以為可以收工了,但瀏覽地圖時發現了另一個問題。

我的地圖只切到了14級,因為在向量瓦片中,14級包含的內容就已經很細了,所以沒有必要再往下切。

但用地圖瀏覽時,超過14級後,因為後臺沒有對應的瓦片,前臺就請求不到資料,地圖就不顯示了。

用 tileserver-gl 釋出同樣的 mbtiles 檔案,再用它的預設地圖檢視器瀏覽地圖,就沒有這個問題。

看來後臺需要把超過14級的請求引數處理一下,超過14級時,直接返回14級的瓦片。

翻了翻 tileserver-gl 的程式碼,並沒有找到相關的邏輯。

在同事的提醒下,發現 tileserver-gl 的預設地圖檢視器,它的前臺請求在超過14級時,是按14級來請求的,這說明我要找的邏輯是在前臺完成的。

去翻 tileserver-gl 的地圖樣式配置,和我自己的配置對比後發現,對資料來源設定 maxzoom 就可以解決這個問題。

看一下官網的解釋,大概意思是,如果你設定maxzoom=14,那麼當地圖縮放超過14級時,地圖仍然會使用14級的瓦片。

這個設定正是我要的。

我把改完後的後臺程式碼上傳到了github,方便以後遇到同樣問題的同學使用。

原始碼:

地址:http://gisarmory.xyz/blog/index.html?source=OSMMbtiles

總結:

  1. 本地釋出的OSM向量瓦片地圖,生成的向量瓦片存放在 mbtiles 檔案中

  2. 釋出mbtiles 中的向量瓦片,目前主流的方式是 tileserver-gl ,它基於nodejs開發的

  3. geoserver有個讀取 mbtiles 的外掛,但它針對向量瓦片的設計是用來讀取 pbf 中原始資料的,不適合用來發布資料。

  4. github上有個 mbtiles4j 的專案,java 開發的,稍加修改後,可以用來直接釋出 mbtiles

  5. mapboxgl 使用釋出的地圖瓦片時,需要設定資料來源的 maxzoom 屬性。


原文地址:http://gisarmory.xyz/blog/index.html?blog=OSMMbtiles

關注《GIS兵器庫》公眾號, 第一時間獲得更多高質量GIS文章。

本文章採用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議 進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名《GIS兵器庫》(包含連結:  http://gisarmory.xyz/blog/),不得用於商業目的,基於本文修改後的作品務必以相同的許可釋出。

相關文章