Slide 1

Slide 1 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. © 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 失敗知識から学ぶ︕ クラウドアプリ設計で避けるべき 事例とその対策 藤原 吉規 A - 5 シニア ソリューションアーキテクト アマゾン ウェブ サービス ジャパン 合同会社

Slide 2

Slide 2 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. シニア ソリューションアーキテクト アマゾン ウェブ サービス ジャパン ⼤阪 好きな AWS サービス: • AWS 技術サポート 藤原 吉規 2001 年から Web マルチテナント SaaS に取り組んできた “firefighter” 🧑🚒

Slide 3

Slide 3 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. Ұ൪ॏཁͰҰ൪΍͔͍ͬͳεΩϧ͸γεςϜΛઃܭ͢ΔͨΊͷ൑அྗͩɻ ݶΓͳ͘γϯϓϧͳσβΠϯͱ͍͏ͷ͸ͳ͔ͳ͔ڭ͑ΒΕΔ΋ͷͰ͸ͳ ͘ɺେํܦݧΛॏͶ֮ͯ͑Δ΋ͷͩɻ ͜ͷʮ൑அྗʯ͸ɺϓϩάϥϚʔʹͱͬͯඇৗʹॏཁͳͷ͕ͩɺͦ͏؆୯ ʹڭ͑ΒΕΔ΋ͷͰ΋ͳ͍ɻ΅͕͘஌ΔݶΓɺ൑அྗΛ͚ͭΔ Ұ൪ͷํ๏͸ɺࣗ෼Ͱઃܭͨ͠γεςϜΛ௕͍ؒϝϯς͢Δ ͜ͱͩͱࢥ͏ IUUQTLOPIKQBOTXFSTEDB Evan Priestley 質とスピード(2022春版、質疑応答⽤資料付き) / Quality and Speed 2022 Spring Edition: P99

Slide 4

Slide 4 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. セッション対象者とゴール 想定視聴者 • 各種データベースやストレージを利⽤してクラウド上に Web アプリを設計・開発す る、サーバーサイド/バックエンド開発エンジニア、テックリード、アーキテクトの⽅ • クラウド上の Web アプリの安定性・コストに課題感をお持ちの⽅ ゴール • クラウド上の Web アプリ設計時のアーキテクチャ選択がネットワークおよび ストレージ I/O 最適化余地を決定し、⾮機能要件である安定性・コストへより 直接的に影響することを理解する • 過去に選択した設計アーキテクチャのトレードオフが後に顕在化する可能性を 理解する

Slide 5

Slide 5 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. アジェンダ • はじめに • 失敗知識事例 1. 100 万の Database Table 🔥 2. 毎⽉ 11 億の Amazon S3 PUT, COPY, POST, LIST リクエスト 🔥 • まとめ

Slide 6

Slide 6 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. はじめに あくまでも、よくあるケース (仮想ストーリー) です 💭 • 私⾃⾝の過去の AWS 上での Web アプリ設計・開発・運⽤経験や、 過去の技術⽀援で発⽣した複数の事例を組合せています • 開発や QA、スモールスタートローンチ時のユーザーやデータが 限られている時は課題になりませんが、成⻑期に⾮機能要件の 安定性・コストが課題となるケースを紹介します

Slide 7

Slide 7 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. © 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 失敗知識事例 1: 100 万の Database Table 🔥

Slide 8

Slide 8 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 新規の業務系 SaaS をローンチ 🚀 してから 3 年後のとある⽇。。。

Slide 9

Slide 9 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 我が社の SaaS テナント契約が 1万社を 達成しました 👏

Slide 10

Slide 10 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. しかし、良いことばかりではなく 😢 業務開始時間ピークの朝 9 時ごろに 頻繁にエラーになったり、レスポンスが遅いと エンドユーザーからクレームが⼊るように 😱

Slide 11

Slide 11 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 業務系 SaaS AWS アーキテクチャ例 アベイラビリティゾーン C アベイラビリティゾーン B アベイラビリティゾーン A Cluster Volume Database 100 Table ... Application load balancer Data Copies APP Amazon Aurora MySQL writer クライアント

Slide 12

