自己紹介
AWS Community Builder - Serverlessの@Kanahiroです。Geospatial Specialistとも名乗っています。GeospatialとAWSを組み合わせて日々おもしろげなことをしたいと考えています。
はじめに
地図タイルとはWebで地図データを効率的に配信する仕組みです。
https://maps.gsi.go.jp/development/siyou.html
地図を上記のような方法で分割していき出来上がる「タイル」という単位で地図データを配信します。これにより①キャッシュ活用しやすかったり、あるいは、②事前にタイルを作っておくことができる、というメリットがあります。
https://docs.google.com/presentation/d/1njywmoBjWeviNAipJasMDLQrPHedMvhICZzAa_KhPpo/edit?usp=sharing より地図タイルのうれしさを語ったスライド
私は地図タイル配信が趣味なので、同じく趣味のひとつであるAWSと組み合わせて、サーバーレスなタイル配信を試みてきています。本記事ではタイル配信のいくつかのパターンごとに、AWSでサーバーレスにタイル配信する手法を紹介します。
タイル配信のパターン
2つの軸でパターンを区別します。
1. Static Tiling / Dynamic Tiling
https://developmentseed.org/titiler/user_guide/dynamic_tiling/
Static Tilingとは、事前に全てのタイルを作成しておくアプローチです。
https://developmentseed.org/titiler/user_guide/dynamic_tiling/
一方のDynamic Tilingは、リクエスト時にタイルを生成してレスポンスするアプローチです。
これらはWebフロントエンドにおける、Static Site GenerationとServer Side Renderingとちょうど同じ違いです。それと話が違うのは、地図タイルを生成するコストの方が遥かに大きいことです(タイルの数が膨大かつ1タイルあたりのコストも大きい)。ゆえに、Static Tilingで事足りるならばそうすべきです(Dynamicに配信するためのコストは大きい)。
2. Raster Tile / Vector Tile
https://commons.wikimedia.org/wiki/File:Raster_vector_tikz.png
Vectorは頂点がなす図形、Rasterはグリッドデータ(=画像)です。ラスタータイルの実体はPNGファイルなどの画像、ベクタータイルはMapboxVectorTileという仕様のプロトコルバッファです。これらはどちらかが常に優れているというものではなく、目的によって利用すべき形式が異なります(例:航空写真の地図タイルは当然ながら画像、ラスタータイルとなる)。
この2軸でタイル配信のパターンを分類するとこうなります。
- Static Raster Tile
- Static Vector Tile
- Dynamic Raster Tile
- Dynamic Vector Tile
ここで、1と2はタイルの作成方法を除き同様の方法で配信できます。なので3通りの配信方法を整理します。
Static Tile
Amazon S3にPMTiles形式1でタイルを配置し、必要なタイルデータだけをHTTP Range Requestsで取得する手法がベストプラクティスです。以下に参考実装があります。
https://github.com/Kanahiro/litiler
要点
- 地図タイルはPMTiles形式で作成し、Amazon S3に保管
- AWS LambdaでS3のPMTilesに対しRange Requests
- ラスタータイルでもベクタータイルでも同じ構成
クライアントがPMTilesに直接HTTPリクエストを行うことも可能ですが、①PMTilesは隠蔽したい②認証ロジックなどを仕込みたいということはよくあるので、上記のようにサーバーを介するパターンをベストプラクティスとして紹介しています。
Dynamic Raster Tile
このパターンを十分に理解するためには地図のレンダリングを多少理解する必要がありますが、この記事ではそこは深掘りしません。あくまでAWSでサーバーレスにやる方法にフォーカスします。
まず現在において、このパターンで用いられるソフトウェアはだいたい以下になります:
MapServerは古き良き地図レンダラーです。何も統計はとってないですが、国内でラスタータイルをdynamic tilingしてるケースでは、まだこれが使われてるケースが多いと思います。ただもはや、新規で採用するようなソフトウェアでもありません。
TileserverGLは、MapLibre Style2をラスタータイルとして配信するためのサーバー実装です。
Dynamic Raster Tileにはだいたいこのいずれかのソフトウェアが利用されますが、いずれもサーバーレス環境では使いづらいです。これは、サーバーレス環境へのデプロイがややこしいということもありますが、いずれもファイルシステムに依存するためサーバーレス環境と相性が悪いです。
なので作ったのがこのサーバー実装です。サーバーレス環境での利用を想定していて、AWS Lambda + Amazon S3みたいな環境下で十分なパフォーマンスが出るような工夫をしています。AWS CDKのサンプルも含んでいるのですぐにデプロイ可能です。
このデモページでは実際にAWS Lambdaでタイルをレンダリングして配信しています。お金はかかっていません。地図画像のレンダリングは本質的にコストが高い処理ですが、Lambdaの高い並列性が高速なタイル配信に活きます。
要点
- あまりサーバーレス向けの選択肢がない(ので作った)
- 地図タイル画像生成という、リクエストが多くて計算コストが高い処理はサーバーレスでやれるとうれしい
- そもそもdynamicにラスタータイルを配信したいケースはあまり多くはない。でも稀によくある。そういうときにサーバーレスに動かせるとコストが安くすむ。
Appendix: Cloud Optimized GeoTIFF3のタイル配信
前述のMapServer/TileserverGL/chiitilerは、なんらかのデータがあってそれをデザインした地図画像を生成するための道具です。一方で昨今活用が進む衛星画像などのラスターデータをdynamicにタイル配信する際に利用できるのがTiTilerです。Lambdaで動かすためのドキュメントも整備されています。S3にあるCloud Optimized GeoTIFFからタイルを配信するというのが典型パターンになります。
Dynamic Vector Tile
このパターンは事実上一択で、PostGIS(PostgreSQLのExtension)へのクエリの出力形式をMapboxVectorTileにする手法です(ST_AsMVT4)。
なのでデータベースが必要となりその部分はサーバーレスには出来ません。Amazon Aurora DSQLがもしGeometryをサポートするようなことがあればちょっと話が変わってきますが、2024年のre:Inventのリリース以後、2025年のre:Inventでも音沙汰なしでした。あまり期待はしないことにしています(チラッチラッ
SQLを投げられれば良いので、もはやコンピューティングはなんでも良いわけですが、Lambda向けのサーバー実装が存在するため紹介します。
Martinはさまざまなデータソースを地図タイルとして配信することにフォーカスしているサーバーです。ドキュメントにAWS Lambdaへのデプロイについて言及があります。
コンテナランタイムを利用するようです。なお筆者は試したことがありません。
もちろんMartin自体を動かして検証したことはあります
https://qiita.com/Kanahiro/items/919e20329ecc9d1f1513
データの取り出し・MVTへの変換をデータベースに委ねるため、データベースの速度・負荷がボトルネックとなります。一見、理想のパターンに思えますが軽々に取るべき選択肢ではなく、十分な考慮にもとづく設計が必要です。
要点
- PostGISとST_AsMVTを利用することで、データベースからMVTでデータを取り出す
- データベースにMVT生成まで計算させることになりコストが高い
宣伝
地図寄りの議論はこの本を読むと理解が深まるかもしれません(セルフマーケティング)