KDL BLOG
先日ニュース発信した、位置情報を使った体験型ゲームのアプリケーション開発において、Azure SignalRというサービスを利用してFLUXというアプリケーションアーキテクチャを応用してみました。
FLUXとはFacebookが提唱しているアプリケーションの設計思想で、 データの流れを単一方向に限定することを特徴としています。今回は実際のゲームアプリ開発でデータを単一方向にした設計の経緯、セキュリティに関する考察、所感などをご紹介します。
ゲームの概要
ゲームの体験レポートをこちらのブログでご紹介していますが、施設内に複数設置されているBeacon検知器が、BLEタグを持っているゲーム参加者の位置を検知し、ゲーム画面や分析画面で確認できる、というものです。ゲーム画面には、来場者の歩いた経路や、距離や時間をもとに運動量を、分析画面にはユーザーの動線や検知回数、検知時間などを表示します。
アプリケーションの設計
このようなアプリケーションを設計する場合、従来は、中央にサーバーを配置し、Gatewayが検知したBeaconの位置情報をサーバに送信して蓄積し、アプリ側はサーバに問合せをして履歴の取得・更新をする、という中央サーバー型設計が一般的だったと思います。
まずは、サーバーレス化。Gateway側とアプリ側のAPIをサーバーレスのFaaS(Function as a Service)に置き換えて、DBもサーバーレスのデータベースに置き換えます。この程度は主流になってきたサーバーレスの考え方だと思います。
リアルタイム通信への道
Gateway側はソラコムさんの回線を用いており(※)、受信した大量のビーコンデータはエッジ側で重複データを取り除いた後にクラウドに送信しています。(※KDLは少ない初期コストで IoTを実現する「SORACOM」のSPSインテグレーションパートナーです。)
一方で、アプリ側ではデータがいつ更新されたか分からないため、通常は定期的にクラウドに問い合わせをしてデータを取得する必要があります。しかしこの方法では無駄な呼び出しやタイムラグが発生してしまうという課題があり、あまりスマートではありませんね。
・・・そんな大きな問題じゃないかもしれない・・。
でも・・・
せっかくなのでできるだけリアルタイムに通信したい!!
(とエンジニア魂に火が付いたワケです)
リアルタイム通信といえば、websocketを思い浮かべる方も多いと思います。
サーバーがある設計であれば、確かにwebsocketを利用して実装するところですが、サーバーレスの場合は処理の実行時間に制限があるため、勝手が違ってきます。
リアルタイム通信をFaaSで実現
そこで課題の解決の一案として今回採用したのが、Microsoft Azure SignalR Service です。Azure SignalR Serviceとは、WebSocket / Server Sent Events / Forever Frame / Ajax long pollingなどを駆使してリアルタイム通信を実現するAzureサービスです。詳細は本家サイトをご覧いただくとして、これを利用した場合はこの感じになります。
アプリ側とアプリ側のServerless FunctionsまでのコネクションをAzure SignalRでつなぐことで、アプリ側からの無駄な呼び出しがなく、タイムラグも軽減できます。
うーん。まだなんだかもやもやする。
もっと工夫することがあるんじゃないか?
データを一方通行に流す
アプリ側の更新を、Gatewayからデータを受信する側のFunctionsに反映してみました。従来はDBを中心にデータをやり取りしていましたが、よく考えてみればその必要はないことに気がつきます。するとなんということでしょう。匠の手によってデータの流れは下りのみとなり、シンプルで美しいフローへと生まれ変わりました。
まず、Gateway側で行われるデータの作成や変更を、要件や仕様に基づいて洗い出し、Functionsに落とし込みます。アプリ側の変更もかならずGateway側のFunctionsを通るので、一方通行で均一化され、アプリに反映されます。つまり同期も確実になりますね。これを実現可能にしたのは、Azureでした。
単一方向のデータフローがもたらすもの
シンプルな単一方向のデータフローがもたらしたものは次のとおり。
- メンテナンス性の向上
- パフォーマンスの向上
- スケーラブル性の向上
- VueやReactと相性がいい
単一方向のデータフローとしてはFacebookが提唱するアプリ開発向けのアーキテクチャー「FLUX」がありますが、サーバーレスとの相性が良さそうだと感じています。今回は、プロジェクトを俯瞰し全体に適用を試みた結果、プロジェクト全体におけるデータの一方通行が実現した事例です。
VSCode の開発体験が素晴らしい
今回の技術要素を整理してみると、なんとほとんどがマイクロソフトさんのサービスでした!
- APIサーバー : Azure Functions
- データベース : Azure Cosmos DB
- RT通信サーバー : Azure SignalR Service
- WEBサーバー : Azure Storage
- CI/CD : Azure DevOps
- 開発言語 : TypeScript
- フレームワーク : Vue.js
- 開発ツール : Visual Studio Code
一番素晴らしいのは、AzureとVisual Studio Codeとの連携です。VSCodeで豊富なAzureエクステンションが提供されているため、今回はこれらのエクステンションを活用して開発した結果、実装・デバッグ・テスト・デプロイは、完全に VSCode のみでストレスなく完結できました。開発体験が素晴らしいですよ、マイクロソフトさん!
Vue.js + Vuex(Flux)の利便性
Vue.jsはリアクティブ指向ビューフレームワークです。データをどのように表現するかだけを指定するだけで、データの変更は自動的にキャッチし、見た目に反映します。
Vue.jsには、単一方向のデータフローを実現する「Vuex」という標準プラグインがあります。このVuexでは、Vue.jsにおいてデータの変化を管理する標準モデルを提供していますが、今回はほぼこのデータフローをそのまま使うことができました。TypeScriptがデータの型を詳細に定義できるところも大変便利でした。
セキュリティ
今回のセキュリティについて考察してみました。
- サーバレスであること
Azureならば、マイクロソフトさんのグローバル レベルの高度なセキュリティをそのまま享受することができます。 - Azure Functionsの認証レベル
Azure Functionsには3段階の認証レベルがありますが、今回は一番強固な、APIごとに認証キーを設定する方法でセキュリティを高めました。 - Cosmos DBにおけるSQLインジェクション対応
Cosmos DBはNoSQLデータベースですが、AzureがSQLインタフェースも提供しており、そのプレースホルダー機能でSQL インジェクションを対策できます。
また、全体的にデータが一方通行のため、データが入ってくるところが必然的に絞られてくるわけですね。Azure Functionsを中心に見ていけば、セキュリティ対策を立てやすいと感じました。
CSP(Content Security Policy)への対応
Vue.js本体を組み込むだけでは、通常はCSPと衝突してしまいますが、Vue.jsのランタイムのみであればCSPに準拠しています。今回はそもそもビルド済みのアプリのみをデプロイするため、最初からビルド構築を自動化(CI/CD)しています。そのため、CSPが有効の状態で運用できました。
DoW攻撃対策
DoW(Denial of Wallet)攻撃とは
サーバーレスシステムでは、DoS攻撃やDDos攻撃(大量アクセスさせてサービスを機能停止させようとするサイバー攻撃手法)を受けても、自動でスケールアウトして処理してくれます。しかし、サービスの実行に伴って課金されるため、対処しないとあとで膨大な額の請求がくることになります。サーバーレスならではの脆弱性ですね。これを財布への攻撃という意味合いでDoW攻撃といいます。
今回は実装しなかったのですが、調べてみたところAzure API Managementというサービスで対処できるそうです。次に機会があれば、ぜひ使ってみたいと思います。
監修:チェン ハン
デジタルビジネス本部 エンジニア
筆者:松丸恵子
広報室