Slide 12 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 環境と発⽣していた事象を整理 環境 • アプリサーバーは Python, Ruby, PHP などの軽量プログラミング⾔語と OSS Web フレームワーク • DB は Amazon Aurora MySQL、1 万テナントを単⼀の Aurora クラスターに収容 Amazon CloudWatch メトリクス • テナント契約増加に合わせてスケールアップを続けてきたが、アプリサーバー Amazon EC2 インスタンスと Aurora インスタンスの両⽅の CPU 使⽤率: CPUUtilization が常に⾼い傾向 • Aurora の DB接続数: DatabaseConnections 、接続試⾏回数: ConnectionAttempts が常に増減しており、特にピーク時間帯にスパイクする

Slide 13

Slide 13 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. クエリチューニングでは根本解決しない 🤔 MySQL クエリの改善内容 • Index 付与 • スロークエリ改修 • N+1 問題によるクエリ実⾏回数 • パーティショニング • 更新ロック • MySQL のパラメータ変更

Slide 14

Slide 14 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. CPU 使⽤率⾼ / DB 接続数, 接続試⾏回数スパイク アベイラビリティゾーン C アベイラビリティゾーン B アベイラビリティゾーン A Cluster Volume Database 100 Table ... Application load balancer Data Copies APP Amazon Aurora MySQL writer クライアント アプリサーバー CPU 使⽤率 ⾼ ピーク時 DB 接続数 接続試⾏回数 のスパイク Aurora インスタンス CPU 使⽤率 ⾼

Slide 15

Slide 15 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. ソリューションアーキテクト SA に技術⽀援のご相談をいただく 🧑🚒

Slide 16

Slide 16 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. SA からテックリードの⽅にヒアリング 👂 環境と発⽣していた事象 • 前述の通り エンドユーザーへの影響以外に困っていることはありますか︖ • クエリチューニングのために Table へカラム追加や Index 付与したのですが、 テナント契約が増えた結果、 Web フレームワーク経由のスキーママイグレーション にとても時間がかかるようになりました。1⽇以上かかることもあります。 Table 数は 100 個ありますが、テナント毎のレコード数は多くても数⼗万程度です。 機能追加にも影響出ています。 • テナント契約増加にあわせてスケールアップしたため、 EC2 インスタンスと Aurora インスタンスのコストも課題なのですが、Aurora ストレージ I/O のコスト⽐率 が⼤きくなっていて、削減を検討したいです。

Slide 17

Slide 17 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. SA からの質問 Web フレームワークで DB コネクションプーリングは有効にしていま すか︖ • リクエスト毎に都度 DB コネクション処理を⾏うと EC2 インスタンスと Aurora インスタンスの両⽅の CPU 使⽤率が⾼くなりやすいです。 • DB コネクション処理は、Aurora エンドポイントの名前解決と TCP ハンドシェイクが⾏われるためです。 テックリードの⽅のご⾒解 • いいえ。DB コネクションプーリングは有効にできないので無効にしています。1万 のテナント毎に database を作成しているので、リクエスト毎に都度異なる database に接続されるためです。

Slide 18

Slide 18 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 1 万 テナント Database x 100 Table 100 万の Database Table 🔥

Slide 19

Slide 19 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 100 万の Database Table, リクエスト毎 DB 接続 Aurora ストレージ I/O のコスト⽐率⾼ アベイラビリティゾーン C アベイラビリティゾーン B アベイラビリティゾーン A Cluster Volume テナント毎 DB 100 Table ... Application load balancer Data Copies APP Amazon Aurora MySQL writer 100 x 10,000 テナント = 1,000,000 Tables ... クライアント 💸💸💸 Aurora ストレージ I/O のコスト⽐率⾼ リクエスト毎の DB 接続 Aurora エンドポイント名前解決 TCP ハンドシェイク

Slide 20

Slide 20 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. テナント毎に Database Table を作成した理由 は、3 年前のアプリ設計時に遡ります 🕐

Slide 21

Slide 21 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. テナント毎に Database Table を作成した理由 市場投⼊までの時間を短縮したい • 個社向けに提供していた既存の Web アプリを SaaS にして新規ビジネスを早急に ⽴ち上げたい︕アプリ改修を避けるために、テナント毎に database を作成しよう︕ • テナント毎に database を作成する OSS Web フレームワークのマルチテナント 対応プラグインを活⽤しよう︕ 運⽤・セキュリティ・データアクセスレイヤー作り込みの懸念 • database をテナント毎に分ければ、解約時の削除が簡単 • セキュリティ厳格化でテナントごとに DB 接続ユーザーと database を分けたい • シャード Database Table に複数テナントのデータを⼊れると、アプリ側でテナント 分離アクセス制御の作り込みが必要になってしまうが、ノウハウがない

