デブサミ 2019 にて「サーバーレス開発の楽しさ」について発表をしました

2019年2月14日~15日に開催された Developers Summit 2019(通称:「デブサミ」)で、『サーバーレスで最高に楽しめるアプリ開発』と題してサーバーレスにまつわる発表をしました。発表内容のサマリーです。

シリーズの記事

デブサミ概要

発表したイベントデブサミですが、技術書籍で定評のある翔泳社さんが開催している “技術者コミュニティとの連携から生まれた総合ITコンファレンス” です。

今回はDevelopers Summit 2019 冬のイベントで、ホテル雅叙園東京で開催されました。よく結婚式などで使われ、建物内に滝と庭園があるすごい場所です。

そして各開催にはテーマが設定されます。今回は「SHARE YOUR FUN!」です。

まさに「サーバーレス開発って楽しいよね」と思っていたところで、その楽しさを多くの人にお伝えしたい、そう考えていたところでの『サーバーレスで最高に楽しめるアプリ開発』の発表となりました。

タイトルが弾け気味なのは楽しさを伝えたいという思いをテーマに乗せました。
(他の登壇者さんのタイトルを見ると、もっと弾けてもよかったかな)

発表資料と Togetter

デブサミ2019【15-B-6】サーバーレスで最高に楽しめるアプリ開発 #devsumiB - Togetter
たくさんのツイートありがとうございます!!

デブサミ 2019 Ask the Speaker で 頂いた QA まとめ
Ask the Speaker 他、QA・ディスカスありがとうございます!!

サマリー

発表の主旨は「サーバーレス開発の楽しさ」です。

これまでさまざまな形態で開発をしてきました。オンプレミス、Amazon EC2、AWS Elastic Beanstalk、Docker…
それが AWS Lambda の登場によって開発体験が激変し、それと同時にさらなる開発の楽しさを体験できました。
もちろんプロジェクトが不調な時もあり、サーバーレスによる制約もあり、たくさんの困難は変わらず待ち構えていますが、それを踏まえても楽しさが勝ると感じています。

そんな体験や思いを多くの開発者さんにお伝えしたく「サーバーレス開発の楽しさ」にフォースし、大きく3つのテーマでお話ししました。

  1. アイデアを即、形にできる、楽しみ
  2. アプリの開発に専念できる、楽しみ
  3. ピタゴラ装置を組み立てる、楽しみ

アイデアを即、形にできる、楽しみ


サーバーレスの環境にすることで、多くのことがクラウドに任せられます。
これはホントにすごいことで、たとえばウェブサーバーもアプリサーバーもデータベースもすべて構築済みでいきなり使い始めることができます。

つまりアイデアが浮かんだら、即コーディングを始めてしまってプロトタイピングできてしまうことです。そして思い切って世に出してしまうことができるということでもあります。

アイデアを形にしていくことは開発者にとって、とても楽しいことではないでしょうか。
また作ったアプリは、過度なアクセスが発生しない限り大した費用にならないことも多く(もちろん、作りにもよりますが)稼働させたままにできます。ポートフォリオとして作品を並べておくこともできます。

アプリの依存ライブラリこそ管理は必要ですが、インフラ部分のパッチあてやバージョンアップなどの運用はクラウドに任せられます。
このアプリの依存ライブラリの管理はDependabotRenovateといったサービスを使うことができます。GitHub などのリポジトリと連携することでpackage.jsonpom.xmlといったプロジェクトのライブラリ管理のファイルを参照し、バージョンアップがあったらプルリクエストを上げてくれます。テストなどに自信がある場合は自動マージさせてしまうのも手です。

サーバーレスには、アイデアを即、形にする楽しさがある!
思いついたら、すぐに作って、どんどん公開して、楽しみましょう♪

※ 発表時に「ラップ、タップ、アップ 🎶」のコスト 500円と話しましたが、さすがに今月は JAWS DAYS 2019 でAWS x JAMstack で 構築・運用する サーバーレス な Web Front| Slides | Riotz.worksもあったので 1,000円にかかりそうです。それでもコスパよいのではないでしょうか。

アプリの開発に専念できる、楽しみ


サーバーレス、FaaS の実行ランタイムにフォーカスして、サーバーレスはアプリ開発に集中できるという話になります。

実行ランタイムが構成済みで使うものを簡単に選択できます。そして、それらは周辺システムと統合されているので、ランタイムを選択するだけで使う始めることができ、他のことを考える必要がありませんし実行ランタイムの違いから周辺システムへの変化を気にすることもありません。

IoT バックエンドの開発プロジェクトの事例になりますが、Java の実行ランタイムを使ったサーバーレスで作っていたものを、本番投入1ヶ月前に Node.js/TypeScript へ切り替えるという事態がありました。

この時でさえ、Lambda の実行ランタイムを Java から Node.js へ切り替え、プログラムは再実装するものの周辺システムは変更ありませんでした。スケールや監視でさえ統合済みなので何も設定する必要はありません。
ホントにプログラムだけを実装しなおしただけになります。

もしインスタンスやコンテナーベースだとしたら、OS やミドルウェアからと、全部やり直しになります。そしてそれに対応できる人材はいたでしょうか。。。

ホントにプログラムだけに集中できました。
プロジェクトは危機的状況ですが、開発者としてコードだけに専念できるのは、とても楽しいことではないでしょうか。

サーバーレス環境は構成済み&疎結合、手軽に切替えて使う楽しさがある!
必要時に最適なものへ切替え、それでも “コードに専念” を楽しみましょう♪

ピタゴラ装置を組み立てる、楽しみ


クラウドには多様な機能があり、クラウド自体もたくさんあり、サービス(SaaS)も含めると無数に機能があるといえます。
サーバレスで開発するときに、これらの機能を組み合わせて作っていきますが、あるいはピタゴラ装置を組み立てているとも言えます。(もうこの時点で楽しい、とも思えてしまいますが)

ここでの「機能を組み合わせる」は、Lambda などの処理ロジックの中で多数の機能を呼び出すのではなく、1つの Lambda が 1つの機能を担い、次の機能へ処理を渡していくような流れを想定しています。


これは、私たちがハッカソンで作った「ラップ、タップ、アップ 🎶」というアプリの例ですが「通知」の機能が DynamoDB の後ろに来ています。

多くの場合「登録の Lambda」処理で一緒に通知を行うのではないでしょうか。
しかしながら、ここでは DynamoDB Streams という機能を使って、DynamoDB のレコードの変化を受けて処理を動かすようにしています。

これにより「登録の Lambda」は DynamoDB へ登録するだけの処理となり非常にシンプルになり
ます。

そして「通知の Lambda」も通知が必要かを判断してFirebase Cloud Messagingを呼び出すだけのシンプル実装です。

また「TTL/削除の Lambda」は DynamoDB の TTL(Time To Live) の機能を使い、レコードの削除を自動的に行うようにしています。レコードが削除されると DynamoDB Streams が動きますので、そこからSkyWayの SFU ルーム削除を呼び出す Lambda 処理が行われます。

一見複雑なアーキテクチャになっているようでいて、1つ1つの処理はシンプルになっているので作りやすくメンテもしやすいのではないでしょうか。

まとめ


以上、発表の主旨とサマリーになります。

エゴサ

まとめ、参加録、フィードバック、いろいろな記事ありがとうございます 😆🙏

デブサミ2019【15-B-6】サーバーレスで最高に楽しめるアプリ開発 #devsumiB - Togetter
たくさんのツイートありがとうございます!!

Developers Summit 2019に参加した感想など - cats cats cats
ラップアプリのアーキテクチャを中心に所感交え書いてくださりました。ありがとうございます!!

初心者がデブサミに参加した感想をまとめたらこうなる - Qiita
ピタゴラとコールドスタートにフォーカスを与え所感交えて書いてくださりました。
またDependabotの補足も入れてくださり、ありがとうございます!!

デブサミ2019メモリンク集~Share my fun~ - Qiita
感動を表現した形のまとめがFun!。ありがとうございます!!

Developers Summit 2019に参加してきました - 御成門プログラマーの日記
要点をまとめ、重要部分にフォーカスしてくださりました。ありがとうございます!!

できる限り探してまとめさせていただきました。
もし入ってなかったり、新たに投稿いただいたなどありましたら Twitter@lulznekoへ DM やメンションいただけたら幸いです。


デブサミで発表させていただくのははじめてで、とても良い経験をさせていただきました。
話始めるまでは緊張があったのですが、不思議なことに話始めると緊張は完全に抜けており、会場の皆さまの真摯な目にしっかり応えていきたい、自分の伝えられるものをすべてをお伝えしたいという気持ちが高まり話をすることができました。

これは会場の空気を作ってくださった聴講者の皆さま、安心して発表に臨めるよう支援してくださったスタッフ・運営の方々のおかげです。ありがとうございます。

AWS Lambda 登場以来、サーバーレスに特化しサーバーレスで開発し続けてきたなかで感じていた「サーバレス開発の楽しさ」については、お伝えすることができたのではないかと思っていますが、やはり『サーバーレスで最高に楽しめる』と銘打ったからにはもう少し弾けて話したほうが良かったかなと少し反省。

最後になりますが、セッションにご参加いただいた皆さま、万事支援してくださったスタッフの皆さま、そして貴重な機会を作っていただいた運営の皆さまに感謝です! ありがとうございす!!

JAWS DAYS 2019 にて頂いた QA まとめ

JAWS DAYS 2019 で『AWS x JAMstack で構築・運用するサーバーレスな Web Front』のお話をした後に頂きました QA をまとめます。

頂いた質問は要点のみを一般化して書いている部分がります。背景などが入っていないので若干わかりにくい部分がありますが、ご了承ください。

シリーズの記事

発表資料と Togetter

2019/02/23(土) JAWS DAYS 2019 <7> 15:10~ #jawsug #jawsdays - Togetter
たくさんのツイートありがとうございます!!

1. DynamoDB の Attribute を変えたい場合に、どうやっているのか?

発表の QA タイムで@yoshidashingoさんに、頂いた質問になります。
AWS Serverless Hero直々の質問に緊張し、質問の要点を上手く汲み取れず、しっかり回答を返せませんでした。すみません。QA 対応力を磨かねば。
(ところで振り返ると、これって「この分野はあんまり詳しくないんですが」事案ではないでしょうか💦)

この QA については、本記事投稿時追記の形で、QA を振り返り整理します。

質問の主旨としては、このセクションのタイトルにした通り「DynamoDB の Attribute を変えたい場合に、どうやっているのか?」の質問と改めて整理しました。

DynamoDB でテーブル作成後に変えられないものは下記になります。(他にもテーブル名や暗号化タイプなどありますが質問のスコープとして)

  • 主キーの構成と型 (パーティションキー、ソートキー)
  • Attribute の名前と型(ただし Attribute の追加はいつでも自由にできる)

主キーはどうにもならないので、テーブルの作り直しになります。

Attribute の名前と型、こちらは変えたいとなるとどうにもなりませんが、Attribute は後から追加できるので新しく Attribute を足して、そちらを使う手も取れそうです。
しかし、既存データを新しい Attribute に移動するのか、またはプログラムでカバーするのかが出てきます。また混ざった状態が発生すると、後々困りそうです。

質問の前提となる事象がわかったら、もう少し踏み込めそうですがざっくりこんな感じの回答になります。

