sodane

AWSと各種SaaSを活用したサーバレス・ライブコマースシステムの開発

水曜どうでしょうエアキャラバンin 赤平2020

10/3(土)・4(日)の2日間で開催された「水曜どうでしょうエアキャラバンin 赤平2020」のオンラインイベント会場として、動画を見ながらお買い物ができるライブコマースシステムの開発を行いました。

アーキテクチャ

全体のアーキテクチャは以下の通りです。
それぞれの役割について簡単にご紹介いたします。

サーバサイドやネットワークの技術者が不在なので、昨年に引き続きSaaSとマネージド・サービスをフル活用してのサーバレス構成で構築を行いました。

エアキャラバン2020.jpeg

映像配信部分

  • AWS側へのアップロードにAWS Elemental のアプライアンスである「AWS Elemental MediaLink」を使用しました。AWS MediaLiveのInputとしてコンソールから直接管理が可能な上、同一のハードウェアを用いることでMediaPackage側でのフェイルオーバーもシームレスに行われることを確認しています。
  • MediaLinkはMediaLiveの入力として繋がります。MediaLinkを用いたときはMediaLive側はSINGLE_PIPELINEしか設定できないため、2つのMediaLiveを使用してそれぞれMediaPackageに入力しました。
  • MediaPackageではMediaLiveからHLSで受けたものをHLSとMPEG-DASHにパッケージしCloudFrontのオリジンとして機能します。
  • また、MediaPackageではネクストスケープ社の「Multi DRM Kit」を用いてDRMを用いたコンテンツ管理を行いました。
  • MediaPackageで作成したHLSとMPEG-DASHのエンドポイントそれぞれをCloudFrontを設定しCDNを用いた動画配信を実現しました。
  • また、2020年のアップデートで追加された新機能を使って、MediaPackageのCDN認証を使ってアクセスをCloudFront経由のみに限定し、MediaPakageへの直接のアクセスを制限しました。
  • フロントエンドに置いて動画プレイヤーとして「THEO Player」を使用しました。プレイヤー側の機能で再生できるドメインも限定しており、よりセキュアな配信を実現しました。
  • MediaPackageで暗号化された動画をプレイヤー側の再生ボタンが押されるタイミングでproxyとして設定したLambdaがMulit DRM Kit に確認を行い、復号化することでセキュアな動画配信を実現しました。
  • 動画プレイヤー側では再生ボタンなどのスキンの変更、イベントを使った再生数の確認なども実施いたしました。
  • 念のためのアーカイブはMediaLiveから分岐してS3に保存することで対応しました。

コマース部分

  • shopify のBuy Button を埋め込むことでコマース部分の構築を行いました。
  • すべてコレクションとして埋め込むことで、現場での商品入れ替えなどをほぼCMS完結で行うことができました。
  • shopifyのBuy Button をそのまま埋め込むとiframeの中に生成されてしまうため、外からCSSなどで直接制御するのが難しかったですが、vue-awesome-swiper を使って多くの商品を表示できるようにしました。
  • コマース部分の表示に関してはPCとモバイルで完全に別のものを作成し、ユーザエージェントで表示訳を行いました。
  • 決済もshopify paymentを使用しました。JCB決済への対応が10/1に発表されましたが、対応が間に合わなかったため、外部サービス連携でJCB決済を実現しました。
  • 本当は決済をすべてStripeにまとめたかったのですが、時間切れでした。
  • 一部食品も扱っていましたが、軽減税率に関しても簡単に適用することができました。
  • ログイン部分で「Auth0」を使用しました。今回は活用は限定的で、利用規約への同意としての役割がほとんどです。

Pick Up! 商品のリアルタイム更新

  • イベントの進行に合わせて、関連する商品を一番上に追加で表示するための仕組みを構築しました。
  • 動画配信中にリロードによる更新は動画が切れてしまうため、可能な限り避けたいというのが理由です。また、演出として動画プレイヤーの外まで使う。ということを試してみたかった。という思いもありました。
  • リアルタイム更新ではAppSyncのsubscriptionを用いて実現しました。
  • フロントではGraphQLのqueryを用いて、DynamoDBに格納したフラグを確認し、初期表示を行います。
  • コンソールからAppSyncでGraphQLのmutationを実行し、リゾルバとして直接Lambdaを動かしてDynamonoの値を書き換えます。
  • このmutationの結果をsubscriptionで受けて、Nuxtのディレクテブである <v-if> で条件付きレンダリングを行い、表示/非表示を切り替えました。
  • 商品の入れ替えについては、非表示の間にshopifyにGraphQLでmutationをかけてコレクションの中身を変更し、さらにAppSync側でmutationでフラグを切り替えることでリロードなしでの表示切り替えを実現しました
  • 開発中、<v-if>の代わりに<v-show>を用いてみましたが、<v-show>ではCSSのdisplay:none: で表示を制御しているため、再レンダリングは行われず、リロード無しでshopify側のmutationの結果を拾うことができませんでした。
  • 他にも実現方法がある気がしましたが、現場でのフレキシブルな運用を考慮し単純な形で実現しました。