Slide 22

Slide 22 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 時間がかかる”より良いアプローチ”を使⽤する 代わりに、今すぐ簡単で限定的な解決策を選択 することが、設計判断時点ではビジネス上必要 であった可能性も 🤝

Slide 23

Slide 23 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 設計判断のトレードオフを評価可能なメトリクス を定義・計測し、運⽤開始後に⾒直しできるよう にすることが最も重要 🔎 mysql> select count(*) from information_schema.tables where TABLE_SCHEMA like ‘tenant%'; +----------+ | count(*) | +----------+ | 1000000 | +----------+

Slide 24

Slide 24 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 定常状態 リソース (ファイルシステム内のログファイルであれ、 データベース内の⾏であ れ、メモリ内のキャッシュであれ)を蓄積するメカニズムは、 ⾼校の微積分に出 てくるバケツに似ている。 バケツにデータを蓄積していくと、⼀定の速度で満た されていく。 同じ速度かそれ以上で排出しなければ、いずれ溢れてしまう。 バケ ツが溢れたら⼤変だ。 サーバがダウンしたり、 データベースが遅くなったりエ ラーを投げたり、 レスポンス時間が天⽂学的に膨れ上がったりする。 リソース を蓄積するあらゆるメカニズムでは、そのリソースをリサイ クルする何らかのメカニズムがほかに存在しなければならな い。 これが 「定常状態」 パターンの考え⽅だ。 Release It︕ 本番⽤ソフトウェア製品の設計とデプロイのために (p. 107) Michael T. Nygard 著、でびあんぐる 監訳

Slide 25

Slide 25 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 対策1: Aurora ストレージ I/O コスト 🧯

Slide 26

Slide 26 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. MySQL の使⽤のベストプラクティス テーブル数合計は 1 万未満に 多数のテーブル (1 万以上) のためにパフォーマンスの低下がある場合、それは MySQL がストレー ジファイルのオープンとクローズを含む作業を⾏うことによって引き起こされるものです。この問題 に対処するには、table_open_cache および table_definition_cache パラメータのサイズを⼤きく します。ただし、これらのパラメータの値を⼤きくすると、MySQL が使⽤するメモリの量が⼤幅に 増加し、使⽤可能なメモリがすべて使⽤される場合もあります。詳細については、MySQL ドキュメ ントの「MySQL でのテーブルのオープンとクローズの⽅法」を参照してください。 さらに、テーブルが多すぎると、MySQL のスタートアップ時間に⼤きな影響を与える可能性があり ます。特に MySQL 8.0 より前のバージョンでは、クリーンシャットダウンと再起動およびクラッ シュ復旧の両⽅が影響を受ける可能性があります。 DB インスタンス内のすべてのデータベースで、テーブル数合計を 1 万 未満にすることをお勧めします。MySQL データベース内で多数のテーブルを使⽤する ユースケースについては、「MySQL 8.0 の 100 万テーブル」を参照してください。 Amazon RDS のベストプラクティス - MySQL の使⽤のベストプラクティス – テーブルの数

Slide 27

Slide 27 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 単⼀インスタンス、シャード Database (プールモデル) でテナント毎のテーブル数増加を 防ぐ ブリッジモデル プールモデル サイロモデル アプリレイヤー Instance database1 database2 database database Instance Instance Instance database Tenant 1 84049-49 True Tenant 2 82-84-949 False Tenant 1 Bob Smith Tenant 2 Lisa Johnson テナント毎インスタンス 単⼀インスタンス、 シャード Database 単⼀インスタンス、 テナント毎 Database SaaS Storage Strategies - Building a multitenant storage model on AWS | AWS Whitepaper

Slide 28

