災害時アプリケーション
いつかくる大震災に向けて、大切な人とつながるスマホアプリケーションを開発するプロジェクトで、開発・設計・実装で考えたこと
基本機能
- iOS、Androidのアプリケーション
- データはクラウドに配置する
- 地震速報をアプリケーションにパブリッシュする
- その時にあらかじめ登録しておいた大切な人(以降、家族と記述する)の現在地が地震速報通知と一緒に通知する
- あらかじめ登録しておいた家族の現在地は、他人には見えない
- 地震速報の履歴が確認できる
基本設計
- クライアント、サーバーでhttp[s]通信をするViewアプリケーション
- クライアントアプリケーションは、iOS:Objective-C、AndroidはJava で開発
- サーバアプリケーションは、java.netty が利用されているvertx + mysql
- サーバはAWSに配置
- データアクセスは、全てStoredProcedure実装として、アプリケーションロジックはソースコードには含めない
特徴
地震速報をpush受信したクライアントアプリケーションは、地震速報と、家族の現在地を表示する。この表示のためのデータは、push通知のユーザテキストに格納している。また、家族の現在地は、刻々とスマホから通知、データベースにアップデートされている。
つまり、いつ来るかわからない地震速報に備えて、家族それぞれのスマホから通知される現在地情報を家族別の現在地情報としてデータベースに保存しておき、そのデータを地震速報をトリガーとして、家族位置情報を対象家族のみに配信するサービス
従来イメージ
本当に大震災が来た時に通信できるのか?
開発チームの面々はそれぞれ、特定アプリケーションにおけるtcp輻輳をFPGAとでなんとかしようとした人、RTOSで巨大なステートマシンを書いていた人、等雑多な経歴を持つチームでしたので、災害時でもアプリケーションが正常動作することについて、それなりに検討された
-
例えば、10万ユーザがアプリを利用すると仮定して、大震災が発生した時、同時にhttp[s]でそもそも通信できるのか?
- network-経路のどこかで、トラフィック過負荷によってパケットがドロップした場合、tcpがそれを検知して再送を行ったとする、そうすると、再送によってさらにトラフィック過負荷状況を悪化させる
- httpsに限定すると、証明書ハンドシェークフェーズのコストが大きいため、災害発生時にはSSL通信ではなく、udp/ip等軽量プロトコルとする必要がある
- 仮に、tcp, http,httpsで通信が確立されたとし、その後に各プロトコルにカプセル化した、アプリケーションデータを送信することになる、それは、重要な通信パケットの邪魔をすることになるのではないか
udp/ipを検討
tcpプロトコルスタックによって、輻輳状況が悪化すると仮定してtcp実装はやめて、NAT/over udpをプトロコルスタックを経由せずに、タイムスライスQOS、スケジューリングFIFO、netmap + Numa + MultiQueueNic 設計を検討した
双方向でのタイムスライス
スケジューリング
経路のスケールアウト
とはいえ、tcp(http[s])はデファクトスタンダードなので、tcpプロトコルスタックは利用することとし経路を分散:スケールアウトする。
その上で災害発生時の通信回数、通信パケットを最小限にすることを検討した
イベントドリブン差分配信
災害発生時シーケンス
差分変更通知シーケンス
実装設計の落とし所
- GAE + DataStore + FCM
- TaskQueue(家族ハッシュで分散)
- Queryは使わない(遅い、価格が、心配)、key-valueのみ
- エンティティのリンクは利用しない(遅い、結局Commitタイミングが、)
- golang
いろいろ検討したけれど
ストレス評価を実施し、運用コスト(普通にサーバコストと、理想の実装udp+...とした場合の人的コスト)を考慮すると、GAE + イベントドリブン + 経路負荷分散(スケールアウト)は、現実的な落とし所であると、納得