AWSマネージドサービスをフル活用したリテールメディアプラットフォームとSRE

この記事は、[CyberAgent Group SRE Advent Calendar 2023](https://qiita.com/advent-calendar/2023/ca-sre)の2日目の記事です。

# はじめに
こんにちは、
[Next Experts of AWS](https://www.cyberagent.co.jp/way/list/detail/id=26223) の小西(@hirokikonishi )です。
業務としては、AI事業本部に属しており、リテールドメインで __ミライネージ__ の開発をしています。
<img width="600" alt="ミライネージ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371458/9f30bbe6-e9d1-dc45-42ce-ec618a15b580.png">

# 本日の内容
主には、SREの観点の中から __Resilience(回復力、耐障害性)設計__ について取り上げたいと思います。

# アーキテクチャ図と概要
ミライネージのシステムの内、一部分を取り上げます。
小売店舗様に設置されているサイネージ端末と下記のようなデータの送受信を行っています。
- 端末運用のためのデータ
- 自社商品や宣伝のためのデータ
- 広告運用のためのデータ
<img width="600" alt="アーキテクチャ図" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371458/90f7e455-9963-74df-92a5-bbe0609d52c7.png">

例えば、
- 端末の調子が悪いので、再起動したい
- 店舗内サイネージの音量が小さいので、ボリュームを上げたい
- サイネージに正しくコンテンツが再生されているか、スクリーンショットを取得して確認したい
- 商品が完売したため、広告を差し替えたい

上記のような要求に対する操作をサーバー側から可能にしているアーキテクチャの一部です。

また設計で大事な点の例として、
- 広告1再生何円という世界ですので、再生が完了したことを通知するイベントの取りこぼしは許されない
- 有事の際の広告配信停止や差し替えの遅延は許されない

等があります。

このようなあたり __回復力・耐障害性__ を考慮してAWS上でシステム設計をしています。

# Resilience設計の詳細
設計の詳細としては下記2点を取り上げます。
1. edge applicationコード内の工夫
1. AWSインフラアーキテクチャの工夫

## 1. edge applicationコード内の工夫
サイネージ(Android OS)内のアプリケーションについてです。
アプリケーションは [AWS IoT Core](https://aws.amazon.com/jp/iot-core/)と接続・MQTT通信することで主なデータの送受信を行なっています。
小売店舗内に設置されているサイネージですので、ネットワーク環境や店舗内の電源状況によって、通信状況が大きく左右されます。
- ネットワークの切断
- サイネージ電源の切断

を考慮したアプリケーションコード設計が必要です。
例えば、
- AWS IoT Coreと接続できなかった場合は、 _exponential backoff_ や _max_attempts_を利用して、接続を再試行したり、再起動を試してみたりします。
- MQTT通信が失敗した場合は、サイネージ内のストレージに一時的に蓄積します。通信が再開した後に順番に処理します。
- エラーがサーバー側を経由してエンジニアに通知されます。別経路を用いてサイネージに遠隔ログインし端末にコマンドを実行したり、遠隔操作したりします。

上記のような回復力・耐障害性を考慮したコード設計・機能開発を行なっています。

## 2. AWSインフラアーキテクチャの工夫
AWSの[Building Blocks](https://aws.amazon.com/jp/blogs/compute/building-blocks-of-amazon-ecs/)の哲学と[Design for Failure](https://aws.amazon.com/jp/blogs/startup/techblog-well-architected-reliability-1/)の思想に基づき設計をしています。
下図が一例です。

<img width="200" alt="アーキテクチャ図工夫" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371458/0913d6af-8f0f-1362-9606-5e3fd5357972.png">

[AWS IoT Rule](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-rules.html)はルールアクションとして、 
_Lambda_ 関数を呼び出したり、 _SQS_ キューにデータを発行したりできます。

AWSコンポーネント間の通信なので、ネットワークの切断や、サービス制限・制約により通信が失敗する場合があります。
その失敗から自動で回復することが望ましいです。
AWSインフラアーキテクチャで実現しました。


### 考えたこと
1. ルールアクションの[エラーアクション](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/rule-error-handling.html)にて、再度Lambda関数を呼び出すことは可能だが、エラーアクションも失敗したら復旧できない

エラーアクションでSQSキューへデータを発行し、サブスクライバとして復旧Lambdaからルールアクションを再呼び出しするように考えました。
ネットワーク障害等により、Lambdaのリトライ回数でも復旧できなかった場合、[デッドレターキュー](https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html)を用いて、ネットワーク障害等が回復次第、データイベントの復旧を行うように考えました。

# まとめ
上記のように一例としてご紹介しました。
ミライネージではより多くの様々な工夫や議論を重ねながら、回復力・耐障害性に向き合っています。

ご興味ありましたら、各種SNS等でお声がけいただき、技術的な会話・議論できますと嬉しく思います。

# さいごに
明日は@mm-matsudaさんです。よろしくお願いします！

# 参考資料
## ミライネージ プレスリリース
- [店舗のメディア化により小売業界の広告事業を支援 　店舗サイネージ配信プラットフォーム「ミライネージ」の提供を開始](https://www.cyberagent.co.jp/news/detail/id=24848)
- [店舗サイネージ配信プラットフォーム「ミライネージ」、デジタルサイネージの広告運用最適化機能の提供を開始 ー販促効果の高い運用の実現により、小売の広告事業を支援ー](https://www.cyberagent.co.jp/news/detail/id=25832)

## AWSドキュメント
- [AWS Lambda での耐障害性](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/security-resilience.html)
- [AWS IoT のルール](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-rules.html)
- [Amazon SQSデッドレターキュー](https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html)