Slide 28 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. Aurora の I/O 計画: バッファキャッシュヒット率 は 99.98% 以上を⽬標に バッファプールは、InnoDB がアクセス時にテーブルおよびインデックスデータを キャッシュするメインメモリー内の領域です。 バッファープールを使⽤すると、頻繁に 使⽤されるデータをメモリーから直接処理できるため、処理速度が向上します。 ⼤容量読み取り操作の効率を⾼めるため、バッファプールは複数⾏を保持できるページに分割されま す。 キャッシュ管理を効率化するために、バッファプールはページのリンクリストとして実装され ます。使⽤頻度が低いデータは、LRU アルゴリズムのバリエーションを使⽤して キャッシュから削除されます。 MySQL 8.0 リファレンスマニュアル - バッファプール Amazon Aurora MySQL では 16 KB のページサイズをサポートし、Amazon Aurora PostgreSQL では 8 KB のページサイズをサポートしています。ページサイズは、データベースエン ジンが実⾏する最⼩の I/O 操作です。 99.98% 以上を⽬標に、バッファキャッシュのヒット率: BufferCacheHitRatio を 監視します。 Planning I/O in Amazon Aurora | AWS Database Blog

Slide 29

Slide 29 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. シャード Database Table と テナント毎 Database Table の⽐較 シャード Database Table (プールモデル) • 16KB ページに複数テナントデータが含まれ、バッファプールがより効率的に。 ※データ・アクセス頻度依存 table_a TenantA table_a TenantA TenantB TenantC TenantD table_a TenantB table_a TenantC バッファキャッシュ テナント毎 Database Table LRU でバッファプールから削除 DB TenantA DB TenantB DB TenantC DB TenantD table_a TenantD バッファキャッシュ シャード Database Table DB TenantAll テナント毎 Database Table (ブリッジモデル) • 16KB ページは単⼀テナントデータのみで I/O オーバーヘッドが⼤きい。⾼アクセス頻度ページが LRU でバ ッファプールから削除されやすく I/O 読込が増え、性能維持にはより多くのメモリを持つ インスタンスが必要に。

Slide 30

Slide 30 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. データアクセスレイヤー (DAL) をアプリに実装 • テナント情報からアクセス先 DB のルーティング の実施や、テナントレベルのセキュリティ担保、 コネクションプーリングの管理などを実施する • 例)通常はプールモデル、特定テナントだけサイ ロモデルとしている Hybrid な場合では、テナン トのパーティショニングモデル毎にアクセス⽅法 の変更が必要になるため、DAL で抽象化出来る ことが望ましい § プールモデル︓インスタンスへの接続と⾏レベルの アクセス制御 § サイロモデル︓インスタンスへの接続の実施 SaaS Storage Strategies - Building a multitenant storage model on AWS | AWS Whitepaper

Slide 31

Slide 31 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 初期設計時に PostgreSQL ⾏レベルセキュリティ (RLS) を候補に⼊れる instance database schema tenant_id user_id username tenant1 1 Suzuki tenant1 2 Sato tenant2 1 Nakamura tenant2 2 Takahashi tenant3 1 Yamada user_id username user_id username 1 Yamada user_id username 1 Suzuki 2 Sato -- Tenant1 SET app.current_tenant = ‘tenant1’; SELECT user_id,username FROM users WHERE tenant_id = ‘tenant1’; -- Create Table CREATE TABLE users( tenant_id VARCHAR(20), user_id INT, username VARCHAR(20), PRIMARY KEY(tenant_id,user_id)); -- Insert Data INSERT INTO users VALUES('tenant1',1,'Suzuki’); INSERT INTO users VALUES('tenant1',2,'Sato’); INSERT INTO users VALUES('tenant2',1,'Nakamura’); INSERT INTO users VALUES('tenant2',2,'Takahashi’); INSERT INTO users VALUES('tenant3',1,'Yamada’); -- Create Policy CREATE POLICY tenant_isolation_policy ON users USING (tenant_id = current_setting('app.current_tenant’)::varchar); ALTER TABLE users ENABLE ROW LEVEL SECURITY; Aurora PostgreSQL の RLS 設定 ※ PostgreSQL 9.5 以降 users table PostgreSQL の⾏レベルのセキュリティを備えたマルチテナントデータの分離 -- Tenant2 SET app.current_tenant = ‘tenant2’; SELECT user_id,username FROM users WHERE tenant_id = ‘tenant1’; -- Tenant3 SET app.current_tenant = ‘tenant3’; SELECT user_id,username FROM users; ※プライマリキーには数値シーケンスを使⽤し、 ⼤規模なデータセットのスケーラビリティとパ フォーマンスを向上させることを推奨

Slide 32

