Edited at

ラスター地図タイルサーバーを作ってみた


はじめに

静的地図サービスを作ってみた の派生でできた ラスターマップ の説明です。


地図タイルとは?

Google Maps をはじめ様々な地図サービスで採用されている、地球を正方形のタイルで表現するための仕組みです。

詳細は 国土地理院 地図タイル仕様OSM のタイル をご覧ください。


image.png

国土地理院 地図タイル仕様 より引用



開発


地図タイルサーバー

任意の範囲の地図の描画の機能は 静的地図サービスを作ってみた で実装済みなので、残りは {style}/{z}/{x}/{y}{r}.{ext} から緯度経度の範囲に変換して、描画した地図を返すだけです。

{r} は Retina Display 用のパラメータで、@2x などの値が入ります

{ext} は今回は png です。


表示側

Leaflet を利用しています。

もともと地図描画のデバッグ用に作ったものなので、右クリックで OSM の編集画面を開きます。


パフォーマンスチューニング


地図タイルのキャッシュ

リアルタイムで地図描画した結果を返しているのですが、地図データ自体はそれほど頻繁に変わるものではない(というか更新の予定がそれほどない)ので、上記の描画結果を HDD にキャッシュとして保存するようにしました。


  1. キャッシュが見つかった場合はそれを返す

  2. 地図を描画し、キャッシュに保存し、返す

という流れです。


地図タイルのキャッシュの最適化

生成された png ファイルを zopflipng を利用してバックグラウンドで最適化したものを別のキャッシュとして生成しています。


  1. zopflipng キャッシュがあればそれを返す

  2. 自分で生成したキャッシュがあればそれを返す

  3. 地図を描画し、キャッシュに保存し、返す

という感じです。

zopflipng は --iterations=20 --filters=0me オプションを指定していて、地図画像の場合は概ね30%程度サイズを減らすことができています。


地図タイルサーバーの並列化

サーバープログラムは QtHttpServer を雑に使っていて、1プロセス1スレッドで動くようなものになっています。

それを GNU parallel で10プロセスほど動かし、nginx の upstream に指定して動かしています。


データベースの速度の改善

データ量の関係で、DB の本体は HDD 上で動かしているのですが、地図描画時の問い合わせで IO がボトルネックになっていたので、PostgreSQL の ロジカルレプリケーション 機能を利用して、描画時に必要なテーブルのみを SSD 側に複製し、そちらを参照するようにしました。


TODO

フロントエンドは daemon 化をするなり Docker 化をするなりして、もう少し雑さを減らしたい。