之前我們分享過如何 在本地釋出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 內部的處理方式大概是:
- 先將
pbf
瓦片拼起來,讀取拼接後的各圖層原始資料 - 把圖層原始資料釋出成 geoserver 的向量瓦片服務
- 前臺呼叫向量瓦片服務時,geoserver 把資料處理成
pbf
檔案返回給前臺
怎麼說呢,這麼做和把 pbf
檔案直接扔給前臺相比,結果是一樣的,但就是感覺 geoserver 的戲太足,內耗太嚴重,還有就是這個發服務的操作過程也很麻煩。
只能說,這個外掛針對向量瓦片的設計,僅是用來讀取原始資料的,不適合用來發布資料。
java專案
再看 java 這邊。
在 github上搜了一下,找到了這個專案:mbtiles4j(https://github.com/jtreml/mbtiles4j)。
是個現成的 java 工程,拉取下來研究了一下,邏輯很簡單,就是直接讀取 mbtiles
中的瓦片返回給前臺,這一點很符合要求,美中不足的是,這個專案是針對柵格瓦片的,預設只支援 .png
檔案,不支援 .pbf
。
這個好說,有原始碼,改改就是了。
改完後發現,前端地圖不顯示,瓦片請求地址報 404 ,
將請求地址中的瓦片編號和 mbtiles
庫中的瓦片編號對了一下,確實沒有。
為啥呢?
哈哈,這個我有經驗,持續關注我們的同學還記不記的,我之前分享過關於 如何讓 maputinik 支援 geoserver 的問題,裡面最關鍵的一點就是設定 mapboxgl 請求瓦片的模式 scheme
,模式包括 xyz
和 tms
,預設使用 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
總結:
-
本地釋出的OSM向量瓦片地圖,生成的向量瓦片存放在 mbtiles 檔案中
-
釋出mbtiles 中的向量瓦片,目前主流的方式是 tileserver-gl ,它基於nodejs開發的
-
geoserver有個讀取 mbtiles 的外掛,但它針對向量瓦片的設計是用來讀取 pbf 中原始資料的,不適合用來發布資料。
-
github上有個 mbtiles4j 的專案,java 開發的,稍加修改後,可以用來直接釋出 mbtiles
-
mapboxgl 使用釋出的地圖瓦片時,需要設定資料來源的 maxzoom 屬性。
原文地址:http://gisarmory.xyz/blog/index.html?blog=OSMMbtiles。
關注《GIS兵器庫》公眾號, 第一時間獲得更多高質量GIS文章。
本文章採用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議 進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名《GIS兵器庫》(包含連結: http://gisarmory.xyz/blog/),不得用於商業目的,基於本文修改後的作品務必以相同的許可釋出。