Slide 32 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. Amazon Aurora I/O 最適化クラスターで ⼀次対応を検討 特徴 • Aurora I/O 最適化では、読み取りと書き込み I/O オペレーションの料⾦は発⽣しない。デー タベースインスタンスとストレージ使⽤量に対 してのみ課⾦ • Aurora I/O 最適化は、I/O 料⾦が Aurora データベースの総消費量の 25% を超える場合、 I/O 集約型アプリケーションのコストを最⼤ 40% 削減可能 • 既存の Aurora クラスターでは、ストレージ構 成を 30 ⽇に 1 回 Aurora I/O-Optimized に 切り替えたり、いつでも Aurora Standard に 戻すことが可能 注意点 • Aurora MySQL v3.03.1 (MySQL 8.0.26 互 換) 以上か Aurora PostgreSQL v15.2 以上, v14.7以上, v13.10 以上に対応 設定画⾯例 既存クラスターの変更はオンラインで可能 新規 – I/O 集約型のアプリケーションで最⼤ 40% のコスト削減を実現する Amazon Aurora I/O- Optimized クラスター設定

Slide 33

Slide 33 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 対策2: アプリサーバー、リクエスト毎の DB 接続 🧯

Slide 34

Slide 34 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. コネクションプーリング (持続的接続) Python SQLAlchemy のコード例 import sqlalchemy pool = sqlalchemy.create_engine( sqlalchemy.engine.url.URL.create( drivername="mysql+pymysql", username=db_user, password=db_pass, database=db_name, host=db_host, port=db_port, ), pool_size=20, max_overflow=0, pool_timeout=2, pool_recycle=3600, ) コネクション 初期化 リクエスト Thread ⽣成 Transaction … コネクション クローズ ︙ Thread 破棄 レスポンス APP DB コネクション 初期化 リクエスト Thread ⽣成 Transaction … レスポンス APP DB リクエスト Transaction … レスポンス リクエスト Transaction … レスポンス コネクションプーリングなし コネクションプーリングあり DB 接続ユーザー database 毎に コネクションプーリング コネクション初期化時に Aurora エンドポイント名前解決 TCP ハンドシェイクを都度実⾏

Slide 35

Slide 35 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. コネクションプーリングは VPC DNS スロットリング対策に有効 DNS クォータ 各 EC2 インスタンスは、Route 53 Resolver (具体的には 10.0.0.2、169.254.169.253 などの .2 アドレス) にネットワークインターフェイスあたり 1024 パケット/秒でパ ケットを送信できます。このクォータを増やすことはできません。 クォータに達すると、Route 53 Resolver はトラフィックを拒否します。クォータ に達する原因には、DNS スロットリングの問題や、Route 53 Resolver ネットワークイン ターフェイスを使⽤するインスタンスメタデータクエリがあります。VPC DNS スロットリ ングの問題を解決する⽅法については、「VPC DNS スロットリングが、Amazon が提供 している DNS サーバーへのDNS クエリの失敗の原因となっているかどうかを判断する⽅ 法を教えてください。」を参照してください。 Amazon VPC - VPC の DNS 属性 - DNS クォータ

Slide 36

Slide 36 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. Private subnet C Public subnet C Public subnet A Private subnet A すべての接続でコネクションプーリング有効化 を検討 VPC アベイラビリティゾーン A APP クライアント Internet Internet gateway APP SG DB SG Aurora writer ALB SG アベイラビリティゾーン C APP Application load balancer ElastiCache Redis Aurora reader ElastiCache Redis 負荷テスト ツール

Slide 37

Slide 37 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. フェイルオーバー時の再接続を 障害テストで確認 実際のワークロードによる負荷テスト中に障害テスト を実施することで確認 • アプリ側のエラーハンドリング • レスポンス低下時のサービス影響 • データ不整合の有無 Aurora では⼿動フェイルオーバー/障害挿⼊クエリを実⾏ して障害をシミュレーション可能 ex.) ALTER SYSTEM CRASH フェイルオーバー時はコネクションプーリングをアプ リ/ミドルウェアで再接続する仕組みが必要 Amazon Aurora - 障害挿⼊クエリを使⽤した Amazon Aurora MySQL のテスト AWS Fault Injection Simulator FIS とは︖ APP 負荷テスト ツール Application load balancer writer reader write read AWS での分散負荷テスト | 実装 | AWS ソリューション

Slide 38