発表時に「あまり大きなものを作ってないので」と回答しましたが、マイクロサービスで作っているので、個々のシステムは小さく、また変化もあまりないので上手く想定できなかったのもあったかもしれません。
それでも Attribute はいつでも自由に足せるので、キレイではないものの逃げ方もあるような 🤔
「ディスカスしましょう」とおっしゃっていたので、このあたりの逃げ方含め議論したかったのかな。

※ Serverless Framework との質問でしたが、DynamoDB の定義は Serverless Framework の構成ファイルserverless.ymlに書きます。しかし CloudFormation のパートになるので、Serverless Framework 固有より、CloudFormation での管理になることと、むしろ DynamoDB そのものの話になるかと思い Serverless Framework は外しました。

参考情報

2. WordPress の静的化に JAMstack は有効なの?


何件か質問をいただきました。

WordPress へ投降者以外は直接アクセスできないようにしたり、投稿通知をするための仕組みを作ってあげる必要はありますが、WordPress を使った既存の運用は残したまま、まったく新しいサイトへ生まれ変わらせることができます。

それにより、セキュリティ問題やバージョンアップ対応の負担を減らすことはできますが、この場合でもセキュリティ問題は内部からの攻撃は避けられません。脅威はインターネット側だけにあるとは限らないこと注意が必要です。

そして静的化するのでパフォーマンスは、とてつもなく向上します。
まさに今日お話ししました、高パフォーマンス、セキュリティただし局所化、スケーリング、運用の軽減が手に入ります。

発表資料ではGridsomeを使ったアーキテクチャ図になっていますが、まだまだ開発中なのでGatsbyJSを使うのが現実的です。

またカスタム API を持たず、WordPress のコンテンツを新しいサイトとして配信するだけならNetlifyに配置するのも手です。

GatsbyJS で WordPress 移行は、多くの情報があるので取り組みやすいです。
私も機会があったらブログとかを書きます。

3. SSR(Server Side Rendering) との違いは何か?

SSR はブラウザからのリクエストを受けて、サーバー側で HTML を生成してレスポンスする形になります。
これはリクエストを受けてから処理を行うので静的サイトを作る SSG(Static Site Generator) より、以下の点で不利です。

  • パフォーマンス、これは HTML 生成処理がある、また DB アクセスすることもあるかもしれません
  • セキュリティ、仮に HTML だけを返すとしても AP サーバが存在するので攻撃対象になります
  • スケーラビリティ、AP サーバをスケールするのは大変です

ただし、開発者フレンドリーは、JAMstack としては良いとしていますが、一概に言えないかもしれません。Web API から取得したデータを JavaScript で HTML を変化させるのは開発者によっては苦痛かもしれない。
私はVue.jsNuxt.jsが気に入っていて、JavaScript で値を設定するのは、楽しいです。


そして SEO の観点でお話ししました通り、SEO のためのヘッダー出力は HTML である必要があります。
自分がコンテンツの発信量をコントロールできている場合は SSG で問題ないのですが、リアルタイムで大量のコンテンツが変化していくものには SSR が必要となります。

SSG では CI などを使ってビルドを回す必要があります。これは遅い処理になります。リアルタイムでユーザーを待たせることができないくらい時間がかかり、また大量に受け付けることができないものになります。

この場面においては SSR が必要となります。
それ以外で SSR 必須、または SSR が良いシーンは今のところ浮かばないです。もっと考えてみます。

4. SPA(Single Page Application) はどうなるのか?

これは、SSG が生成した HTML の形式になるので、ツールによります。

ブログツールのHexoは SSG で MPA(Multiple Page Application) です。

私たちが作ったラップ・バトルはNuxt.jsで SSG & SPA で動かしています。
Nuxt.jsは SSR もできるので、設定で指定します。

ツールの考え方とかもあるので一概に何とも言えないところがあります。
ただし高パフォーマンスの観点で考えると、ページの先読みやキャッシュなどが重要になっきます。そして、これらも SSG がどのような機能を持っているかによります。

その点で、私たちはGridsomeが気に入っています。
まだ開発中なので、普通に使うにはGatsbyJSが良いかもしれません。
また、アプリ開発用途でしたら、Nuxt.jsをオススメします。

5. JAMstack でも Lambda や DynamoDB は必須なのか?


“俺の満漢全席” を想定されての質問と考えます。
こちらは JAMstack で作ったアプリ全体像としてのアーキテクチャ図になります。

JAMstack の要件はざっくり言うと「HTML を事前ビルドして CDN に置くこと」なので、Lambda や DynamoDB は JAMstack とは関係ないものになります。


JAMstack の要件だけの図としては “満漢ミニ席” または “WordPress リプレース席” をイメージしていただけるとよいです。
“満漢ミニ席” では、ブログなどの情報発信サイトをイメージしていて、記事を Markdown などのファイルに書き、それを HTML として出力、CDN へ配置する形になっています。
ここには Lambda や DynamoDB は登場しません。純粋にウェブサイトだけになります。

6. “俺の満漢全席” で Lambda/DynamoDB は EC2/RDS にしてもよいか?


Lambda/DynamoDB を EC2/RDS へ変えても構いません。JAMstack の要件としては「再利用可能な API」なので、Web API 提供できれば大丈夫です。

ですが、せっかくなのでサーバーレスで作ってほしいです。

JAMstack は SSG を使うことで、HTML の生成を事前に行います。
そして CDN に配置するだけで運用するので、言わばフロントエンドのサーバーレスともいえるでしょう。

Web API をサーバーレスで作ってきても、フロントエンドで SSR するからインスタンスが欲しいとなって、全体でサーバーレスになれなかったケースなどもあり、フロントエンドのサーバーレス化も重要だと思ったことがあります。

CDN に配置するだけのことをサーバーレスと言うのは、ちょっと苦しいですが、全体をサーバーレスで作りたい撮った時に「JAMstack で、フロントもサーバーレスで」って言いたいのもあります。

最後のまとめ「名前が付き、認識されることで、伝わる」はまさにそんな思いからになります。
むしろ「JAMstack で、フロントもサーバーレスで」って書いたほうが良かったですね。


質問いただき、ありがとうございました。

QA や議論ができ、とても楽しかったです。そしてお話しいただくことで気付きを得たり、考えの整理にもつながり、とても勉強になりました。

できる限り思い出して書きましたが、もし入ってなかったり、別途気になることなどがありましたら Twitter@lulznekoへ DM やメンションいただけたら幸いです。

発表者は、その日何をしていたのか - 発表の舞台裏 JAWS DAYS 2019 編


新しい朝が来た希望の朝だ、発表の朝だ!

JAWS DAYS での発表の朝を迎えて、発表者 lulzneko は絶望していた。
なんと発表資料が完成していないのです 😱


2019年2月23日に開催された JAWS DAYS 2019 で『AWS x JAMstack で構築・運用するサーバーレスな Web Front』と題して JAMstack にまつわる発表をしました。その発表の舞台裏ということで、発表者が当日何をしていたのかを綴ります。

シリーズの記事

JAWS DAYS 概要

発表したイベントJAWS DAYS 2019ですが、AWS のユーザーコミュニティJAWS-UG主催、後援 アマゾン ウェブ サービス ジャパン株式会社さん で 行われる JAWS-UG 最大のイベントです。

場所は TOC五反田メッセで、さまざまなイベントや展示会などが開催される場所です。

会場入り

ストーリーとスライドの配置は完成していて、そこに載せる図AWS における JAMstack の配置の章で使うものが間に合ってなかったレベルなのですが、慌てて PowerPoint を操作する朝から始まりました。
なんか、前回のデブサミ舞台裏でも同じことを書いた気がします。

なお、前日の 22日には発表用資料をうっかり消し飛ばす事故を起こしました。
慌てるとよくないことがあるので、急ぎつつも作業ミスをしないのが大事です。

急いでスライドを完成させ、所用を済ませと、あわただしく過ごして午後一の会場入りをしました。
資料の都合というより所用があって午前入りできなかったのですが、午前中のセッションも聴きたかった。

会場である TOC五反田メッセは、本館とは別の建物になります。
“TOC” だけで考えていると、うっかり本館へ行ってしまい、結構な回り道を歩くことになります。
そうです、うっかり本館へ行ってしまいました。微妙な場所からの移動だったのでタクシーさんに乗せてもらったのですが “メッセ” が伝わってなかったようで、がっつり本館へ。あまり東京の道に慣れてないとのことでしたので、結構な周り道を徒歩で堪能させていただきました。

受付

無事会場入りできたので次は受付です。

イベント開催用の建物なので、入ってすぐに受付になります。
手前に参加者の受付があり、少し進んだところに発表者の受付があります。
クロークもあるので、モコモコのジャケットを預けられたのが嬉しいです。

受付で Doorkeeper のチェックインをします。QR コードを表示して読み取ってもらいます。
続いて自分の名前が書かれてるスピーカーパスをもらい、印刷したアイコンの切り紙を差し込みます。(写真では名前部分が隠れてますが、当日はアイコン画像を端において名前は見えるようにしています)

受付が終わると、発表時間までフリーなのでセッションを楽しんだり、控室で作業したりできます。

発表 10分前

前の発表が終わり、落ち着いたところで演台へ近づき発表準備に入ります。

進行の方から名前等の最終確認を受けます。

そして、電源の確認。
今回はちゃんと持っていきました!(持って帰るのを忘れました💦)

発表者サポートは、進行の方が残り時間をボードで教えてくれます。
10分、5分、3分。しっかり出してくれるので助かります。

マイクはワイヤードで、演台にセットされています。持っているほうが安定するので、外して持つようにしました。
会場は各セッションごとの個室ではなく、会場の後ろ側が空いている&壁が天井までつながっていない仕様のため、マイクの音が小さめでレシーバーで聞くようになっています。会場の後ろのほうで聞いていると音があまりしないので、話すときにどんな感じか心配しましたが話している分には側のスピーカーから聞こえるので違和感はなかったです。

プロジェクターが大きく、普段は投影画像を直接指さすタイプなのですが、さすがに届かない感じです。そろそろマイ・レーザーポインターを用意したほうが良いと思いつつ、準備完了。

発表用スライドの URL をツイート。

発表

いざ、発表!
ご清聴ありがとうございました!!

たくさんのツイートありがとうございます!!
2019/02/23(土) JAWS DAYS 2019 <7> 15:10~ #jawsug #jawsdays - Togetter

@kondoyukoさんに、グラレコを作っていただきました。ありがとうございます!

※ QA は後ほどまとめます。

懇親会まで、徘徊

Ask the Speaker はないので終了。
発表用スライドの URL を再度ツイート。

エゴサして、Like、RT、Follow-…

回れてなかった出展ブースを巡り、スタンプラリー
すべて回ったはずなのに、スタンプが1つ足りず。。。どこが足りないのかはわからない仕様なので諦める&配布終了に間に合わず。残念。
(次の日になったらアプリで表示できなくなったのでキャプチャできず)

懇親会

すごい人数でした。🍻 楽しかったです!


以上、発表者の一日でした。
なんとか無事発表を終えることができました。

次回は、2019年3月9日(土)『【CTOって本当にかけるの!?】ベンチャー6社のCTOチームと競う新規サービス立ち上げハッカソン』でハックしに行きます。
2/25日現在、まだまだ枠がある(8/30人)ようなので、よかったら一緒にハッカソンしましょう。

