Sputnikマップチームは 、OpenStreetMapデータに基づいてマップを開発しています。 この記事では、タイルをレンダリングするためのソリューションのアーキテクチャについて説明します。
マップバックエンドはMapnikライブラリを使用してGoで記述されているため、Gopnikという名前を付けました。 GopnikソースはGithubで入手できます。
openstreetmap.orgサービスのアーキテクチャには、多くのコンポーネントが含まれています。
詳細を無視すると、3つの主要な部分があります。PostgreSQLデータベース、データのロードと編集のためのAPI、およびマップレンダリングシステムです。
OSMデータに基づいてマップを作成するには、データベースとレンダリングシステムのコピーを保持する必要があります。
オンラインマップの作成に関する一般的な問題に触れます。 現在、いくつかの表示テクノロジーがあります。サーバーがクライアントに完成した画像を提供するときのオプションから、クライアント側でダウンロードしたデータを視覚化するオプションまでです。 タイルカードは現在最も人気があります。 タイルは、マップセクションのある小さな正方形の画像です。 クライアントはサーバーからタイルをダウンロードし、タイルを単一の画像に接着します。
このテクノロジーは実装が簡単で、クライアント側の負荷を最小限に抑えます。 もちろん、欠点がないわけではありませんが、このような技術の使用は今後長い間正当化されると思われます。
OpenStreetMapの世界では、タイルマップのスタックは3つの柱に支えられています。
データベース(ほとんどの場合PostgreSQL)。
レンダリングライブラリ(通常Mapnik)。
クライアントjavascript-library(ほとんどの場合-Leaflet)。
これらのテクノロジーを組み合わせるには、必要に応じてデータを補完し、アイコンを追加し、描画スタイルを説明し、タイルの生成とキャッシュを構成するために、いくつかのことが必要です。
スタイルを開発して、データの完全性と認識の容易さの両方を達成したいと考えました。 美しさの価格は技術的に複雑になっています。 このスタイルは、openstreetmap.orgスタイルの約2倍の複雑さと重さでした。
その結果、タイルの更新には長い時間(約5日間)がかかり、大量のデータ(約2 TB)をキャッシュする必要があります。 これはすべて、人生を大きく複雑にします。
ほとんどの場合、レンダリングスタックは、mod_tileプラグインとタイル生成に直接関係するバックエンド(TirexまたはRenderd)を備えたApache HTTPサーバーに基づいて構築されます。
このスキームは時を経てテストされました。これが、maps.sputinik.ruの最初のバージョンの仕組みです。 しかし、彼女が私たちに完全に合ったとは言えません。 最初に思いついたのは、タイルキャッシュにクラウドストレージを使用することの難しさでした。 mod_tileはファイルシステムに着目して開発されたものであり、最終的な整合性機能を使用することは、重大な修正なしでは完全に不可能です。 さらに、レンダリングバランシングスキームにはいくつかの欠点があり、複数のデータセンターの環境で使用することは困難です。 また、通常のユーティリティは特に便利ではありません。
私たちは実験を行いました。私たちはシステムのプロトタイプをスケッチして、私たちが望んでいたことを正確に実現しました。 プロトタイプが定着し、さらに開発されました。 コアでは、システムはmod_tileアーキテクチャをほぼ繰り返し、いくつかの拡張と追加を行います。 Mapnikライブラリを使用してGoで記述されており、その名前はGopnikです。
Gopnikは、任意のノード数に応じて簡単にスケーリングでき、さまざまなストレージシステムを使用でき、プラグインを使用した拡張をサポートします。
Gopnikは、ディスパッチャとレンダリングの2つのコンポーネントで構成されています。 Dispatcherはユーザーからのリクエストを受信し、キャッシュ内のタイルの存在を確認し、必要に応じて、ハッシュ座標関数によってクラスター内の適切なノードを選択し、タイルを生成するタスクを設定します。 レンダリングは直接レンダリングを提供します。
リポジトリとの対話の問題には特に注意が払われます。 問題は、ユーザーがタイルを1つずつ要求することです。 サーバーは、リソースを節約し、個々の画像を接続する際の問題を軽減するために、すぐにカードの大きな領域(通常は8x8タイル+追加のバッファー)を生成します。 この領域はメタタイルと呼ばれます。 Gopnikは、ユーザーからのリクエストをメタファイルでグループ化します。キャッシュに保存されていないメタファイルに対して初めてリクエストが行われると、レンダリングが開始されます。 後で受信したすべての要求は待機に追加されます。 レンダリングが完了すると、保留中のすべてのリクエストに対してタイルが返され、バックグラウンドキャッシュが開始されます。 さらに、クライアントが新たに生成されたメタファイルから他のタイルを要求する場合、レンダリング結果は一定の(カスタマイズ可能な)時間の間、ノードのローカルキャッシュに保存されます。ローカルキャッシュは、保存の確認をサポートする場合、ストアに完全に保存されるまでデータを保持することもできます
ただし、オンザフライでは、データの量が制限されているマップの一部のみを生成できます。 それ以外の場合は、事前にタイルを準備する必要があります。 Gopnikには、このための特別なユーティリティセットがあります。
インポーターユーティリティを使用して、生成計画が準備されます。 Prerenderはプロセスを調整します。 事前レンダリングスレーブノードクラスターは直接レンダリングします。
システムは分散されており、ネットワーク障害およびスレーブノード障害に耐性があります。 コーディネーターは単一障害点ですが、レンダリングログのため、プロセスは障害点から続行できます。 このソリューションにより、適切なレベルのフォールトトレランスを確保しながら、複雑で完全に分散されたシステムを回避できます。
Githubのソース
ドキュメント
Highload ++ 2014でのMaxim Dementievのレポートに基づく