Slide 38 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 改善後アーキテクチャ アベイラビリティゾーン C アベイラビリティゾーン B アベイラビリティゾーン A Cluster Volume Application load balancer Data Copies APP Amazon Aurora MySQL writer 10,000 テナント = 100 Table クライアント シャード Database Table (プールモデル)による バッファキャッシュ の活⽤ コネクションプーリングの活⽤ tenant_id user_id name TenantA UserA Fujiwara TenantB UserB Hama TenantC UserC Mazda TenantD UserD Honda Database 100 Table ...

Slide 39

Slide 39 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. © 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 失敗知識事例 2: 毎⽉ 11 億の Amazon S3 PUT, COPY, POST, LIST リクエスト 🔥

Slide 40

Slide 40 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. アクセス解析のために クライアントからログ収集する仕組みを追加 ⚙ してから 3 年後のとある⽇。。。

Slide 41

Slide 41 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. アクセス解析対象の DAU (Daily Access User) が 30,000 を超えました👏

Slide 42

Slide 42 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. しかし、良いことばかりではなく 😢 経理の⽅から、 Amazon Simple Storage Service (S3) の ⽉額コストが $ 5,000 を超えていると指摘が 💸💸💸

Slide 43

Slide 43 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. S3 のアクセス解析ログ⽉間処理データ量は 約 400GB なので、ストレージ費⽤は ⼗数ドル程度のはずなのに 🤔

Slide 44

Slide 44 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. EC2 instance EC2 instance EC2 instance ログ収集 AWS アーキテクチャ例 Application load balancer クライアント APP APP プログラム ログオブジェクト S3 バケット EC2 instance ログ集計 BATCH プログラム ログ集計 BATCH Amazon Aurora 集計済 ログデータ 400GB/⽉

Slide 45

Slide 45 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 環境と発⽣していた事象を整理 環境 • アプリ・バッチサーバーは Python, Ruby, PHP などの軽量プログラミング⾔語の OSS Web フレームワーク • クライアントは 30,000、平⽇⽇中に 1分に 1回、ログをアプリサーバーに送信 • 30,000クライアント x 1時間60回 x ⽇中8時間 x 平⽇20⽇間 = 288,000,000/⽉ • バッチ集計サーバーは 5分に 1回、ログを集計して Amazon Aurora に保存 Amazon CloudWatch メトリクス • 該当バケットの S3 リクエストメトリクスを有効にして確認、リクエスト⽐率は PutRequests : GetRequests : DeleteRequests : ListRequests = 1:1:1:3以上 で ListRequests が最も多いが、リクエスト元が不明

Slide 46

Slide 46 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. EC2 instance EC2 instance EC2 instance S3 PUT : GET : DELETE : LIST = 1 : 1 : 1 : 3以上 で LIST が最も多い Application load balancer クライアント APP APP プログラム ログオブジェクト S3 バケット EC2 instance ログ集計 BATCH プログラム ログ集計 BATCH Amazon Aurora 集計済 ログデータ 30,000クライアント x 1時間 60回 x ⽇中 8時間 x 平⽇ 20⽇間 = 288,000,000/⽉ S3 PUT S3 GET S3 DELETE S3 LIST の リクエスト元 が不明 400GB/⽉

Slide 47

Slide 47 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. ソリューションアーキテクト SA に技術⽀援のご相談をいただく 🧑🚒

Slide 48

Slide 48 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. SA からテックリードの⽅にヒアリング 👂 環境と発⽣していた事象 • 前述の通り S3 PUT 時に複数リクエストのログを集約していますか︖ • いいえ。リクエスト毎に JSON Log を 都度 S3 PUT しています。リクエスト あたり最⼤ 1.5KB と⼩容量だからです。 アプリ・バッチサーバーは S3 バケットへのログ保存・取得・削除操作 にプログラミング⾔語⽤の AWS SDK を使⽤していますか︖ • いいえ。アプリ・バッチサーバーに OSS の S3 ファイルシステムをインストール して S3 バケットをマウントしています。プログラミング⾔語からファイルシステム 経由で直接読み書きでき、実装が簡単だからです。

Slide 49

Slide 49 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. EC2 instance EC2 instance EC2 instance OSS の S3 ファイルシステム経由でリクエスト毎に 都度 JSON Log を S3 PUT Application load balancer クライアント APP APP プログラム ログオブジェクト S3 バケット OSS S3 Filesystem /mnt/s3bucket EC2 instance ログ集計 BATCH プログラム OSS S3 Filesystem /mnt/s3bucket ログ集計 BATCH Amazon Aurora 集計済 ログデータ リクエスト毎に JSON Log を 都度 S3 PUT JSON Log 1.5KB per Object OSS の S3 ファイル システム OSS の S3 ファイル システム S3 LIST の リクエスト元 が不明