また、ちょっと来て話をしてよ、といったようなことなどありましたら、Twitter DM/メンションを@lulznekoへ気軽にいただければ幸いです。
これまでの発表歴は、こちら [Slides | Riotz.works]https://riotz.works/slidesになります。


聴きに来てくださり、ありがとうございました。
スタッフの皆さま、支援ありがとうございました。

そして、ポエム的なものをここまで読んでくださり、ありがとうございます。

デブサミ 2019 Ask the Speaker にて頂いた QA まとめ

Developers Summit 2019 で『サーバーレスで最高に楽しめるアプリ開発』のお話をした後の Ask the Speaker で頂きました QA をまとめます。

頂いた質問は要点のみを一般化して書いています。背景などが入っていないので若干わかりにくい部分がありますが、ご了承ください。

シリーズの記事

発表資料と Togetter

デブサミ2019【15-B-6】サーバーレスで最高に楽しめるアプリ開発 #devsumiB - Togetter
たくさんのツイートありがとうございます!!

1. ピタゴラ装置式で障害が発生したら、どのように追跡するか?


たとえば IoT プラットフォームの例では、AWS Lambda を細かく分けていますし、いくつかのサブシステムや AWS アカウントをまたがって処理を行っていたりします。

また入力ソースがバッチとウェブがあり、途中から同じ処理フローになっていきます。

障害が発生すると、結局のところログを洗っていくしかないのは変わらずで。分散されているので地道に追いかけています。

開発メンバーのひとりが、トレースID をヘッダーにつけてリレーする方式を導入を進めてくれているため、導入されている範囲は比較的探しやすいです。

その方法は以下となります。

  • リクエストを最初に受けた場所は、次のリクエストを投げるときにTRACE_IDというヘッダーに UUID をつけて送る (※TRACE_IDは本記事用の仮名)
  • 中間の処理でもTRACE_IDがなかったら、そこからTRACE_IDをつけ始める
  • TRACE_IDを受け取った場合は、その値をリレーして使っていく(新たに発行しない)

マイクロサービスのトレーシング用ライブラリや基盤もあります。いまちょっと名前が思い出せないです。すみません。まだ、しっかり調査できてないので導入できてないです。

※ 本記事投稿時追記
マイクロサービスのトレーシングはZipkinという分散トレーシングシステムを思い出して話していました。名前がすぐに出てこないとは💦
同様のプロダクトやサービスがあり、今後調べていきたいと考えています。

2. ラップ・アプリのモバイル通知が Amazon SNS でないのは?


ラップ・アプリは Web API を AWS に構築しています。
AWS を使っているので Amazon SNS(Simple Notification Service) を使ってモバイル通知をすれば、ワンストップになるので良いのではないかとも考えられます。

これについては、ざっくり行ってしまうと「普段から使っていたから」が一番大きい理由になります。

これは、ハッカソンという時間が限られた場で開発をするので、使い慣れているものを使うのが一番ということになります。

では、なぜ普段使いだったのか(普段 AWS なのだから、SNS が普段使いでもよいはずで)

モバイル通知を必要としたころの調べで、FCM(Firebase Cloud Messaging) のほうが手軽に扱えて、サポートするモバイルデバイスが広かったので FCM を使い、その後も使い続けているといった理由になります。

今なら Amazon SNS でも変わらないのかな。いずれ調べてみたます。

3. IoT プラットフォームでファイル分割処理場をしてる理由は?


開発当時 AWS Lambda が 5分しか稼働できなかったため、ファイルを分割しながら DynamoDB へ投入しているとタイムアウトしてしまったためになります。

そのためいかに高速に処理を行えるようにするかを考え「ファイル分割だけ」をすることが高速化につながったので、ファイル分割を入れています。

高速化のために AWS Lambda のローカルストレージを使ったりとさまざまな工夫が入っています。

2019年2月現在は 15分まで稼働できるので、このシステムではファイル分割をしなくても処理しきれるかもしれません。

4. IoT プラットフォームの DymemoDB はコスト高ではないか?


たしかに DynamoDB を 3つ使っていて、データの内容物としてはおぼ同じものになり、ムダになっているように見えます。

まず DynamoDB のストレージ料金は、高額ではありません。
データの複製を大量に持ったとしても、ストレージについては気にしなくてもよいかもしれません。

ストレージ料金に対して Read/Write のキャパシティが高額です。
このシステムはバッチ処理で一時的に大量データを読み書きする必要があるため、とくに1つめの DynamoDB のキャパシティは高く設定しています。

それでも何百ドルとまでは行っていないはずなので、1つの DynamoDB にして処理ロジックを複雑にさせるより、複数配置するほうを選んでいます。

※ 本記事投稿時追記
2019年2月東京リージョンのストレージ単価は0.285 USD/GB
10GB のデータベースで約3ドル、超大規模デモない限りロジックの簡易さを求めてもよいのではないでしょうか。

Read/Write キャパシティについては、オンデマンドキャパシティモードも出たので、状況に応じて変わってきます。

Amazon DynamoDB 料金
https://aws.amazon.com/jp/dynamodb/pricing/

AWS Simple Monthly Calculator (簡易見積ツール)
https://calculator.s3.amazonaws.com/index.html?lng=ja_JP

5. Amazon SNS で処理を分岐するメリットと活用方法について


IoT プラットフォームの例では、Amazon SNS で本処理と Redshift へデータを渡すのを分けています。

スライドの図では処理の流れを示したかったので矢印が Amazon SNS → DynamoDB の用になっていますが、実際の流れとしては Amazon SNS へ Subscribe しているので矢印が逆になります。

処理を分岐しているというより、データの公開場所を用意したので、欲しい人は見に来てくださいという形になります。

この形のメリットはデータを欲しくなった人が増えた時に、Amazon SNS の Subscribe を追加するだけで追加でき、ロジックを変更しなくてよいものになります。

6. Amazon SNS でウェブの処理を分岐できますか?


Amazon SNS の Subscribe で動作するのは非同期処理になります。

ウェブのリクエストが Amazon SNS の先の処理結果を必要とせず、何かしらのデータを Amazon SNS に公開して、ウェブのレスポンスを返せる場合は、処理分岐として利用可能です。

プログラミングの if文のような条件分岐としては利用できません。
Amazon SNS はデータの公開場所を作っておき、そこにデータを置く人、データをもらう人、それぞれがそれぞれのタイミングで動作するイメージになります。


Ask the Speaker へ来てくださり、ありがとうございました。

QA や議論ができ、とても楽しかったです。そしてお話しいただくことで気付きを得たり、考えの整理にもつながり、とても勉強になりました。

できる限り思い出して書きましたが、もし入ってなかったり、別途気になることなどがありましたら Twitter@lulznekoへ DM やメンションいただけたら幸いです。

発表者は、その日何をしていたのか - 発表の舞台裏 DevSumi 2019 編


新しい朝が来た希望の朝だ、発表の朝だ!

デブサミでの発表の朝を迎えて、発表者 lulzneko は絶望していた。
なんと発表資料が完成していないのです 😱


2019年2月14日~15日に開催された Developers Summit 2019(通称:「デブサミ」)で、『サーバーレスで最高に楽しめるアプリ開発』と題してサーバーレスにまつわる発表をしました。その発表の舞台裏ということで、発表者が当日何をしていたのかを綴ります。

シリーズの記事

デブサミ概要

発表したイベントデブサミですが、技術書籍で定評のある翔泳社さんが開催している “技術者コミュニティとの連携から生まれた総合ITコンファレンス” です。

今回はDevelopers Summit 2019 冬のイベントで、ホテル雅叙園東京で開催されました。よく結婚式などで使われ、建物内に滝と庭園があるすごい場所です。

会場入り

ストーリーとスライドの配置は完成していて、そこに載せる図ピタゴラ装置を組み立てる 楽しみの章で使うものが間に合ってなかったというレベルなのですが、慌てて PowerPoint を操作する朝から始まりました。

lulzneko は遅筆で資料の一部が、間に合ってないことが結構あったりします。
今回はデブサミの次週に JAWS DAYS での発表もあるため、早めに着手したのですがギリってしまった。
あまり本質的でないところとかでも、気になってしまったり、こだわったりしてしまうのが原因なのですが。。。
スライドや文章、図が早く作れる方はうらやましいです。

急いでスライドを完成させ、所用を済ませと、あわただしく過ごして午後一の会場入りをしました。
なおデブサミの運営さんからは、”講演開始50分前までにご到着ください。” とのことですが、やはりセッションを見たいので早く到着するに越したことはないですね。
(資料の都合というより所用があって午前入りできなかったのですが、午前中のセッションも聴きたかった)

会場である雅叙園は実はエントランスとは別の裏道があります。
目黒駅を出て雅叙園に向かう、あのヤバい坂に差し掛かる手前で左に曲がります。住宅地のような感じもある道ですが、気にせず進むと右にアマゾンジャパンさんのオフィスへ行く道が出てきます。
実はこれが裏道で、アマゾンジャパンさんのオフィスへ入り、すぐに右へ行くとなが~いエスカレーターが出てきます。これを降りると、エントランスから入って左手に見えてる庭園へ出ることができます。
あのヤバい坂は急で長距離なだけでなく、車もバシバシ通るので裏道(こっちも車は結構通るのですが)を使いたいところ、もちろん使わせてもらいました。(目黒駅に帰る場合はエスカレーターで登れるので、裏道のが断然いいですね)

受付

無事会場入りできたので次は受付です。

雅叙園は結婚式などでも使われる素敵な場所で、エントランスを入ってすぐに素晴らしい庭園とお洒落なレストラン街があります。

はじめて来ると、IT イベントはやってなさそうな雰囲気に焦りますが、気にせず奥まで進むと、デブサミの看板のあるエスカレーターが出てくるのでビビらずに進むのが大事です。

エスカレーターを上がり2階へ着くと受付がありますが、発表者は3階まであがり、発表者受付に進みます。
こちらも “3F控室前の受付へお越しください。” とメールの案内にあります。

受付で、自分の名前を発表時間、lulzneko の場合ですと「15-B-6 サーバーレスで最高に楽しめるアプリ開発」といった感じで伝え、名刺1枚を渡します。

スピーカーパスをもらって、自分の名前を書きます。
せっかくなのですが名前を書いても、ぱっと見でわからないので印刷したアイコンの切り紙を持っていて、それも差し込んでいます。

受付が終わると、”講演開始30分前” までには控室にいるようにとの説明を受けます。

あとは時間までフリーなのでセッションを楽しんだり、控室で作業したりできます。
セッションは事前登録なしでもスピーカーパスで入ることができます。

ただし lulzneko は、リハーサルに参加してなかったので、流れの確認と接続チェックがあるので、まずは控室入りとなりました。

※ 発表者受付では入場者バッグは配布されていませんでしたが、2階の受付でスピーカーパスを見せたらもらえました♪

控室 & 流れの確認

セッション用に使っているのと同じ規模の部屋になります。

長机に椅子、電源、コーヒー、お茶、スナック、お弁当が用意されています。
電源が豊富に用意されているのがありがたいです(ACアダプター忘れましたが)。発表前に少し手直ししたり、作業したりすることがあり、電源がないとバッテリーの心配が出たりするので重要です。

スタッフの方より名前を呼ばれ、流れの確認に入ります。
スピーカー事前確認フォームで入力した内容を元に、会社名や名前、タイトルを確認します。進行の方が始まりに名前を呼んでくださるためですね。