twitter表示部分

  • お買い物が一通り済んでしまった方のために、twitterの埋め込みを行いました。
  • twitter公式でハッシュタグの埋め込みは用意されていなかったため、Serach API を用いて実現しました
  • フロントからはAPI Gateway から Lambdaでsearch API を呼び出してツイートを取得しています。
  • Lambda側では最後に取得したツイートのIDをParameter Storeに格納し、ツイート取得時にフィルタリングすることで表示の重複を防ぎました。
  • Lambdaが毎回起動してしまうと、APIの制限回数にひっかかる恐れがあるため、API Gatewayのキャッシュを有効にし、Lambdaの起動回数を抑えるようにしました。
  • また、Lambdaが複数起動してしまった場合、Parameter Store の値に不整合が起きてしまうので、これをコントロールするためにLambdaの同時実行数を1にして対応しました。
  • エア開催になってしまったキャラバンですが、twitterを表示することで同じ空間で参加者のみなさんがワイワイ盛り上がってる感じをお伝えすることができたのではないかと思います。

開発環境

  • 全員で「Visual Studio Code」を用いて開発を行いました
  • ソースコードは「GitHub」のプライベートリポジトリで管理しています。
  • Lambdaまわりは「serverless Framework」を使用しました
  • フロントエンドは Nuxt を使用しました。
  • webアプリケーションの展開先としては、AWS Amplify を使用しました。
  • Amplify と GitHub と Route 53 を連携させることにより、ドメイン管理しながら、prod/stg/dev など開発に必要な環境を数クリックで用意することができ、開発そのものに集中できるようになりました。
  • S3 + CloudFront でやっていた時代には戻れなくなりました。

開発サポート

  • まずは、AWSの弊社担当である川原さんに感謝を伝えたいと思います。
  • 本当様々な我々の見当違いや無理難題に対応していただいて本当にありがとうございました。
  • またあとで反省会しましょう。

  • 全体のコンサルを「Serverless Operations」さんにお願いしました。
  • aws側だけでなく、フロントエンドも含めた全体のアドバイスを頂き、技術検討にかかる時間をかなり圧縮することができました。
  • 堀家さん、キムさん、本当にありがとうございました!

  • awsのアカウントは「クラスメソッド」さんのMembers アカウントになっているため、上限緩和申請など大変お世話になりました。
  • 昨年の、水曜どうでしょう祭での有料ライブ配信でのやりとりのアーカイブも振り返りながら実装を進めることができ、スムーズな構築を行うことができました
  • 特にMedia系で相談にのっていただいた清水さん、本当にありがとうございました!

感想

今回の開発を迎えるにあたって、社内では暫定ではありますが、開発チームが立ち上がりました。みんなあっというまにプラクティショナーに合格。さらに開発言語をゼロから覚えるところからでしたが、苦労しながらも、しっかり作り込んで、無事にエアキャラバンを終えることができました。

開発チーム一同、参加者のみなさんが楽しいでいるツイートを見て本当に報われました。ありがとうございます。

また、社外の皆様にも本当にお世話になりました。
ここまでの技術開発やプロジェクトマネジメントをなんとかやってこれたのは、JAWS-UGserverless meetupJBUGなどをはじめ、この1年で参加・登壇させて頂いた様々なイベントでコミュニティのみなさんから多くのことを学ばせて頂いたおかげです。今回協力頂いた、Serverless Operationsさんとの出会いも福岡でのserverlessDays Fukuoka 2019でした。
1つのアウトプットから多くのインプットを得ることができ、それを更に社内に還元することができたことで本当に大きな変化が起きました。

イベントだけでなく、Developers.IO を初め、QiitaやSlideShare、SpeakerDeckなど、いろんな技術者の型のアウトプットの寄せ集めで実現したと言ってもいいくらい、これでもかと活用させていただきました。

これら我々を育ててくれた技術者コミュニティに対してできる最大の恩返しはアウトプットすることだと思いますので、今回の件も含めて引き続き共有できていければと思いますので、引き続きよろしくお願いいたします。

以上、オープンレポートでした

技術的なことで調べたり勉強したことを残していきます。日報をブログでやってみています
きっとゆるめに脱線することもあると思いますが、ゆるめに見守っていただければと思います。


参考にさせてもらったみんなのアウトプットに最大限のリスペクトと感謝を。
そして、この記事が誰かの役に立つことを願って

この記事を書いたのは

三浦一樹

社外の勉強会コミュニティによく出没
コミュニティ活動が評価され AWS SAMURAI 2019 という称号を頂きました。
技術がみんなものになればいいな、と思っています。
保有資格・【第一級陸上無線技術士】 【AWS SAA】 ネットデジタル事業部 所属