Slide 50

Slide 50 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. SA からの提案 対象の S3 バケット・オブジェクトの AWS CloudTrail イベントログ 記録を有効化して、S3 LIST のリクエスト元を特定しましょう テックリードの⽅のご⾒解 • CloudTrail イベントログ記録を有効化し、OSS の S3 ファイルシステムの書込、 読込、削除操作毎に S3 LIST リクエストがそれぞれ 1回以上実⾏されているこ とがわかりました。PUT : GET : DELETE : LIST = 1 : 1 : 1 : 3以上の⽐率とも⼀致 しています。ファイルやディレクトリの更新・存在チェックのために実⾏される ように⾒えます。 • 30,000クライアント x 1時間60回 x ⽇中8時間 x 平⽇20⽇間 = 288,000,000/⽉ • JSON Log 1Object 毎に PUT 1回, LIST 3回で合計 4 回 1,152,000,000/⽉となり、 S3 PUT, COPY, POST, LIST リクエストが $ 5,000 のコスト要因でした。

Slide 51

Slide 51 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 毎⽉ 11 億の Amazon S3 PUT, COPY, POST, LIST リクエスト 🔥

Slide 52

Slide 52 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. EC2 instance EC2 instance EC2 instance 毎⽉ 11 億の Amazon S3 PUT, COPY, POST, LIST リクエスト Application load balancer クライアント APP APP プログラム ログオブジェクト S3 バケット OSS S3 Filesystem /mnt/s3bucket EC2 instance ログ集計 BATCH プログラム OSS S3 Filesystem /mnt/s3bucket ログ集計 BATCH Amazon Aurora 集計済 ログデータ JSON Log 1.5KB per Object OSS S3 Filesystem 書込 S3 PUT, S3 LIST OSS S3 Filesystem 削除 S3 DELETE, S3 LIST 30,000クライアント x 1時間 60回 x ⽇中 8時間 x 平⽇ 20⽇間 = 288,000,000/⽉ x PUT 1回, LIST 3回で合計 4回 = 1,152,000,000/⽉ OSS S3 Filesystem 読込 S3 GET, S3 LIST

Slide 53

Slide 53 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. OSS の S3 ファイルシステムを採⽤した理由は、 3 年前のアプリ設計時に遡ります 🕐

Slide 54

Slide 54 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. OSS の S3 ファイルシステムを採⽤した理由 市場投⼊までの時間を短縮したい • オンプレミスで稼働中の既存の Web アプリはストレージに拡張性・耐久性の課題 があるため Amazon S3 を利⽤したい︕アプリの改修を避けるために、OSS の S3 ファイルシステムを利⽤しよう︕ S3 データアクセスの作り込みの懸念 • プログラミング⾔語で S3 データアクセスする作り込みが必要になってしまうが、 AWS SDK の利⽤ノウハウがない︕ OSS の S3 ファイルシステムはプログラミング ⾔語からファイルシステム経由で直接読み書きでき、実装が簡単︕ コスト試算や PoC が不⼗分または実施していなかった • JSON Log はリクエストあたり最⼤ 1.5KB と⼩容量なのでコストは問題ないだろう

Slide 55

Slide 55 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 時間がかかる”より良いアプローチ”を使⽤する 代わりに、今すぐ簡単で限定的な解決策を選択 することが、設計判断時点ではビジネス上必要 であった可能性も 🤝 再掲

Slide 56

Slide 56 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 設計判断のトレードオフを評価可能なメトリクス を定義・計測し、運⽤開始後に⾒直しできるよう にすることが最も重要 🔎 -- Querying CloudTrail logs - Amazon Athena SELECT COUNT(eventname) AS cnt, eventname, useridentity.principalid FROM "cloudtrail_logs_ap_northeast_1_pp" WHERE eventsource = 's3.amazonaws.com' AND requestparameters LIKE ‘%[s3_bucket_name]%' AND useridentity.principalid LIKE '%:i-%' AND timestamp '[yyyy/MM/dd]' GROUP BY eventname,useridentity.principalid ORDER BY cnt DESC 再掲