続いて機材の確認で PC だけ、音声や映像の再生は不要、スマホを使うが接続の必要なしなどを確認し、ディスプレイへの接続チェックをします。
VAIO は HDMI、VGA どちらもいけるほか、接続問題もほぼなく助かってます。一度だけ HDMI はつながらなかったことがあったのですが、ケーブルが長すぎたと思われます。

続いて、バックアップの確認になります。
こちらも事前フォームで PDF を提出したものの確認になります。”必ず2/12(火)までにバックアップデーターを提供する。” こと案内があったのですが、当日の午前中に提出でした 🙇

PDF を提出はしているのですが、実は発表資料はウェブアプリでできています。(ラップのアプリを埋め込みで動かしたのは、この仕掛けだったりします)

発表用のバックアップとしては、ウェブアプリが必要なので Google Chrome でプレゼン URL へアクセスしてもらいました。
その際に URL をうまくお伝えできずに、テキストファイルを作って USB メモリーへコピーしたのですが、スタッフさんより「USB メモリー を PC へ接続して大丈夫ですか?」との確認があり、きちんとされてるなぁと。

そして電源の確認。
忘れてしまったことを素直に白状し、使わないようにしてバッテリーが大丈夫なこと説明しました。
スタッフさんを、とても悲しい表情にさせてしまいました。すみません 🙏

発表者の移動動線

最後に、発表時の流れの説明を受けます。
受付時に以下のようなカードをもらっており、こちらの説明です。

雅叙園は結婚式などでも使われており、そのための裏動線が用意されているとのことです。すごい!

控室は図の「C会場 Ask the Speaker」の上の部屋になります。
その部屋のエスカレーター側入り口とは別の裏口から出て、エレベーターへ回ります。
そして2階に行き、各会場へ入るという流れになります。

確かにデブサミ級のイベントになると、参加人数も多いですし、入り口で事前登録のチェックなどをしているので、発表者が入り口から入ってくると都合が悪そうです。

このような観点からも会場選びとかされているのでしょうね。ザ・プリンス パークタワー東京 が IT系イベントで使われているのも、もしかしたら?

なお Ask the Speaker の受ける場合は、発表終了後に退出される参加者さんへ突して所定位置へ移動するとの説明を受けます。スタッフさんから「私がお客様を掻き分けて進むので、しっかり付いてきてください」とのことです。

まぁ、確かにメイン動線へ戻るためのルートはなさそうですし、早く Ask 席へ移動すること、またスタッフさんを次の発表者につけるためにも突るしかないのでしょう。

以上、説明を受けてフリーです。
コーヒーを堪能して心を落ち着け、セッションとブースへ!

発表 30分前

控室に待機し、発表準備に入ります。
スタッフさんから名前を呼ばれ、先ほど説明を受けた裏動線で移動開始です。

「B会場なので厨房を通ります。気を付けてください。」
「みなさま、ここを通る時は楽しそうにしてます。やっぱり珍しいんですかね。」
「昨日は厨房でケーキを見ていたら食べたくなって買いました。1階で売って、とてもおいしいですよ。」
「こちらで少々お待ちください。」

と、適切なナビを受けて会場裏に到着です。

倉庫のような場所の丸椅子で少々待機。30分前に移動してるとはいえ、20分の休憩があるので直前の発表の、ほぼ終了時点で待機場所到着です。

自分の資料を見直す時間もなく莫大な拍手が聞こえ「入ります。どうぞ!」の案内。

正面のすぐ横から入ってセッティング。
進行の方から名前等の最終確認を受け、発表用の「雅叙園ウォーター(秩父源流水)」をもらいます。

そして、電源の確認。
また進行のスタッフさんを、とても悲しい表情にさせてしまいました。すみません 🙏

発表者ツールとしては、まず演台の下に正面投影用と同じ内容を表示するディスプレイがあります。
こちらへ事前に映しておき、切り替えたらすぐに表示されるようになっています。すごい。
(デモのときに QRコードをスマホで撮るためにしゃがんだのが、このディスプレイです)

客席正面の真ん中に大きなカウントダウン時計があります。演台の手元にもカウントダウン時計があります。
正面のは、とても大きく見やすくて助かりました。(手元のはなぜか動いてなかった)

マイクはワイヤレスで、ハンドマイクとピンマイクがあります。
持っているほうが安定するので、ハンドを選びました。

レーザーポインターもあります。
普段は投影画像を直接指さすのですが、さすがに届かないのでお借りしました。

発表用スライドの URL をツイート。

発表

いざ、発表!
ご清聴ありがとうございました!!

たくさんのツイートありがとうございます!!
デブサミ2019【15-B-6】サーバーレスで最高に楽しめるアプリ開発 #devsumiB - Togetter

Ask the Speaker

お片づけをして、Ask 席へ向かって突ります。
スマホの片づけとかあったので、お待たせしてしまいました。すみません。

10名ぐらいの方に来ていただきました。ありがとうございます!!
いただきました質問はできる限り思い出してメモりましたので、別途まとめを書きます。

[2019.2.23 追記] こちら『デブサミ 2019 Ask the Speaker で 頂いた QA まとめ』にかきました。

何か気になることなどQAや、またフィードバックなどありましたら、Twitter@lulznekoへ DM をいただければと。オープンになっているので、とくにデブサミに限らず気軽にいただければと。

おわり

発表用スライドの URL を再度ツイート。

これまでは発表前だけだったのですが、あるTwitter の 投票で、発表後にスライドを共有してほしいというのが1番だったので再度ツイートするようにしました。遅くなってしまったので、お片づけ時にツイートすべきでした。反省。
(発表前は2番だけど、発表時に手元へあるといいこともあるので)

エゴサして、Like、RT、Follow-、バッテリー切れ…


以上、発表者の一日でした。

色々しでかし気味なヤバい一日でしたが、無事発表を終えることができました。

いろいろなイベントで話をする機会をいただいておりますが、スタッフさんとの濃密なやり取りや、裏動線を使った移動などははじめてで、これはぜひ伝えたいなと思い書いた次第です。

文才があったら発表者目線な読み物にしたかったのですが、ムリかったので淡々と描く形になりました。
発表者サイドではありますが、舞台裏がどうなっていたのか少しでも伝わりましたら幸いです。

次回は、2019年2月23日(土) 15:10~JAWS DAYS 2019で『AWS x JAMstack で構築・運用するサーバーレスなWeb Front』のお話をします。 もしよろしければ、お越しください。

