Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

クラウド時代における分散Webシステムの構成とスケーリング #seccamp

2020-11-01
セキュリティ・キャンプ全国大会2020 オンライン
プロダクトセキュリティトラック
クラウド時代における分散Webシステムの構成とスケーリング

事前課題: https://gist.github.com/nekoruri/6b638b4ca551552480b9d3de3bb61151

  • Be the first to comment

  • Be the first to like this

クラウド時代における分散Webシステムの構成とスケーリング #seccamp

  1. 1. クラウド時代における 分散Webシステムの構成とスケーリング セキュリティ・キャンプ プロダクトセキュリティトラック 仲山昌宏 (@nekoruri)
  2. 2. 仲山 昌宏 / @nekoruri • 株式会社WHERE IoT基盤センター サービスプロデューサー(2016-) • セキュリティ・キャンプ 講師(2015-) • SecHack365 トレーナー(2017-) • 技術系同人誌サークル 「めもおきば」「ssmjp同人部」 • #ssmjp / #qpstudy / #serverlesstokyo • ProjectDIVA Arcade LV.631 2
  3. 3. 経歴 • 2003-09~2005-03 大学院ネットワーク管理(慶應SFC/徳田村井研) • 2004-03~2010-06 WIDE Project irc.fujisawa.wide.ad.jp運用 • 2004-09〜2005-10 国際大学GLOCOM (研究アシスタント) • 2005-08〜2008-09 AIP • 2008-10〜2009-12 KBB, I&D • 2010-01〜2013-06 Xtone • 2013-07〜2016-01 CyberAgent (パシャオク⇒Ameba⇒DC運用) • 2016-02〜現職 WHERE (IoTスタートアップ) ⬅今ここ SNS CGM ソーシャルゲーム ・クラウド IoT サーバーレス
  4. 4. 主なスキルセット • システム設計 • クラウドとIoTデバイス組み合わせ 良い感じのシステム/ソリューション • ウェブアプリの内部アーキテクチャ • アプリケーション開発 • サーバーレス構成なサーバサイド • 普通のサーバサイド(+フロント) Perl、Ruby、Python、JS、PHP • 過去にはWindowsアプリとかも • 情報システム • 社内ITシステムの設計、運用 • 情報セキュリティマネジメント • サーバ/ネットワーク運用 • サーバHW(特にストレージ)周り • IPネットワーク • 「必要があればなんでもやる」 • 「やりたい事を実現する」 4
  5. 5. すすめかた • サンプルアプリをベースに、高信頼なシステムを設計する • 最初にサンプルアプリの解説をします • 5チームに分かれてハッカソン • モブプログラミング(後述) • ハッカソンの流れ • サンプルアプリのユースケースをより具体的に想定し、 スケールさせるうえでの課題と、それを解決する設計を考える • 時間内にできる限り実装して、その設計を検証する • どんな設計をしたかを発表し、それに対して議論する
  6. 6. スケジュール • 前説 08:30~08:40 • サンプルアプリの解説 08:40~09:00 • ミニハッカソン 設計テーマ決め 09:00~09:30 • ミニハッカソン 実装 09:30~11:30 • 各チーム発表 11:30~12:00 • 講評+まとめ 12:00~12:30
  7. 7. サンプルアプリ • タイムライン型アプリケーションの基本的な構造 • ニュースサイトの新着ニュース通知や フォロー関係のあるタイムラインサービス(SNS) • 今は「自分の投稿」をただ保存し取得する部分だけを実装 • サーバーレスアーキテクチャを採用
  8. 8. サーバーレス • 狭義には、「サーバー」を事前に確保することなく、実際に消費した リソース分だけ利用できるような実行モデル • 広義には、それを活用したベストプラクティス群を含む 非同期、疎結合、ステートレス、など • FaaS • 自分の書いたプログラムを動かせる • Functional SaaS(BaaS) • 具体的なサービスをAPIとして提供する
  9. 9. FaaS (Function as a Service) • 「Function(関数)」と呼ばれる小さなプログラムの実行環境 • 起動プロセス数などリソース量をクラウド側が動的に管理 • 消費したCPU時間やメモリに対して課金 • AWS Lambda、Azure Functions、Google Cloud Functions • 今回はAzure Functionsを利用します • 参考:サーバーレスコンテナ実行環境 • 関数の代わりにDockerコンテナを動かす基盤 • Google Cloud Run • AWS Fargate、Azure Container Instances
  10. 10. Functional SaaS(Software as a Service) • 具体的なサービスをAPIとして提供 • 既存のアプリケーションにおける「ライブラリ」「ミドルウェア」に相当 • データベース、メール送受信、メッセージキュー、全文検索、etc • BaaS(Backend as a Service)とも呼ばれる • 今回はAzure Cosmos DBを利用
  11. 11. 全体像 Static Web Apps (Netlify) HTML Azure Functions 投稿API タイムラインAPI その他API ブラウザ クライアント アプリ JS CSS 認証
  12. 12. Static Web Apps • 静的コンテンツを提供 • 機能としては3つ • ログイン・ログアウト用URLへのリンク • 投稿 • タイムラインの表示
  13. 13. Azure Functions • サーバ側のAPIを提供 • 「Azure App Service」という基盤の上で 「Azure Functions」というFaaSが動いている • ドキュメント • Azure Functions のドキュメント • App Service のドキュメント
  14. 14. Azure Functions (認証) • App Service組み込みの認証連携機能を利用 • Azure App Service および Azure Functions での認証と承認 • Azure AD ログインを使用するように App Service または Azure Functions アプリを構成する • しくみ • 特定のURL(/.auth/login/aad)を開くと認証される • 認証されるとCookieに保存 • API呼び出し時にCookieを送ることで認証状態を送信 • 関数実行前に検証されてリクエストヘッダに追加される
  15. 15. Azure Functions (投稿API) • 投稿処理 • POST /api/post • 実装: api/post/index.js • 投稿されたデータを、Cosmos DBに保存する • アウトプットバインディングという仕組みを利用 • functions.jsonで出力先DBを設定 • context.bindings.outputDocumentに保存内容を代入 • 関数の実行後にDBに保存される
  16. 16. Azure Functions (投稿API) 検証されたログインユーザ名 保存したいドキュメントを アウトプットバインディングに送る
  17. 17. Azure Functions (タイムラインAPI) • 特定のユーザのタイムラインを表示 • POST /api/timeline • 実装: api/timeline/index.js • 指定されたユーザか自分の投稿をCosmos DBから取得し返す • Cosmos DB(旧名:DocumentDB)へのクエリを実行 • Azure Cosmos DB のドキュメント • Azure Cosmos DB でのパーティション分割と水平スケーリング • Azure Cosmos DB のインデックス作成 - 概要
  18. 18. Azure Functions (タイムラインAPI) Cosmos DBへのクエリとパラメータ クエリの実行と配列化 動作確認用ログ出力 必要な項目のみ出力
  19. 19. 新しい関数を増やす
  20. 20. Cosmos DB • 分散データベース • うまくつかえば地球規模のスケーラビリティ • 様々なデータモデル(今回は単純なドキュメントDBを利用) • RU(要求ユニット)に対して課金される • IDとパーティションキーを指定した1KBの読み取りが1RU • Azure Cosmos DB の要求ユニット • パーティションキーをどう選ぶかが重要 • Azure Cosmos DB Performance Tips • 消費したRUを確認する • timelineアプリには確認用にCosmos DBからの戻り値をログ出力 しているので、x-ms-request-charge として確認可能 • Azure Portal上でクエリを実行してみて確認
  21. 21. 消費RUの確認 (1)
  22. 22. 消費RUの確認 (2)
  23. 23. Next step • 「フォロー関係」を保存し、フォロー先の投稿が見られるようにする • ここからきちんと設計が必要! • ユースケースをきちんと考える • 「フォローした相手の投稿を一覧で見られる」 というのは突き詰めると何をやっているのか? 何が必要なのか? • 他に必要なユースケースはなんだろうか?
  24. 24. すすめかた • サンプルアプリをベースに、高信頼なシステムを設計する • 最初にサンプルアプリの解説をします • 5チームに分かれてハッカソン • モブプログラミング(後述) • ハッカソンの流れ • サンプルアプリのユースケースをより具体的に想定し、 スケールさせるうえでの課題と、それを解決する設計を考える • 時間内にできる限り実装して、その設計を検証する • どんな設計をしたかを発表し、それに対して議論する
  25. 25. 設計テーマの共有 • 9時30分になったら、設計テーマをスライドにまとめてください。 • どんなユースケースと課題を想定し、 どんな設計でそれを解決・改善しようとしているのか • Google Slideで2枚以内 • まとめたらSlackに投稿 • 良いテーマがあったら話してもらう、かも?
  26. 26. モブプログラミング • チーム「全員」で「同じ作業」に向かう • 分担では無く共同作業 出典:https://speakerdeck.com/takaking22/mob-programming-startup-manual-number-mobprogramming-number-mobupuro
  27. 27. モブプログラミング • 15~20分くらいでドライバー(操作担当)を交代 ⇒いつでも作業を共有できる状態を保つことが重要 画面共有やVSCode Live Shareなどを上手く使ってください。 • 作業内容はどんどんGitHubに上げていく • 議論や結論もその場でドキュメントに書いて共有 • Google DocumentやGitHub Wiki等を活用 • 苦手な作業があればチーム内で手助けしあう(暗黙知の共有)
  28. 28. チーム発表 • 11時30分から各チーム持ち時間5分で発表 • 発表しているチーム以外の人は、 シートを用意するのでコメントを書いてください • 必ず入れて欲しい内容 • 想定した利用ケースとスケール上の課題 • スケールさせるために考えた設計 • どこまで実装できたか、検証できたか
  29. 29. チーム発表 • ヒント • 設計を数値による検証で裏付ける • コストとユースケースのバランスを取る • 実装してわかった課題に立ち向かう • 運用時の視点を持つ
  30. 30. 設計例
  31. 31. ユースケースと課題 • Twitterを想定 • ツイートできる • ツイートはどんどん増えていく • 利用者もどんどん増えていく • フォローできる • ほとんどの人は、フォロー人数はそこまで多くない • ツイートを削除できる
  32. 32. 基本設計 • 以下のテーブルを持つ • (A)ユーザ自身のツイートのテーブル(ツイート) • (B)ユーザをフォローしている相手を格納するテーブル(フォロイー) • (C)ユーザのフォロー先のツイートのテーブル(タイムライン)
  33. 33. テーブル構造 • (A)ユーザ自身のツイートのテーブル(ツイート) • パーティションキー:ユーザID • インデックス:タイムスタンプ • データ:ツイート内容、削除フラグ • (B)ユーザをフォローしている相手を格納するテーブル(フォロイー) • パーティションキー:ユーザID • データ:「ユーザID」をフォローしている人のユーザIDの配列 • (C)ユーザのフォロー先のツイートのテーブル(タイムライン) • パーティションキー:ユーザID • インデックス:タイムスタンプ • TTL:1ヶ月
  34. 34. 投稿時 • 投稿時にA(ツイート)に保存すると同時に、以下の処理を非同期 でおこなう • B(フォロイー)からフォローしている相手の一覧を取得 • 相手のC(タイムライン)に追加していく • A(ツイート)への追記は1回 • フォロワー数に応じて回数が増えるので、特別にフォロワー数が 多い人の処理は遅れるが、ほとんどの人は非同期でも少ない時間 で書き込みされる ⇒品質の制御(何かを切り捨て、守りたい品質を守る)
  35. 35. タイムライン表示 • C(タイムライン)から最新のタイムラインを取得する • タイムスタンプでソートすることで最新N件 • 一ヶ月以上古いツイートはタイムライン経由では諦める • A(ツイート)からツイート本文を取得する • インデックス完全指定なのでこの処理は早い • ツイート数が極めて多い人は、ノード間でデータが偏り、 処理コストが増大する可能性がある ⇒API利用制限などで対応 • 取得できる件数に制限を設けることで、 Aへのリクエスト回数の最大を制御できる
  36. 36. フォロー時 • フォロー相手のB(フォロイー)に自分を追加する • フォロー相手のA(ツイート)から新しい順に取得し、 C(タイムライン)に追加していく • タイムラインを取得できる件数や期間に制限があれば、 期間分だけAから取得すれば良い⇒処理量の最大を制限できる
  37. 37. フォロー解除時 • フォロー解除相手のB(フォロイー)から自分を削除する • C(タイムライン)から解除相手のツイートを削除していく • タイムラインを取得できる件数や期間に制限があれば、 期間分だけAから取得すれば良い⇒処理量の最大を制限できる
  38. 38. ツイート削除時 • ツイートのユーザIDとタイムスタンプを指定して削除 • A(ツイート)の削除フラグを立てる
  39. 39. キャッシュ戦略 • Aへのリクエストがまずボトルネックになるのでキャッシュを併用 • ツイート本文は書き換わらない • 削除フラグに関しては、「消える」までの遅延を許容する必要がある
  40. 40. ふりかえり • 今日やったことを「次」につなげる • 今日やったこと • わかったこと、印象に残ったこと • 次にやってみたいと思ったこと • スプレッドシートに書いていってください。 • 書くことで自分へのおさらい

×