Slide 57

Slide 57 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 定常状態 リソース (ファイルシステム内のログファイルであれ、 データベース内の⾏であ れ、メモリ内のキャッシュであれ)を蓄積するメカニズムは、 ⾼校の微積分に出 てくるバケツに似ている。 バケツにデータを蓄積していくと、⼀定の速度で満た されていく。 同じ速度かそれ以上で排出しなければ、いずれ溢れてしまう。 バケ ツが溢れたら⼤変だ。 サーバがダウンしたり、 データベースが遅くなったりエ ラーを投げたり、 レスポンス時間が天⽂学的に膨れ上がったりする。 リソース を蓄積するあらゆるメカニズムでは、そのリソースをリサイ クルする何らかのメカニズムがほかに存在しなければならな い。 これが 「定常状態」 パターンの考え⽅だ。 Release It︕ 本番⽤ソフトウェア製品の設計とデプロイのために (p. 107) Michael T. Nygard 著、でびあんぐる 監訳 再掲

Slide 58

Slide 58 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. 対策: 毎⽉ 11 億の Amazon S3 PUT, COPY, POST, LIST リクエスト 🧯

Slide 59

Slide 59 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. Amazon S3 の料⾦ S3 標準ストレージ: リクエストとデータ取り出し ※AWS アジアパシフィック (東京) リージョン • PUT、COPY、POST、LIST リクエスト (1,000 リクエストあたり) $0.0047 • GET、SELECT、他のすべてのリクエスト (1,000 リクエストあたり) $0.00037 S3 PUT/LIST リクエストは GET リクエストに⽐べて、10倍以上⾼額 なため、S3 PUT はバッファリング・バルク処理しつつ、 S3 LIST リクエストを削減できる AWS サービスを併⽤する Amazon S3 の料⾦

Slide 60

Slide 60 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. EC2 instance EC2 instance EC2 instance 改善後アーキテクチャ Application load balancer クライアント APP APP プログラム ログオブジェクト S3 バケット ログ集計 JSON Log < 128MB per Object AWS SDK Amazon Kinesis Data Firehose 30,000クライアント x 1時間 60回 x ⽇中 8時間 x 平⽇ 20⽇間 = 288,000,000/⽉ Amazon Kinesis Data Streams EC2 instance ログ集計 プログラム AWS SDK Amazon Aurora 集計済 ログデータ バッファリング サイズ: 128MB インターバル: 300秒 JSON Log 1.5KB per Object Amazon SQS S3 Event Notifications S3 PUT オブジェクト キー情報を ログ集計で利⽤ アプリ・ログ集計 で AWS SDK を使⽤

Slide 61

Slide 61 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. S3 署名付き URL HTTP POST で画像など⼤容量 ファイルをクライアントから直接アップロード import logging import boto3 def create_presigned_post(bucket_name, object_name, fields=None, conditions=None, expiration=60): # Generate a presigned S3 POST URL s3_client = boto3.client('s3') response = s3_client.generate_presigned_post(bucket_name, object_name, Fields=fields, Conditions=conditions, ExpiresIn=expiration) # The response contains the presigned URL and required fields return response Generating a presigned URL to upload a file – Boto3 Python boto3 のコード例 EC2 instance APP プログラム AWS SDK S3 バケット クライアント Web ブラウザー APP 1. 署名付き URL ⽣成 リクエスト 2. HTTP POST で直接 アップロード response[ʻurlʼ], response[ʻfieldsʼ] に HTTP FORM に必要な URL, FIELD データが含まれるため、 クライアント JavaScript でアップロード可能

Slide 62

Slide 62 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. © 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. まとめ

Slide 63

Slide 63 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. まとめ • クラウド上の Web アプリ設計時のアーキテクチャ選択が ネットワークおよびストレージ I/O 最適化余地を決定し、 ⾮機能要件である安定性・コストへより直接的に影響する • 過去に選択した設計アーキテクチャのトレードオフが後に 顕在化する可能性 • システム設計の判断⼒をつける⼀番の⽅法は、⾃分で設計した システムを⻑い間メンテすること • 失敗知識は貴重です︕ぜひみなさんも社内外で共有しましょう︕

Slide 64

Slide 64 text

© 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved. Thank you! © 2023, Amazon Web Services, Inc. or its affiliates. All rights reserved.