【セッションレポート】Nature Remoの裏側 ~ AWSとWeb技術をIoTの世界でフル活用する【#AWSDevDay】

2019.10.04

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

AWS DevDay Tokyo 2019 Day2 で開催された「Nature Remoの裏側 ~ AWSとWeb技術をIoTの世界でフル活用する」についてレポートします。

目次

セッション情報

スピーカー:Nature 株式会社 松木 雅幸 氏

セッション名:Nature Remoの裏側 ~ AWSとWeb技術をIoTの世界でフル活用する

Nature Remoは家庭のWifiに接続し、家電の操作を自動化するIoTスマートリモコンです。販売累積10万台を越え、多くの家庭の重要なインフラにもなりつつあるNature Remoですが、それらをリアルタイムに確実に動かすために、堅牢なクラウドシステムが必要です。とは言え、Nature RemoのシステムはGoで書かれた素朴なWebシステム群で、Amazon ECS、Amazon RDS、Amazon ElastiCache、AWS Lambdaといった普通のコンポーネントを組み合わせて作られています。それらの組み合わせてスマートフォンアプリやスマートスピーカーからの操作をどのようにリアルタイムにデバイスに反映させているのか、といったことを例に挙げながら、現在のシステム構成や開発フロー、現在の課題や今後の展望についてお話します。

アジェンダ

  • Nature及びNature Remoの紹介
  • Nature Remoのシステムアーキテクチャ紹介
  • ECS活用事例
  • 現在の課題
  • その他の細かい取り組み

会社と製品

  • Nature Remoでできること
    • 外出先からエアコンや電気をスマホから操作できる
    • 赤外線で家電を操作している
    • センサーが搭載されているので室温に合わせて自動で調節する機能がある
  • 2年弱で10万台突破
  • 今後の展望
    • 2019年現在 - 家電操作
    • 2020年 家の電力の最適化
    • 2022年 ユーザがP2Pで電力交換できるプラットフォーム
  • Nature Remo E
    • 現在開発中のスマートエネルギーハブデバイス
    • 家庭の太陽光発電や蓄電池を操作したりモニタリングを行う
    • いずれは機械学習などで最適化を行う予定
    • ECHONET Liteプロトコルを採用
      • 日本国内のスマートメータとHEMSをつなぐ標準プロトコル (経産省認定)
      • 家庭のWiFiにつないでUDPやWi-SUNなどで通信
    • スマートメータは実はほぼすべての家庭で利用可能

Nature RemoとGo

機能

  • IoT製品のスマートリモコン
  • スマートフォンやスマートスピーカから家電操作
    • エアコン・TV・ライトなど
    • 既存の赤外線リモコンをそのまま置き換えられる
    • かんたんなリモコン学習(検出)機能
  • センシングやユーザの位置情報をもとに家電操作
    • 温度、湿度、家から離れたとき、近づいたときなど

前提

  • Nature Remoは自宅のWi-Fiに接続してローカルIPを持つ
    • インターネット側からのリクエストを受け付けるのは容易ではない
  • 屋外のスマホ、スマートスピーカー、ルールなどに対して素早く反動する必要がある
  • Nature Remoはマイコンボード上でCのFirmwareが動作している
    • あまり複雑なことはさせたくない

どうやって実現する?

  • UPnPなどによるポート開放とDDNSの組み合わせ
    • 機器をインターネットにさらすのは怖い
  • UDPホールパンチングなどのNAT越え技術を用いて、スマホから家の中の機器を操作
    • かっこいいが接続維持が難しそう。特に移動体(スマホ)

実際の仕組み

  • スマホ -> HTTP API -> クラウドにあるシステム -> WebSocket -> Nature Remo
  • スマホアプリからはAPIリクエスト (開発者向けのAPIも提供)
  • Nature RemoはWebSocketで常時接続している
  • シンプルな仕組みで動作している

なぜWebSocketなのか

  • リアルタイムの双方向通信がお手軽にできる
    • 「普通」のWeb技術なので扱いやすい
  • 双方向に通信したい理由は、Nature Remoから温度、湿度のデータが送信されている。サーバからは赤外線を出すような命令がいく。
  • 接続や切断時の再接続はNature Remo側が制御
  • 常時接続になるため接続管理が割と大変ではある
    • 10万台 + 増加の一途
    • 増加にどう対応するかという課題はある

アーキテクチャ

  • ほぼAWS上で構築している
  • ECS上に3つのコンポーネント(Goアプリ)
    • Worker : ルールの実行
    • API : スマホアプリやスマートスピーカーとの通信
    • Stream : Nature RemoとのWebSocket通信
  • スマホからNature Remoを操作する場合
    • スマホ -> ALB -> APIサーバがRedisへPublish -> StreamがRedisをSubscribe -> Nature Remo

Remarkable Points

  • 素朴なGo製のWebアプリ
  • Redis Pub/Subを用いた、API - Stream間のやりとり
  • Consulによるサービスディスカバリとコネクション管理
  • AlexaのカスタムスキルはAWS Lambda経由で実行

