速くて運用コストが低い位置情報検索アプリを作るときのベストアーキテクチャは?

  • 23
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

mixiグループアドベントカレンダー9日目です!

ちょっと前に個人的に開発したアプリで得られた、位置情報検索関連の知見について共有しようと思います。

今回ご紹介するのは、位置情報を使って現在地付近の特定の場所を検索するようなアプリを作ることを考えた場合に、こう作っておけば間違いないんじゃないかと思うアーキテクチャです。
これから会社でも個人でも、位置情報を利用したアプリを作ろうと考えている方の参考になれば幸いです。

まず、アプリに求める要件を書き出します。

要件

  • 地図を画面全体に展開するタイプのアプリで、画面内に表示対象(建造物など)がある場合はそれを表示する
  • 地図をドラッグして動かせる。動かしている間でも表示対象があればそれを表示する
  • 個人的なアプリでも大丈夫なように、運用コスト(時間やお金)がかからない

設計を考える前に

位置情報検索を行おうと思った時、すぐに考えつくのは Elasticsearchなどを用いたものでしょう。
クライアントで表示している矩形領域の位置情報をサーバーに送り、サーバー側で先に挙げたElasticsearchなどを用いて範囲内にある表示対象を検索します。しかしこの設計では、上に挙げた要件を満たせないことがわかります。

例えば、ドラッグ中であっても表示対象を更新できるようにするためには、そのまま作ると地図が動く度にサーバー側にリクエストが飛び、1ユーザーからのリクエストがとんでもなく多くなってしまいます。
これではサーバー側の負荷が心配なだけでなく、金銭面でもコストが高くなりそうです。

設計案

サーバー側で検索処理を実行してクライアントに結果を返すアーキテクチャだと、更新頻度が多い場合にはどうしてもNetwork I/Oが気になります。逆に考えると、Network I/Oがいっさい発生せずに検索できれば、高速に検索結果を表示できるし、サーバー側のコストも下がるのではないでしょうか!?
そこで今回紹介するアーキテクチャパターンはクライアント側ですべてを完結させる手法になります。
クライアントで完結させることで、次のようなメリットがあります

  • 通信が発生しない
  • 高速
  • サーバー側の運用コストがほぼ0

通信が発生しないので、オフライン時でも検索結果を表示することができます(地下鉄で圏外になっても検索できる!)。
クライアントで検索処理を実行するため、Networkを介さないぶんとても高速に検索結果を得ることができます。
当然サーバー側の負荷も上がらないため、利用者が増えても問題なしです。

まさに 速い!安い!最高!ですね。

ひとつ、クライアントで完結させる際に気になる点として、表示対象データの更新タイミングをどうするかというのがあると思います。これは、位置情報検索で利用する検索対象に建造物が多いこと(更新頻度が多くない)から、一日に一回程度バックグラウンドでデータを取得しなおせば済むとわかります(実際はもっと頻度を下げて良いと思います)。
仮に人物の位置情報などの動的な検索対象を扱う場合でも、データの更新タイミングを調整しさえすれば、クライアント側で処理したほうが良いケースがほとんどだと考えています。

あとは実装方法を考えるだけです。
...が!しかしここでひとつ問題があります。
iOSは当然の事ながらデーモンプロセスの起動ができないため、位置情報検索エンジンとアプリケーションは同一プロセスでなければなりません。

そこで今回自分が目をつけたのがGroongaです。

Groonga !?

Groongaは自然言語処理で用いられることが多いですが、位置情報検索機能も備えています。
よくElasticsearchと比較されているので、比較記事を読まれた方も多いかもしれません。
特筆すべきはGroongaがファイルベースのアーキテクチャを採用している点で、SQLiteのようにデーモンを立ちあげずに利用することができる点です。(本当はRealmに位置情報検索機能があったらなーと思いましたが、まだ実装されていないようです)

しかしGroongaに関してもモバイル用途での利用などは当然ながら考えられていないため、
iOS/Androidから利用するには一手間加える必要があります。
ですが、GroongaはC言語で書かれているため、軽微な修正でアプリに統合できますし、
ドキュメントは少ないですが、サンプルコードは結構あるのでそちらを参照しながらC APIを駆使して実装することができます。

まだライブラリとして完成されてはいませんが、参考までに自作アプリに組み込んだ際に実装したものを公開します。
この記事で興味を持って頂けた方は https://github.com/goccy/iroonga を参照されると、C APIとのつなぎ込み部分などを理解して頂けると思います。

さいごに

メリットばかり書きましたが、デメリットもあります。
データをクライアント側にすべて置くため、ストレージ使用量が大きいことです。
(実はこれはGroongaが参照するファイルをgzip圧縮することで、劇的に減らすことができるとわかっています)

そこで我こそは!と思う方がいれば、
冬休みを使ってストレージも食わない、モバイル用途の高速な位置情報検索エンジンを作ってみるのも面白いんじゃないでしょうか!?

明日は、radioboo さんが面白い記事を書いてくれますよ!