また、ちょっと来て話をしてよ、といったようなことなどありましたら、Twitter DM を@lulznekoへ気軽にいただければ幸いです。
これまでの発表歴はこちら [[Slides | Riotz.works]https://riotz.works/slides](https://riotz.works/slides/になります。


聴きに来てくださり、ありがとうございました。
スタッフの皆さま、支援ありがとうございました。

そして、ここまで読んでくださり、ありがとうございます。

Riots.works での JAMstack の利用

最近注目を集め始めている “JAMstack”、より良いパフォーマンス、より高いセキュリティ、より安価で簡単なスケーリング、より良質な開発者エクスペリエンスを提供するアーキテクチャ。

Riotz.works でも注目しており、実際に活用しています。今回は、この JAMstack を Riotz.works でどのように使っているかをご紹介します。

Riotz.works 公式ウェブサイト

公式ウェブサイトのトップページhttps://riotz.works、Works ページ、Engineers ページがGridsomeで JAMstack なサイト作りをしています。

Gridsomeは 2019年1月現在バージョン 0.4.5 で速いペースで開発が行われておりますが、必要な機能が未実装だったり、実行環境によってはさまざまな準備や設定が必要だったりします。
StaticGenでは 30位あたりになります。

数あるサイト・ジェネレーターからGridsomeを選んだのは、まずは Node.js で作られていること念頭に置きました。
これは Riotz.works では Node.js、主に TypeScript で開発を行っているため、スキルセットや開発環境を合わせたかったのがあります。

続いてVue.jsベースであることを選びました。
こちらも開発がVue.jsベースで行っているので合わせたかったものになります。

そうすると、比較的メジャーと思われるGatsbyJSHexoなどが落ちてしまいます。
GatsbyJSは非常に興味深いのですが、いつかは使ってみたいと思っていますが、今回はVue.jsベースとしました。

選択肢としてはNuxt.jsVuePressGridsome、VueWebsite になります。

Nuxt.jsはアプリ作成で使っていますが、ウェブサイトやブログ構築よりアプリ向けに感じます。
そうなるとVue.js公式であるVuePressが最有力になりそうです。

もうひとつのGridsomも調べたところ、“highly inspired by Gatsby.js”とあり、またVue.jsベースであることが、まさに私たちの考えと一致するものでした。

そしてデータソースを GraphQL で扱えるところが魅力的です。
入力ソースは基本的に Markdown を使いたいと考えていますが、エンジニアによっては CMS を使いたいケースもあるでしょう。このような複数のソースを GraphQL で扱えるのが助かります。

このような経緯から Riotz.works 公式ウェブサイトはGridsomで構築することにしました。

ただし、これまでの開発経緯から Articles と Slides はGridsomとは異なる技術を使っています。
リンクを踏むとヘッダーが異なるのはこのためです。Gridsomへ意向を考えてはいますが、なかなか着手できてない状況です。。

Riotz.works Articles ページ

Articlesページは、Hexoで作られた JAMstack なサイトです。

この Articles こそGridsomが活用できる場所ではあるのですが、Gridsomが登場する以前にHexoで作ったものになり、いずれはGridsomへ移行したいと考えてはいますが、Gridsomはまだ初期開発中で Category や Tags などのページを自前で作る必要があり、作りこみができてないです。(いずれ公式でサポートされるとは思うので待ちたいのもあり。。)

HexoStaticGenでもトップ5に入る人気のサイト・ジェネレーターです。

記事は Markdown で書けるので、エンジニア・フレンドリーといえるのではないでしょうか。
一方で表現力は落ちてしまう点がありますが、最後は HTML を直接書いて埋め込めるので、どうしても Markdown で表現しきれない部分は HTML でカバーできます。(あまりやりたくないので奥の手という感じですが)

ブログサイトをとても手軽に作ることができ、テーマも多数用意されているので好みのデザインにすることも簡単ですし、各種 Plugin もあるので簡単に拡張することもできます。

日本語の情報も多いので、比較的簡単にやりたいことや、困りごとを解決できます。

JAMstack なブログサイトをつくり始めるには、よい入口と言えるでしょう。

Riotz.works Slides ページ

[Slides](https://riotz.works/slides/ページは、静的サイトではありますが完全に手組の HTML で、”構築済みの HTML” とはなっておらず、アクセスを受けてから JavaScript で HTML を構築しているので JAMstack なサイトではありません。

こちらは、Markdown ファイルをソースとしたプレゼンスライドを作れるremark.jsを使っています。

仕組みとしては事前に用意された Markdown ファイルを、スライド形式の HTML に変換して表示なので、JAMstack とは相性が良く、JAMstack なスライドシステムがあったら使いたいと考えています。

Markdown からスライドを作るライブラリとしてはreveal.jsremark.jsぐらいで、どちらも事前構築の HTML には対応しておらず、現時点では現状のままか、時間を作って自前開発をしたいところです。

JAMstack なスライドシステムがあったら使いたいと考えていますが、現時点ではなさそうなので、しばらくは現状のままでしょう。

スライドシステムについては時間を作って自前開発にチャレンジしたいとも思っています。
ソースは Markdown で書きたいのがありますし、カジュアルな勉強会ではリアルタイムなフィードバック機能を動かしてみたいなど、いろいろとやってみたいことがあります。

ラップ、タップ、アップ 🎶

最後にハッカソンで作ったラップ、タップ、アップ 🎶ですが、こちらも JAMstack なアプリです。

技術としてはNuxt.jsを使っていて SPA で静的サイトとして生成、ホスティングしています。(SSR、サーバサイドレンダリングにすると JAMstack ではなくなります)
これにより基本的な画面は “構築済みの HTML” となり、CDN に配置した際のメリットを出せます。

ラップ対戦のルーム作成はクライアントサイドのJavaScript から Web API を呼出しています。
また動画の中継と配信も JavaScript のライブラリからサービスを呼び出しています。

ハッカソンの 24時間という限られた時間の中で、フロントエンドとサーバサイドを分離し HTML をツールを使って生成する JAMstack のアーキテクチャがまさに活かせた瞬間といえるのではないでしょうか。

サーバサイドの機能が Web API 形式で提供されているため、ロジックの変更や UI の変更といったものが相互に依存せず最小限の修正で組み込みできました。


JAMstack は公式ウェブサイトのような完全な静的サイトのほか、ブログやアナウンスなどのニュースといった緩やかな更新が発生するサイト、そしてアプリといったさまざまなサイトが実現でき、Riotz.works の中でも多様な使い方をしています。

とくにラップ、タップ、アップ 🎶のような、サイト・ジェネレーターで静的ホスティングなサイトを作っていて、Web API を呼び出しているようなケースは意外とあったりするのではないでしょうか。

実は JAMstack なサイトを作っていたけど、JAMstack のキーワードが知られてなく、そんな名前がついていたんだというケースがいろいろありそうです。(実はラップ、タップ、アップ 🎶作成時点では JAMstack の言葉は知らなかったです)

ただ、これだけ JAMstack な サイトと書いてきましたが 実はホスティングが GitHub Pages で、JAMstack ベスト プラクティスの CDN に 乗ってなかったりも。。

これまでの経緯から GitHub Pages を使ってて、またカスタムドメインを使っているほか、4サイト(リポジトリ)がのっかっているので一斉に引っ越しする必要があり、作業時間を作るのに苦慮しているためです。

JAMstack、それはハイパフォーマンスなウェブフロントを実現するアーキテクチャ

“JAMstack” と呼ばれる新しいウェブの開発手法で「より良いパフォーマンス」「より高いセキュリティ」「より安価で簡単なスケーリング」「より良質な開発者エクスペリエンス」を提供するアーキテクチャが注目を集め始めています。

JAMstack とは何か、どのように使い、どのようなメリットがあるのか、公式サイトの情報をもとに読み解きます。

JAMstack の定義


オフィシャル・サイトhttps://JAMstack.orgによると、以下の要素に基づく最新のウェブ開発アーキテクチャとされています。

  • クライアントサイドのJavaScript
  • 再利用可能なWeb API
  • 構築済みの Markup (HTML)

HTML に JavaScript そして Web API なので、ウェブフロントの開発をする場合によく使うであろう技術と言えるでしょう。

ここでは動的な要素をサーバーサイドで組み込んだ HTML などをレスポンスするのではなく、クライアントサイドのJavaScript から Web API を通じて取得/更新し、クライアントサイドでダイナミックに描画する方式、いわゆる REST API などを使ったウェブフロントの作り方を指しています。

そして Markup (HTML) の部分がポイントなのですが“prebuilt at deploy time”、デプロイ時に事前ビルドされているとしています。そして多くの場合、サイト・ジェネレーターなどを使って作ります。(ツールの紹介は後述


The JAM Stack44ページ目のスライドにある、この図が JAMstack のアーキテクチャをシンプルに表現しています。
Git に Push されたコードから、ビルドツール(サイト・ジェネレーターなど)が動作し、Web API などのデータと組み合わせて、構築済みの HTML を生成、CDN へ配置して配信します。

なぜ JAMstack なのか

なぜ JAMstack、とくに構築済みの HTML をデプロイするのか。

公式サイトでは、大きく4つ「より良いパフォーマンス」「より高いセキュリティ」「より安価で簡単なスケーリング」「より良質な開発者エクスペリエンス」のメリットを上げています。

より良いパフォーマンス

最初のページを高速に表示するためには、HTML を事前に構築しておき CDN で配信することが最適です。
構築済みでない場合、高速に配信できる CDN を介することができず、また HTML を生成するための処理を待つことにもなります。

より高いセキュリティ

サーバーサイドの処理をマイクロサービスとして API に抽象化されているため攻撃の対象となる部分を小さくできます。
また、事前に構築済みの HTML をデプロイしているため、HTML を処理するためのプロセスはオフラインにできることもメリットといえるでしょう。

より安価で簡単なスケーリング

デプロイするものは構築済みの HTML となるため CDN に配置することができ、スケーリングすることが容易になります。
CDN が安価かは悩ましい部分はありますが「Web サーバ」と「AP サーバ」をスケールさせるために用意することを考えると、CDN だけでよいので簡単とはいえるでしょう。

より良質な開発者エクスペリエンス

疎結合にすることで、よりターゲットを絞った開発とデバッグを可能とします。
構成を簡素化できることは開発者の精神衛生上よいといえるでしょう。

このようにロジックを Web API として分離し、フロントエンドを構築済みの HTML としておくことで、多くのメリットを享受できます。

ベストプラクティス

JAMstack なプロジェクトを構築する際に、いくつかのベストプラクティスを活用することでスタックのメリットを最大限に発揮できます。

CDN に全部配置されている

JAMstack なプロジェクトは、サーバサイドのコードに依存しないため、単一のサーバではなく分散して配置できます。
CDN から直接サービス提供することでスピードとパフォーマンスを発揮できます。アプリがネットワークにエッジまで配置されることで、より良いユーザー体験になります。

すべてが Git に存在する

JAMstack なプロジェクトは、誰もがgit cloneでき、必要な依存関係をnpm installなどのような標準的な手順でインストールし、プロジェクトをローカルで実行する準備ができているはずです。複製するデータベースも、複雑なインストールもありません。
これによってコントリビューターの負担を減らし、ステージングとテストのワークフローも簡略化されます。

モダンなビルドツール

モダンなビルドツールの世界によるアドバンテージを受けましょう。
それは動きの速い世界でジャングル(無法地帯)を志向するかのようですが、未来のブラウザを待たずに最新のウェブ標準を使うことができるようになります。
それは現時点では Babel、PostCSS、webpack、そしてその仲間です。

自動ビルド

JAMstack のマークアップ(HTML) は、事前ビルドされているため、コンテンツの変更はビルドを実行するまで反映されません。このプロセスを自動化するとフラストレーションを軽減できます。
これを webhook で行うことも、自動的にパブリッシュするプラットフォームなどを使うこともできます。

アトミックなデプロイ

JAMstack なプロジェクトが非常に大きくなるにつれて、新しい変更のために数百ものファイルを再デプロイする必要があるかもしれません。 これらのファイルを一度にアップロードすると、プロセスの完了までの間に不整合を生じる可能性があります。 これを避けるに、すべてのファイルがアップロードされるまで変更が行われない「アトミックデプロイ」を実行できるシステムを使用します。

キャッシュの即時無効化

ビルドからデプロイへのサイクルが定期的に行われるようになったら、デプロイの実行が反映されるようにします。CDN は側にキャッシュを消去できます。

サイト・ジェネレーター

JAMstack のメリットはわかったとして、それでサイトを作るには「構築済みの HTML」が必要となってきます。
この構築済みの HTML は手組みの HTML を用意することではなくて、サイト・ジェネレーターを使うとされています。

主なサイト・ジェネレーターは、こちらStaticGenに列挙されています。

有名どころとしては GitHub Pages でも使われているJekyllなどがあり、HugoHexoといったブログ構築用の静的ジェネレーターやNext,NuxtといったReactVue.jsのアプリ・フレームワークなどもあります。

JAMstack のコンテキストではGatsbyVuePressGridsomeなどを目にすることが多いようにも感じます。

ヘッドレス CMS

これはとくに JAMstack の要件ではないのですが、JAMstack なブログや情報発信サイトを作る際に使われるものです。

WordPress などの CMS はコンテンツを配信するための部分が含まれ、そのままホスティングすると JAMstack なサイトにはならないので、別の仕組みが必要となりますが、WordPress などのように優れたコンテンツを管理するための仕組みが欲しくなります。
そうしたニーズに応えるのが、このヘッドレス CMS です。最低限の UI でコンテンツを管理することができ、作成したコンテンツを API 経由などで提供し、上記サイト・ジェネレーターなどと組み合わせてサイトを作ります。

主なヘッドレス CMS は、こちらheadlesCMSに列挙されています。

前半に Open source なヘッドレス CMS が並び、後半に Closed source があります。
またサービスとして提供されているものは、こちらの Closed source に含まれます。たとえば最近よく目にするContentfulは Closed source になります。

サイト・ジェネレーターによっては、WordPress の REST API からコンテンツをとってきたり、ローカルの Markdown ファイルを使うこともできるので、サイト・ジェネレーターの機能と管理方法に合わせて選択します。

参考情報


実際のところ、Web API ベースなアプリ開発をしていると、意識はしてなくとも JAMstack なウェブフロントを作っているなぁというケースもあったりします。

さっくり言ってしまうと、そんな Web API ベースなアプリでウェブフロントを構築済みの HTML として CDN へ配置するものに、JAMstack の名前がついた感じになります。

名前がついたことで認識され、認識されることで広まる流れになっていくのではないでしょうか。

2018年の振り返り

2018年最後のポスト、1年間の活動を振り返ります。

サマリー

  • 発表: 6回
  • 記事: 3本
  • アプリ開発: 3本
  • ハッカソン: 1回

発表 6回

2018.02 Agile & DevOps 勉強会 -@lulzneko&@lopburny

クローズドな Agile & DevOps 勉強会でスマートデバイス と クラウドサービス を 自動パーソナライズする IoT バックエンド開発チームにおける Agile と DevOps プラクティスの発表をしました。

タイトルが長くでピンとこないのは、オリジナルのタイトルは製品名が入っていたからで、公開に当たって製品名を外す必要があったからになります。

ベースとなる話は昨年の Serverlessconf Tokyo 2017 で発表したava チームが選択した TypeScript による AWS Lambda 開発になり、Java で開発していたプラットフォームを TypeScript で開発しなおす大手術をしたプロジェクトではどのような Agile & DevOps でやっていたのかを話しました。

私たちとしては必要に駆られてのことでしたが、途中でプログラミング言語を切り替えるのは衝撃を受けたほか、そのようなことをできる人たちがいることに驚いたと言われ開発者として誇らしく感じ、そして必要なことであればどのような困難でも真正面から取り組んでいくスタイルはずっとキープしていきたいと改めて感じるイベントでした。

2018.05 JJUG CCC 2018 Spring -@lulzneko

日本最大のJavaコミュニティイベント JJUG CCC でJava から TypeScript へ 切り替えて加速するサーバーレス開発の発表をしました。

Java のコミュニティで「Java をやめて TypeScript を選びました」という主旨の発表になり、かなり緊張しながら入室したことを覚えています。
仕事では Java をずっとやってきて、よく勉強でお世話になっていた会に、このような立場で発表するとは思っていませんでした。

会場は満員御礼で立ち見でも聞いてくださる方も多く、そして熱心に耳を傾けてくださり発表者冥利に尽きる会でした。

内容については賛否両論、手厳しい指摘も上がっていましたが、新たなる可能性についての話につなげられたと思っています。

批判や厳しい指摘を恐れず、発信したいことはしっかり話す。そして議論へつなげ盛り上げることの大切さを実感できた会だと感じました。

発表について1つ反省点が、タイトルは「Java から TypeScript へ切り替えて加速する」としているのに、「Java と TypeScript の親和性」についての話になっていたなと。資料を書いているうちに、どんどんアイデアが膨らんでしまうのに気をつけねば。。

2018.06 SPAJAM 2018 東京D予選 -@lulzneko&@lopburny&@javaponny

日本最高峰のアプリクリエイター競技会 の スマートフォン アプリ ハッカソン SPAJAM。ハッカソンの内容については後述、ここでは発表パートについて。

リアルタイム の 競演 と 参加型観戦 で 音楽を最高に楽しむ🎶 「ラップ、タップ、アップ」で発表しました。

徹夜でアプリ開発をしたあとの発表会。体力的にも集中力的もかなり厳しかった。スライドに何を書くのかとても苦戦しました。

一方で話し始めるとランナーズハイならぬスピーカーズハイとでもいうような高揚感で、今までの発表の中で一番ノッていました。

発表の神様が降りてきてくださった、そんな発表でした。
このような発表を毎回できるように精進しようと心から思いました。

進行より東京D予選は最難関と言われていましたが、どのチームも素晴らしい発表をされており、最高の発表をライバルの立場として体験させてもらえたことに感謝です。

2018.09 Serverlessconf Tokyo 2018 -@lulzneko&@lopburny&@javaponny

サーバーレスアーキテクチャを用いたアプリケーション構築における知見の共有を目的とした、コミュニティ主導の技術カンファレンスで、リアルタイム動画ラップ バトル アプリを 短時間で作り上げた完全サーバーレスな秘技の発表をしました。

Serverlessconf Tokyo は Riotz.works の原点ともいえるイベントで、2017年のイベントで発表させていただいたのが Riotz.works の始まりになります。

SPAJAM で作ったアプリはフル・サーバーレスでできており、サーバーレスで戦ったからこそ、優秀賞を受賞することができたと思っています。
そのサーバーレスの素晴らしさをハッカソンの観点からお伝えできたのではないでしょうか。

今回の会場は東京タワーのスタジオで 25m プール 1面分の超巨大スクリーンでの発表でした。

このような会場ははじめてで緊張したものの、発表する楽しさを強烈に実感できる場所でした。また、このような場所で発表に臨めるよう技術と活動をしっかり行っていこうと思いました。

Vue Fes Japan 2018 Reject Conference -@lulzneko&@lopburny

日本開催初の大規模 Vue.js カンファレンスでVue.js/Nuxt.js で 実現できた PWA の リアルタイム動画ラップ バトル アプリのリジェクトコンで発表しました。

プレイドさんのオフィスで開催され、芝生スペースの素敵な場所でした。
フロント系のイベントははじめての参加で、今まで参加してきたイベントとは雰囲気が違う感じを受けましたが、楽しさはかわらず、技術イベントはいいなぁと再認しました。

懇親会では多くの方々と話をする機会がありとても楽しかったです。

東京 Node 学園祭 2018 -@lulzneko&@lopburny

年に一度、真剣に学んで楽しもう! 日本最大のNode.jsカンファレンス! でVue.js/Nuxt.js で 実現できた PWA の リアルタイム動画ラップ バトル アプリの発表をしました。

TypeScript でサーバーレスを推している身として Node.js の総本山ともいえるイベントでお話しできるのは最高の体験でした。

記事 3本

こちらは全然かけなかったので反省です。
とくに TypeScript のスターター記事を書き始めたのに2回で止まってしまった。

引き続き TypeScript でサーバーレスは推していきたいので、しっかり記事を書いて発信していくとともに、Nuxt.js や Gridsome などを使い始めているので、こちらも情報発信をやっていけるようにしたいです。

活動の仕方を見直して、記事を書く時間をしっかりとるようにしたいです。

アプリ開発 3本

まだ公開できないプロトタイプが1本ありますが、3本作れたのはよかったです。

ラップはハッカソン制作作品ですが、少しずつ機能追加などもやっていて、引き続きいろいろな機能を追加したり、おもしいことを試せたらと思っています。

ウェブサイトは Gridsome を使ってリニューアルしました。 Slides と Articles の引っ越しはできていませんが、リニューアルで念願だった Works と Engineers が追加できました。
Gridsome は JAMstack としておもしいので、ちゃんと使いこなせるようにしつつ情報発信をしていきたいと感がています。

ハッカソン 1回 -@lulzneko&@lopburny&@javaponny

SPAJAM の スマートフォン アプリ ハッカソン に 参加しました。
自分自身も、Riotz の メンバー 全員 で はじめてハッカソンに参加した記念すべきイベントでした。

5人でチーム編成のところ、Riotz は 3人とチャレンジングな参加でしたが、サーバーサイドはサーバーレスの武器を活かすことでチャレンジできる、そしてアプリ側もネイティブではなく敢えて PWA を使うことで持てる技術を最大限に生かせることで戦えると考えていました。

とはいえ日本最高峰のアプリクリエイター競技会を謳っているイベントであり、参加した東京D予選ドワンゴ会場は最難関の予選会場(進行談) とのことで、すごい人、すごいチームばかりでした。

午前のチームを超えて全体でのアイデアソンではポンポンすごいアイデアを出す方、発表の時間では今すぐ公開可能レベルのアプリ、TED 会場かと錯覚するプレゼン、参加者のとてつもないレベルに面食らいました。

当日発表のテーマ「音楽」に対して、メジャーからストリート、Google Home、Spotify に Tシャツ制作サービス連携、スマホのあらゆる機能活用と、想定しきれないありとあらゆるものがそろっていたと思っています。

Riotz.works は幸いにして「優秀賞」をいただけましたが、どのチームがとってもおかしくない、最難関の予選会場(進行談) だったのではないでしょうか。

そのような方々相手にアイデアと技術を競えたことに感謝です。
ハッカソンははじめての参加でしたが、このような最高に高揚し意地を張れる場所に、多く参加できるよう技術の研鑽と戦うマインドをキープしていきたいと思う場でした。


この1年は Riotz.works が発足して、ほぼ1年と半分。

多くの場所でお話しさせていただきました。サーバーレスはアプリ開発にとって最強の武器」を標語に活動してきた自分たちの思いをたくさんをお伝えできたのかなと思っています。

一方で残していけるはずの記事がたくさん作れなかったことは反省です。
話をすること、文章を書くこと、どちらも凄く好きなのは、今文章を書いていて感じていますが、時間を作ることが下手だったのかなと。
この辺は来年に向けて改善をしっかり考えていきます。

よかったところを伸ばし、反省点を見直して次の年へ繋げられるよう頑張ります。

よいお年を。

共有:

2018年の Riotz Works の活動を振り返る

どうも、Riotz Works のうさぎ(@lopburny)です!

昨日、年内予定していた全ての用事が終わり、年末の連休に突入しました。僕は例年クリスマスが終わった時点でそわそわして集中力が持たなくなりますが、今年は色々あって今日からやっと休暇に入ります。

そして Riotz Works も結成から1年が経過し、個人的にはここ数年で最も忙しく過ごした1年で、充実できた1年だったと思います。

一方、反省点も多々あり、ちゃんと振り返って来年の活動に活かしたいという気持ちもあります。この記事は、そんな Riotz Works での活動を振り返り、発表では言えなかったこと、私が感じたことをつらつらと書いていきます。

2018年のうちにやってきた発表

※ 2018/12/29 時点

これ、ちょうど1年前は、たったの1行でした😂

まさかこのページが埋まるとは、想像していませんでしたが、何事もチャレンジしてみるもんですね。Riotz Works の活動は、今のところ仕事というわけではないので、メンバーの 100% ピュアなモチベーションでやってこれたのも効果的だったと思います。

スマートデバイスとクラウドサービスを自動パーソナライズする IoT バックエンド開発チームにおける Agile と DevOps プラクティス

@Agile & DevOps 勉強会、 発表資料はこちら

2月、@lulzneko@lopburnyが発表しました。Riotz Works が結成して 1回目の発表が Serverlessconf Tokyo 2017 という大きくてパブリックな発表だったのに対して、今回(2回目)は Closed な勉強会だったので比較的緊張はしなかったです。

しかし、タイトルにもあるように、勉強会のテーマは Agile や DevOps といった開発プロセスなので、参加者のみなさんが必ずしも Web やクラウドに明るいわけではなく、様々なバックグラウンドを持つ人にどう伝わるか悩ましいところでした。

中盤の自分のパートが AWS に触れたことがない人には分かりにくい内容だったと自覚し、補足説明をたくさん入れるようにしましたが、本番では早口で突っ走るような話し方になっていたかもしれません。

発表後、「刺さる人には刺さった」というコメントをもらったときは嬉しかったです。

Java から TypeScript へ切り替えて加速するサーバーレス開発

@JJUG CCC 2018 Spring、 発表資料はこちら

5月26日。@lulznekoの単独発表です。

AWS Lambda は、リリース当初から現在に至るまで、Java ランタイムを選択すると必然的に Cold Start に悩まされることになります(Cold Start を無視してもいいケースなら問題になりません)。この問題に対するアプローチはいくつかあると思いますが、私たちのチームが身をもって実践してみたことで、「Java 開発者において、TypeScript は良い選択になり得る」というのがポイントになります。

発表会場が開始後すぐ埋まり、立ち見の方もいらっしゃるほど盛況でした。このアプローチに対するフィードバックは賛否両論ありましたが、みなさんにとって興味深い内容だったのではないかと思います。

リアルタイムの共演と参加型観戦で音楽を最高に楽しむ🎶「ラップ、タップ、アップ」

@SPAJAM 2018 東京D予選、 発表資料はこちら

6月16日~17日。今回はカンファレンスではなくハッカソンです。@lulzneko@javaponny@lopburny3人で出場しました。メンバー全員初めてのハッカソンで、Riotz Works としても初です。もともとこの SPAJAM というハッカソンには注目していて、Riotz Works 結成前から「出てみたい」と何度か話したことがありました。そして、思い切って、エントリーしたのです。

1日目の朝、そわそわしながら会場へ向かい、午前のアイディアソンを終えて、ハッカソンのテーマ(音楽)が発表されました。会場近くの築地市場で海鮮丼を食べながら、どうする?何作る?と議論をはじめ、私が思いついたのが、このラップバトルです。言ってみたものの、これどうやってつくるの、やばくね、みたいな感じでした💦

ラップバトルのサービスは世の中にいくつも存在しますが、僕はよりインタラクティブな演出がいいなと思ったのと、ラップバトルの「対戦」と「観戦」を 同時にかつリアルタイムにできる仕組みを作ることで差別化を図りました。いわば Twitch のゲーム実況ストリーマー同士が即座で対戦を始め、その様子をそれぞれのチャンネルで数百〜数千の人たちが観戦しながらコメントやヤジを飛ばす様子。そういうのが作りたかったです。

果たして作りきれるだろうか。。。午後から真面目に調査します。数時間ほどでなんとか SkyWay のサンプルを動かすことができました。夜になって会場を出た時点で、ようやく翌日の発表に向けた最も基本的な機能(リアルタイム動画ストリーミング)ができました。そして、夜も気を抜くことはできません。オールナイトで作業して30分ほど仮眠を取り、発表直前まで開発を進めた結果、なんとかデモができるところまで作れました。

結果は・・・なんと、優秀賞をいただきました!!

今でもあの感動を忘れられません。恐らく今年起きた出来事の中で最強のインパクトでした。。

そして帰りに飲んだビールは間違いなく今年飲んできたビールの中で最高の味でした。😂

残念ながら SPAJAM の本選に出ることはできませんでしたが、次はもっと進みたいと思います!!

リアルタイム動画ラップバトルアプリを短時間で作り上げた完全サーバーレスな被疑

@Serverlessconf Tokyo 2018、 発表資料はこちら

9月29日。@lulzneko@javaponny@lopburny3人で発表しました。Serverlessconf Tokyo での発表は、去年に続き2回目となります。夏のハッカソンの余韻がまだ残っていて、この発表の準備にも気合が入りました。特に、会場スクリーンのアスペクト比が 48:9 という、ものすごく大きくて迫力のある会場だったため、わくわくしつつもかなり緊張していました😂

気合を入れて会場に着き、生でみる会場の広さとスクリーンの迫力にびっくりしながら、デモの準備をしました。ちゃんと動くのを確認してこれはいける!と思ったんですが、本番では開始とともにデモが固まって動かないことに。そういうことにならないよう、開始10分前からアプリを立ち上げた状態で待機したのですが、なぜか開始のタイミングで 僕のスマホが固まってしまったんです。えーーー、なんで。。。ショック。。。とパニックになってしまった僕は、落ち着いて話すことができず、発表中に焦りを出してしまった気がして反省しています。

当時@lulznekoが言っていたように、「デモが動かないことは、よくあることですね」と、一旦落ち着いて進めていき、メンバーが対応してくれることを待つべきだったことを学びました。

幸い、メンバーが対応してくれたおかげて、発表中にデモが復旧し、ハッカソンで作ったアプリを披露することができました。また、サーバーレス関連の色んな方々とお話ができて、他の発表についても、どれもすごく勉強になったので、貴重なイベントでした。

Vue.js/Nuxt.js で実現できた PWA なリアルタイム動画ラップバトルアプリ

@Vue Fes Japan 2018 Reject Conference、 発表資料はこちら

11月10日。@lulzneko@lopburnyが発表しました。前回の Serverlessconf ではバックエンドの内容がメインでしたが、今回はフロントエンドにフォーカスした話です。元々、Vue Fes Japan そのものにエントリーしましたが、枠が非常に限られていたらしく、採用にはならずとも魅力的な内容だということで、 Reject Conference に参加させていただくことになりました。

Riotz Works のメンバーは、全員フロントエンド以外の領域を得意としています。ですが、フロントエンド/バックエンドの領域にこだわらず、思いついたことは自ら形にしていくことが大事だと思っていますし、ハッカソンでものを作っていく中で、人の目にダイレクトに届くUIの重要性と楽しさに気づいてしまったので、もっと極めたいなと思っています。

今回の発表は、今まで数を重ねてきたこともあり自信持ってできた気がして、懇親会でも色んな方々とお話させていただき、個人的に最も楽しくできた発表でした。

Vue.js/Nuxt.js と TypeScript で実現する PWA なリアルタイム動画ラップバトルアプリ〜フル Node.js エコシステムで戦ったモバイルアプリのハッカソン〜

@東京Node学園祭2018、 発表資料はこちら

11月23日。@lulzneko@lopburnyが発表しました。今回も話のネタそのものは変わらないですが、Riotz Works が Node.js を使い始めて、2018年をどう過ごしたかという集合体のような内容です。またサーバーサイド(Node.js)→フロントエンド(Vue.js)→Node.js環境全般 という流れができたのと、Node.js コミュニティでの発表ということで胸が熱くなりました。

発表も比較的慣れてきたところで順調に進みましたが、React 界隈の方々が多く、前回よりは重い空気になることもありました。ですが発表の順番が最後で、たくさんの方々に聞いていただき、たくさんフィードバックをもらえたので、かなり手応えのあったイベントでした。

2018年を振り返って、よかったこと

あえて2点にしぼると、こんな感じです。

  • ハッカソンに出て、アイディアを形にできたこと
  • 次々と発表が決まり、絶え間なくイベントに参加できたこと

2018年を振り返って、反省したいこと

たくさんありますが、これも2点にしぼります。Riotz Works というより個人的な話ですね。

  • タスクの優先順位を考慮した、自分のリソース管理
  • 発表以外のアウトプットができていない点

当たり前な話ですが、何らかの活動を継続して進めていくためには、自分の体力・時間などのリソース管理を上手にできることが重要なポイントかなと思います。

僕は思いつきとその時のモチベーションに左右されやすいタイプで、できないことも意地を張って挑戦し続けたりするので、無駄にした時間が結構ありました。目標やコミットしたことに対して確実に結果を出すためには、もっと冷静に自分を見直して、シビアにならないといけないですね。

あと、もっとブログ書きたかったのですが、上記のリソース管理ができなかったせいか、できていません。書きたい話は結構あります。2019年からばんばん出して行きたいと思います。

終わりに

ちょっと長くなってしまいましたが、いかがだったでしょうか。
Riotz Works は 2019年も楽しく活動していきたいと思います。みなさん良いお年を〜

API Gateway の WebSocket でチャットを実装 w/Serverless Framework

この記事はServerless Advent Calendar 2018の 22日目になります。

AWS re:Invent で発表された API Gateway の WebSocket 対応、ついに利用できるようになりました!
WebSocket がサーバーレスで簡単に利用できるようになるとアプリの幅も広がり、いろいろなことができるようになります。
さっそく API Gateway の WebSocket を試してみます。

※ 今回 Serverless Framework の serverless-websockets-plugin を使いますが 2018年12月現在、暫定の実装になるとのことです。API Gateway の WebSocket 対応が AWS CloudFormation で未サポートのため Serverless Framework 本体には含まれず Plugin になっているとのこと。正式版では構文など変わる可能性があることに注意が必要です。

しかしながら “With all that out of the way, play with our new presents!” ということで、楽しんでみましょう!

環境
本記事の開発環境は以下となります。

  • Windows 10 64bit + WSL Ubuntu 18.04.1 LTS
  • Visual Studio Code
  • Node.js 8.10.0
  • Yarn 1.12.3
  • TypeScript 3.2.2
  • Serverless Framework 1.35.1
  • Serverless Websockets Plugin 1.0.0

参考情報

WebSocket について

HTTP ベースの Web API ではサーバーに対して接続、リクエストを送り、処理結果のレスポンスを受け取り、切断終了の流れになります。
必要に応じて、このリクエスト/レスポンスのやり取りを繰り返す形になります。

それに対して WebSocket はサーバーに接続後、コネクションを維持したまま双方向でメッセージを送ることができます。
これは通常のリクエスト/レスポンスに当たるやり取りのほかに、サーバー側から任意のタイミングでメッセージを送れます。

たとえば私たちがハッカソンで作った「ラップ、タップ、アップ 🎶」では、演奏者へのフィードバックとして「👍」を送ることができ、その数をリアルタイムでカウントする機能があります。

この「👍」をリアルタイムでカウントする部分を HTTP ベースの Web API で作るとすると、アプリから「👍」の数を取得する API を繰り返し「リクエスト/レスポンス」して受け取る必要が出てきます。
仮に数に変化がなかったとしてもアプリ側は知るすべがないので、繰り返し「👍」の数を取得しに行かなければなりません。

WebSocket が使える場合、コネクションは維持したまま必要な時に「👍」の数をサーバー側がアプリへメッセージを送ることができるようになります。
「👍」の数に変化がなかった場合は維持されているコネクションの中にメッセージが流れないだけでアプリはとくに何もする必要はありません。変化があった時だけサーバーが教えてくれるので、それに応じてアプリの表示を変えるだけになります。

これにより不要なリクエスト/レスポンスを減らせるほか、よりリアルタイムに近い状態で変化を受け取ることができるようになります。
HTTP ベースでは「リクエスト/レスポンス」で受け取り、次のリクエストを出すまでの間にあった変化は結果しか受け取れません。5だった「👍」を次のリクエスト/レスポンスでは 10になっているかもしれません。

WebSocket では状態の変化を断続的に返すことも可能になるので、5、6、7… とメッセージを返せます。

これにより、よりスムーズに描画を変えていくことができるようになります。
これはチャットのようなコミュニケーションや金融などの取引の価格情報などに使うことができます。

今回API Gatewayがこの WebSocket に対応したので、その使い方をチャットを実装することで確認します。
(WebSocket でチャットは定番すぎますが、「👍」のカウントだとさみしいですからね)

※「ラップ、タップ、アップ 🎶」では、API Gateway がまだ WebSocket が扱えなかったので、Firebase Realtime Databaseを使って実現しています。

Node.js プロジェクトの準備

Serverless Framework のボイラープレートを使って、TypeScript の Node.js プロジェクトを作成します。

プロジェクトのディレクトリを作成しプロジェクトのひな型を作ります。

1
2
3
4
5
6
7
8
9
username@pc:~$ mkdir samples-apigateway-websocket-chat
username@pc:~$ cd samples-apigateway-websocket-chat
username@pc:~/samples-apigateway-websocket-chat$

username@pc:~/samples-apigateway-websocket-chat$ npx serverless create --template aws-nodejs-typescript
Serverless: Generating boilerplate...
(省略)
Serverless: Successfully generated boilerplate for template: "aws-nodejs-typescript"
Serverless: NOTE: Please update the "service" property in serverless.yml with your service name

続いて Serverless Framework をローカルで追加し、AWS SDK と WebSocket クライアント wscat、必要なパッケージを最新化してインストールします。
Serverless Framework はグローバルに追加して使うようですが、複数人開発でグローバルのを使っているとバージョンの違いなどでトラブルがあったのでpackage.jsonで明示して、それを使うようにしているためです。サクッと試すにはグローバルでもよいでしょう。

1
2
3
username@pc:~/samples-apigateway-websocket-chat$ yarn add -D serverless serverless-websockets-plugin wscat
username@pc:~/samples-apigateway-websocket-chat$ yarn upgrade --latest
username@pc:~/samples-apigateway-websocket-chat$ yarn add aws-sdk

package.jsonをプロジェクトに合わせて修正します。
主にnamedescriptionauthorあたりを合わせるとよいでしょう。
また、作成しているのはアプリケーションなのでモジュール公開の防止のために"private": trueを設定しておくとよいでしょう。private の詳細は、こちらのpackage.json | npm Documentationをご確認ください。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"name": "samples-apigateway-websocket-chat",
"version": "1.0.0",
"private": true,
"dependencies": {
"aws-sdk": "^2.382.0"
},
"devDependencies": {
"@types/aws-lambda": "8.10.17",
"@types/node": "^10.12.18",
"serverless": "^1.35.1",
"serverless-webpack": "^5.1.1",
"serverless-websockets-plugin": "^1.0.0",
"source-map-support": "^0.5.6",
"ts-loader": "^5.3.2",
"typescript": "^3.2.2",
"webpack": "^4.5.0",
"wscat": "^2.2.1"
},
"author": "Riotz.works (https://riotz.works)",
"license": "MIT"
}

Serverless Framework の設定

serverless.ymlを編集し Serverless Framework の設定を行います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
service:
name: samples-apigateway-websocket-chat

plugins:
- serverless-webpack
- serverless-websockets-plugin

provider:
name: aws
stage: ${ opt:stage, 'dev' }
region: ${ opt:region, 'us-west-2' }
runtime: nodejs8.10
iamRoleStatements:
- Effect: Allow
Action:
- execute-api:ManageConnections
Resource:
- arn:aws:execute-api:*:*:**/@connections/*
- Effect: Allow
Action:
- dynamodb:Scan
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
Resource:
- Fn::GetAtt: [ ChatConnectionsTable, Arn ]
environment:
DYNAMODB_CONNECTIONS:
Ref: ChatConnectionsTable
websocketApiName: ${self:service.name}-${self:provider.stage}
websocketApiRouteSelectionExpression: $request.body.action

functions:
connect:
handler: handler.connect
events:
- websocket:
routeKey: $connect
disconnect:
handler: handler.disconnect
events:
- websocket:
routeKey: $disconnect
defaultMessage:
handler: handler.defaultMessage
events:
- websocket:
routeKey: $default
sendMessage:
handler: handler.sendMessage
events:
- websocket:
routeKey: sendMessage

resources:
Resources:
ChatConnectionsTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: ${self:service.name}-connections-${self:provider.stage}
AttributeDefinitions:
- AttributeName: ConnectionId
AttributeType: S
KeySchema:
- AttributeName: ConnectionId
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
SSESpecification:
SSEEnabled: True
StreamSpecification:
StreamViewType: NEW_AND_OLD_IMAGES

pluginsに API Gateway WebSocket を使うためのserverless-websockets-pluginを追加します。

iamRoleStatementsでは、API Gateway の WebSocket API を呼び出すためのexecute-api:ManageConnectionsに許可を与えます。
また WebSocket に接続しているクライアントのコネクションを管理するための DynamoDB が必要なので、DynamoDB に関する許可も与えます。

30行目、31行目のwebsocketApiNamewebsocketApiRouteSelectionExpressionは、serverless-websockets-plugin の設定になります。websocketApiNameは管理用にわかりやすい名前を設定しておくとよいでしょう。

functionsは WebSocket のイベントとアクションに合わせて定義を行います。
eventswebsocketが追加でき、websocketApiRouteSelectionExpressionに設定された Key の値とrouteKeyの文字列のマッチングによって起動する Lambda を振り分けています。
$connect$disconnectは WebSocket の接続と切断に対応します。また$defaultはマッチするアクションがない場合に呼び出されます。
最後のsendMessageが WebSocket で受け取るメッセージのキーになります。具体的には{ "action":"sendMessage", "data":"hello world" }のような JSON のactionに入る文字列のマッチングになります。

resourcesは WebSocket のコネクション管理用 DynamoDB を定義しています。
今回は最低限のConnectionIdだけを管理します。名前など無しの完全に匿名のメッセージだけのチャットになります。(WebSocket の動きと実装を試すってことで💦)

AWS Lambda の実装

handler.tsに処理を実装します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import { APIGatewayEventRequestContext, APIGatewayProxyEvent, APIGatewayProxyHandler, APIGatewayProxyResult } from 'aws-lambda';
import { ApiGatewayManagementApi, DynamoDB } from 'aws-sdk';

interface APIGatewayProxyEventWithWebSocket extends APIGatewayProxyEvent {
requestContext: APIGatewayEventRequestContextWithWebSocket
}
interface APIGatewayEventRequestContextWithWebSocket extends APIGatewayEventRequestContext {
domainName: string,
connectionId: string
}


const apigateway = ({ domainName, stage }): ApiGatewayManagementApi => new ApiGatewayManagementApi({ endpoint: `${domainName}/${stage}` });
const dynamodb = new DynamoDB.DocumentClient();

export const connect: APIGatewayProxyHandler = async (event: APIGatewayProxyEventWithWebSocket): Promise<Result> => {
console.debug('Starting Lambda handler: event=%s', JSON.stringify(event));
await dynamodb.put({ TableName: process.env.DYNAMODB_CONNECTIONS, Item: { ConnectionId: event.requestContext.connectionId }}).promise();
return new Result('Connected');
};

export const disconnect: APIGatewayProxyHandler = async (event: APIGatewayProxyEventWithWebSocket): Promise<Result> => {
console.debug('Starting Lambda handler: event=%s', JSON.stringify(event));
await dynamodb.delete({ TableName: process.env.DYNAMODB_CONNECTIONS, Key: { ConnectionId: event.requestContext.connectionId }}).promise();
return new Result('Disconnected');
};

export const defaultMessage: APIGatewayProxyHandler = async (event: APIGatewayProxyEventWithWebSocket): Promise<Result> => {
console.debug('Starting Lambda handler: event=%s', JSON.stringify(event));
const params: ApiGatewayManagementApi.Types.PostToConnectionRequest = {
ConnectionId: event.requestContext.connectionId,
Data: 'Error: Invalid action type'
};
await apigateway(event.requestContext).postToConnection(params).promise();
return new Result('Error: Invalid action type', 500);
}

export const sendMessage: APIGatewayProxyHandler = async (event: APIGatewayProxyEventWithWebSocket, context, callback): Promise<Result> => {
console.debug('Starting Lambda handler: event=%s', JSON.stringify(event));
const connections = await dynamodb.scan({ TableName: process.env.DYNAMODB_CONNECTIONS, ProjectionExpression: 'ConnectionId' }).promise();
await Promise.all(connections.Items.map(async ({ ConnectionId }) => {
try {
const params: ApiGatewayManagementApi.Types.PostToConnectionRequest = {
ConnectionId: ConnectionId,
Data: JSON.parse(event.body).data
};
await apigateway(event.requestContext).postToConnection(params).promise();
} catch (e) {
if (e.statusCode === 410) {
await dynamodb.delete({ TableName: process.env.DYNAMODB_CONNECTIONS, Key: { ConnectionId: ConnectionId }}).promise();
} else {
throw e;
}
}
}));
return new Result('OK');
}


class Result implements APIGatewayProxyResult {
public constructor(public body: string, public statusCode: number = 200) {}
}

4行目~10行目の interface 宣言ですが、こちらは API Gateway の WebSocket 対応の TypeScript 型定義がまだ入っていないので補完するために宣言しています。requestContextに入ってくるdomainNameconnectionIdが必要なため追加しています。型定義が更新されたら不要となります。

13行目ApiGatewayManagementApiのインスタンスを取得する関数ですが、API Gateway から WebSocket のメッセージを返す際にendpointが必要となり、これがdomainNamestageから決まってきます。固定値の場合はよいのですが、今回のように動的に決まってくる場合はrequestContextから受け取ったdomainNamestageが必要なため毎回インスタンスを生成しています。

16行目~58行目でserverless.ymlに定義した Lambda のエントリーポイントと実装があります。

connectdisconnectは WebSocket の「接続/切断」の際に呼び出されます。
接続時にconnectionIdを DynamoDB へ保存し、切断時に削除しています。切断は呼び出されないこともあるので、注意が必要です。

defaultMessageは WebSocket で受け取ったメッセージに対応するアクションがなかった場合に呼び出されます。ここでは “Error: Invalid action type” をクライアントに返しています。
WebSocket でメッセージを返すにはApiGatewayManagementApipostToConnection()を呼び出します。その際にクライアントのconnectionIdが必要となります。
この関数のようにメッセージを送ってきたクライアントだけにメッセージを送る場合はrequestContextconnectionIdが使えるので、それを使ってエラーメッセージを返します。

最後のsendMessageは、チャットのコメントを送る処理になります。リアルタイムに複数クライアントへメッセージを送る WebSocket を使う処理の肝となる部分です。
複数クライアントにメッセージを返すには、メッセージを送るべきクライアントすべてのconnectionIdが必要となり、それぞれにApiGatewayManagementApi#postToConnection()を行う必要があります。
つまり API Gateway が接続中のクライアントを知ってくれてるわけではないので、自前で管理する必要があり、そのために DynamoDB を用意しているものになります。

今回は全員参加の簡単な実装なので、DynamoDB のコネクション管理テーブルをスキャンし、全件に対してApiGatewayManagementApi#postToConnection()を呼び出しています。(なんか、もっとスマートな実装できないかなぁ)

ApiGatewayManagementApi#postToConnection()を呼び出す際に、コネクションが切断されているクライアントがありえます。先ほど「切断は呼び出されないこともあるので、注意が必要です。」と書きました通り、クライアントが切断されてもイベントが呼び出されないケースもあります。そのため DynamoDB への削除されずconnectionIdが残るケースもありえます。その場合statusCode410のエラーが投げられるので、そのエラーが投げられた場合は DynamoDB から該当するconnectionIdを削除しておき再発防止しておきます。

デプロイ & 実行!

デプロイは Serverless Framework がしっかりやってくれるので、以下のコマンドで行えます。
あらかじめ AWS の Access Key の用意とプロファイルを設定しておきます。(デフォルト・プロファイルでない場合は--aws-profile [your profile name]と利用するプロファイル名を--aws-profileで指定します)

1
2
3
4
5
6
username@pc:~/samples-apigateway-websocket-chat$ yarn serverless deploy
(省略)
Serverless: Deploying Websockets API named "samples-apigateway-websocket-chat-dev"...
Serverless: Websockets API named "samples-apigateway-websocket-chat-dev" with ID "6ovkt8XX" has been deployed.
Serverless: Websocket URL: wss://6ovkt8XX.execute-api.us-west-2.amazonaws.com/dev/
Done in 137.90s.

デプロイが完了すると、コマンドの実行結果に WebSocket の URL が出力されます。
その URL に対してwscatで接続し API Gateway WebSocket の動きを確認します。

1
2
3
username@pc:~/samples-apigateway-websocket-chat$ yarn wscat -c wss://6ovkt8XX.execute-api.us-west-2.amazonaws.com/dev/
connected (press CTRL+C to quit)
>

接続できると>で入力待ちになります。{ "action":"sendMessage", "data":"hello world" }とメッセージを送ると、チャットのコメントが帰ってきます。

1
2
3
4
5
username@pc:~/samples-apigateway-websocket-chat$ yarn wscat -c wss://6ovkt8XX.execute-api.us-west-2.amazonaws.com/dev/
connected (press CTRL+C to quit)
> { "action":"sendMessage", "data":"hello world" }
< hello world
>

複数のコンソールから接続すると、送ったコメントがすべてのコンソールに流れてきます。
WebSocket でリアルタイムに複数クライアントへメッセージが遅れていることが確認できます。

チャットとは名ばかりのコメントだけを送りあうだけの実装(しかも wscat によるコマンドライン)でしたが、API Gateway WebSocket の実装がつかめました。

Serverless Framework は今後の AWS CloudFormation 対応によって変わってくる部分がありますが、こんなに簡単に設定できるのでとても助かります。

WebSocket が簡単に利用できるようになったので、いろいろなアプリづくりに生かせそうで楽しみです。


では、ハッピー・サーバーレス・ライフ! ハッピー・ホリデー!!