Simple Web Application with Go

  • 普通のWebアプリケーション
    • もともとherokuでホストしていた名残も
  • フレームワークは使わずGorilla web toolkitを部分的に利用
  • MySQL / Redis
  • gorp / redigo
  • DynamoDB
    • guregu/dynamo

Utilize Redis Pub/Sub

  • APIからはRedisにPublish
  • StreamはRedisをSubscribe
  • 相互通信しない疎結合を実現している
  • Steam側はあくまでWebSocketとRedisからのSubscribeで受けた命令の実行しか行わず状態を持たない

Service Discovery with Consul

  • 歴史的な経緯によりNagure RemoはALBへの直接接続が困難
  • NginxからProxyしてStreamサーバに接続している
    • NginxでTLS終端とWebSocketのProxyを実施
    • エフェメラルポートの都合上、6万接続程度が上限
    • 接続数が少ないサーバにNature Remoは接続
    • 接続先を返すAPIをコールし、返却されたIPにWebSocket接続
      • Consulを使ってディスカバリを実現

ECSを用いたコンテナ活用

  • ほとんどのサービスをECS上で動かしている
  • GoでDockerイメージを作成するのは簡単なのでECSが便利

CI/CDの流れ

  1. GitHubにpush
  2. CircleCIでテスト、ビルド
  3. ECRにイメージプッシュ
  4. ecspressoでデプロイ

ecspressoでのデプロイ

  • github.com/kayac/ecspresso
  • ecs-deployから乗り換え
    • ecs-deployからの乗り換え先としてちょうどよい
    • 既存のタスク定義を使える
    • シームレスに移行可能
  • CircleCI上で実行してデプロイ
  • タスク定義の修正がリポジトリ内で完結できてよい
  • サイドカーの更新やパラメータ変更がレビューできるようになったのが良かった

課題や今後取り組みたいこと

Nginx Proxy

  • 歴史的経緯によりNature RemoはALBに接続できない
  • Nginxに直つなぎしている
    • Nginxはstreamにproxyしているのでエフェメラルポートの関係で6万接続程度が上限
    • コネクション数管理が煩雑!
  • ALBに一本化したい
    • DNSベースで自動で内部のノード増やしてくれるのがいい

サービスディスカバリ

  • Consulのサービスディスカバリはかっこいいが不安定になることも
    • Consulのバージョンも古い
  • Cloud Mapなどに切り替えていきたい

Streamの再接続問題

  • steramをdeployすると一斉にNature Remoとの接続を切断することになるため再接続ラッシュとなる
    • 一時的にAPIが過負荷気味になる
  • コンテナがコネクションを維持したまま、ローリングで入れ替えていく方法を模索中

ログモニタリング

  • uber-go/zap でJsonログをCloudWatch Logsに送信
    • CloudWatch Logs Insightも安定してきて原理
  • CloudWatch LogsのAWS利用費に占める割合が高いので安くなることを期待
  • 一部のログはアプリから直接Firehose経由でS3へ送信
    • Athenaで調査
    • Firehoseがたまに一時的にエラーが続くことに困っている
  • 改善したい

AWSの活用

  • AWS IoT
    • 無理して使う必要はないと考えているが、選択肢を広げて必要応じて使いたい
  • 機械学習系機能
    • ユースケース
      • 室温や快適度の自動調整
      • 電力の最適化や需給調整

RDB Migration

  • gooseを利用
    • 積み上げ式のMigrationはいまいち
    • メンテもと滞っている
    • マスタデータ入れるのもやっているので若干借り換えづらい
  • schemalex/schemalexに乗り換えたい
    • sqldefでも良いがschemalexは社内に作者がいる

持続可能な開発のために入社後に取り組んだこと

Go Module導入

  • depから移行

Dependabot導入

  • depandabot.com
  • 依存ライブラリのバージョンが上がっていたらpull requestを起票してくれるサービス
    • GitHubが買収して今は無料で使える
  • とにかく依存ライブラリは最新にし続けたいので便利
  • Go対応正直微妙な部分も...
    • 頑張ってほしい...
    • 起票後CircleCI上でgo mod tidyを走らせるなどの工夫もしている
    • アップデート当番のアサインも自動化

git-pr-release自動化

  • developブランチにfeatureブランチマージしたら勝手にリリースpull requestが生えてきて便利

ECS Scheduled Task管理のためのツール ecsched を作っている

  • GitHub - Songmu/ecsched
  • バッチ類は、ECSのScheduled Taskを利用しているが、それをバージョン管理したいという動機

まとめ

  • サーバサイドはほぼ全てGo
  • 実は割と普通のWeb技術を使って実現している
  • インフラはAWSに寄せているし、もっと寄せたい
    • 本質的なサービス開発に注力したい
  • WebSocketの接続管理がチャレンジング
    • サービスも急成長中
  • 開発体験を上げるためにも色々やっています