Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
FastlyとTypeScriptで実現するカナリアリリース / yamagoya2020
Search
Sho Miyamoto
November 25, 2020
Technology
20
7.3k
FastlyとTypeScriptで実現するカナリアリリース / yamagoya2020
#yamagoya2020 で 2020/11/25 に登壇させていただいたセッションの資料です。
Sho Miyamoto
November 25, 2020
Tweet
Share
More Decks by Sho Miyamoto
See All by Sho Miyamoto
JavaScriptエンジンから見るランタイム / 2024-04-25
shqld
12
2.1k
Proxy-Status & Cache-Status
shqld
0
610
High Performance JavaScript / jsconfjp2019
shqld
0
590
ServiceWorkerの開発 / ServiceWorker Development
shqld
2
740
Loading Performanceとの向き合い方 / InsideFrontend 2019
shqld
8
2.3k
日経電子版とPWAのこれから / PWANight vol.2
shqld
2
5k
日経電子版のマイクロフロントエンドとPWA / devsum2019
shqld
7
13k
Other Decks in Technology
See All in Technology
[CV勉強会@関東 ICCV2025] WoTE: End-to-End Driving with Online Trajectory Evaluation via BEV World Model
shinkyoto
0
320
組織の“見えない壁”を越えよ!エンタープライズシフトに必須な3つのPMの「在り方」変革 #pmconf2025
masakazu178
1
650
2025年 面白の現在地 / Where Omoshiro Stands Today: 2025
acidlemon
0
140
不確実性に備える ABEMA の信頼性設計とオブザーバビリティ基盤
nagapad
4
5.4k
メッセージ駆動が可能にする結合の最適化
j5ik2o
8
1.1k
生成AI時代に若手エンジニアが最初に覚えるべき内容と、その学習法
starfish719
2
570
AWS re:Invent 2025 で頻出の 生成 AI サービスをおさらい
komakichi
2
180
TypeScript 6.0で非推奨化されるオプションたち
uhyo
13
4.2k
re:Invent2025 事前勉強会 歴史と愉しみ方10分LT編
toshi_atsumi
0
240
How We Built a Secure Sandbox Platform for AI
flatt_security
1
110
AI × クラウドで シイタケの収穫時期を判定してみた
lamaglama39
1
380
単一Kubernetesクラスタで実現する AI/ML 向けクラウドサービス
pfn
PRO
1
340
Featured
See All Featured
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.8k
GraphQLとの向き合い方2022年版
quramy
49
14k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.5k
The Pragmatic Product Professional
lauravandoore
36
7k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
51k
Rebuilding a faster, lazier Slack
samanthasiow
84
9.3k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Bash Introduction
62gerente
615
210k
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
340
A Tale of Four Properties
chriscoyier
162
23k
Side Projects
sachag
455
43k
Building Applications with DynamoDB
mza
96
6.8k
Transcript
FastlyとTypeScriptで 実現する カナリアリリースと A / Bテスト Sho Miyamoto (日本経済新聞社)
- 名前 Sho Miyamoto - 所属 日本経済新聞社 - 領域 -
web - front-end - {client,server,edge}-side - GitHub https://github.com/shqld 自己紹介 2
⚠ 今日の発表では実装の詳細に (なるべく)深入りしないようにします 3 代わりに、発表後に公開されるこの資料をご覧いただけると嬉しいです
(ダーク)カナリアリリースを ご存知でしょうか? 4
カナリアリリース 5 - 一部のユーザだけに新機 能を見せる - ランダムに絞ることが多い - 問題がなければ、その後 100%のユーザに展開
- 開発者・社内のユーザな ど、特定の条件に合う ユーザだけに新機能を見 せる - 本番環境での確認やQA を通した上でユーザへ展 開 ダークカナリアリリース
6
- 絞った数のユーザだけで、画面やシステムへの影響度を見ることができる - 問題があったときに全体に波及させない - ダークカナリアリリースの場合、そもそもユーザには見えないのでより安全 - 公開前の機能・ページを予め本番に出しておいて社内で確認、指定日時に自動リ リース、ということも可能 カナリアリリースの利点
7
A / B テスト 8 - いわずとしれた 分析手法
Feature Toggles で 実現できる 9
Feature Toggles 10
Feature Toggles 11 https://laptrinhx.com/1-minute-feature-toggle-1686812105/ - 機能のオンオフ状態を示す - イメージはスイッチボタン
- 実際にコード内で行っているのは分 岐を作ることだけ - コードを書き換えるのではなく、分 岐させる - 分岐先はランタイムで判定 Feature Toggles
12
Feature Toggles - ここに全てが記されている - Feature Toggles (aka Feature Flags)
by Martin Fowler 13
14 ポイント リリースとデプロイの タイミングをずらす → ユーザからの見え方や挙動を より柔軟にコントロールできる
- 機能リリースが安全になる - 一度本番で確認してから全体へリリー ス、ということができる - QAテストが容易になる - 他部署・非エンジニアでも、スイッチを 切り替えるだけで検証できる
15 Feature Toggles の利点 - 非常時の対応が素早い - 何かあればスイッチを切り戻すだけで デプロイせずに対応できる - 非機能要件の検証がしやすい - パフォーマンス施策の効果検証など
16 問題があったときに、 いかに素早く切り戻せるかも重要 Toggle経由ならデプロイも待たずに即反映できる
電子版と Feature Toggles 17
- 新しい機能やページは基本的に ダークカナリアリリース - 実際に開発者が本番で確認してから 全てのユーザに展開 - 指定の日時に自動リリース - e.g.
大統領選の始まる時間に合わせ て特設ページをリリース 18 Feature Toggles の用途 - マーケティング施策のA/Bテストを 行う - e.g. ペイウォール(有料登録動線)の 文言変更 - 技術的な施策の効果検証を行う - e.g. Dynamic Critical CSSを本番に反 映しても問題ないか検証、確認が取れ るまでは反映しない
- JSONで管理 - defaultValue を決めて おく - A / B
テストを行うときは candidates を定義 実際の Toggle 定義 19
- 基本的に boolean なの で、ただの分岐として書く だけ ダーク カナリアリリース 20
- カナリアリリースのときと 特に変わらない - この例ではコンポーネント ごと出し分けている - これらのTogglesは全て 計測システムに送ってい るので、この機能を見た
ユーザを判別できる A / B テスト 21
22 社内の非開発者でも簡単に オンオフできるUIもある
Feature Toggles の 実装 23
Default / Static - 既定値 - Toggle の定義時に人間が決定 - リリース用
- 例 - 「このToggleはもうリリースできるのでオン」 Override / Dynamic - 上書き値 - 定義された条件から機械的に決定 - スケジュール用、セグメンテーション用 - 例 - 「11/25になったからオン」 - 「このユーザのセグメントが10%内だからオ ン」 24 Toggle の2つの側面
25 Toggle の2つの側面
26 Feature Toggles の材料
基盤の構成 27
- dynamic toggles の計算のため に別のサーバを必要としている - 運用・ケアが必要 - Toggles サーバにリクエストする
ために VCL内で restart している - restart - static toggles の同期のために サービス側で5分おきにAPIへ ポーリングしている - メモリに暗黙的な状態が存 在する 28
- HTTPヘッダに Toggles を詰めて オリジンへリクエスト - キャッシュが混らないように`Vary` ヘッダを付けてレスポンス メッセージの やりとり
29
旧基盤 (Nikkei-Flags) についての詳しい解説はFastlyの記事で How to solve anything in VCL, part
3: authentication and feature flags at the edge https://www.fastly.com/blog/how-solve-anything-vcl-part-3-authentication-and- feature-flags-edge 30
Feature Toggles システムの リプレース 31
リプレースの要件・ゴール (1) 32 - インフラ - 状態や計算も全てVCLで完結 - 完全サーバーレス -
転送量 - 各リクエスト毎に送られるデータはなるべく小さく - できるものは全て静的に解決しておく - 複雑性 - 暗黙的・非透過的な状態はなるべく排除 - 「いま何がメモリにあって何がどうなっているのか」という懸念がない
- 運用性 - 更新反映が速い - 終了した・不要な toggle の分岐がコードに残らない - Toggleの定義
- 定義が簡潔 - 個々の存在目的が明確 リプレースの要件・ゴール (2) 33
34 まずToggleの概念を再考した
35 https://martinfowler.com/articles/feature-toggles.html
- Toggleの種類は4つ - Release: (ダーク)カナリーリリース - Experiment: ダークローンチやA/Bテスト - Ops:
状況に応じてインフラなどを切り替える - Permission 権限別に処理をスイッチ - → 本当に必要なのは Release と Experiment - それ以外はどちらも Longevity(寿命)が長く消しづらい - Opsはユースケースが限定的 で頻度が少ない - Permissionはアプリケーションの一部として 依存されてしまう可能性が高い Toggle 再考 36
- 存在意義・目的が明確 - ある機能をスイッチ(オン /オフ)するだけ - → 値は True /
False の2値のみ - 1つのToggleに複数の用途を持たせない - 寿命が短く疎結合 - 短い役目を終えたら すぐに消せる - コードから剥がしやすい - 存在が透過的 - Toggleの存在を前提としない - Toggleにアプリケーションの 実装が依存しない あるべき理想のToggle 37
38 色々な議論・紆余曲折あったが... 最終的にできたもの (設計に半年以上かかった)
39 Feature Toggles の材料
新基盤の構成 40
- エッジで dynamic toggles の計 算を行う - サーバレス、VCLで完結 - restart
/ polling も消えた - 最初から bereq に toggles が入っている - 各bereqごとに CDN へリクエスト して static toggles を取得 - 常に最新の toggles を同 期できる - 暗黙的な状態を持たない 41
- 誰にでも書ける簡単・簡潔な インターフェース - 名前と概要、各タイプのオプション を記述 - JSONとは異なり、オプションの チェックや補完が効く トグルの定義
42
- Fastify の `req` オブジェクトに APIを生やす - TypeScriptで実装 - できるだけ型で縛れるように型推
論多め - 返る値は必ずBoolean アプリケーション コード 43 (文字列の位置が下がっているのはVSCodeのプラグインの関係)
デプロイフロー - Toggles を別のリポジトリの切り 出した - npmの`prepublishOnly` フックでデプロイが実行さ れる -
npm publishとVCLのdeployが終 わったあとに Fastly API でソフト パージ - toggles 周りのVCLは VCL Snippets として作っており、本体 のVCLとは別軸・別レポでデプロ イが可能 44
45 VCL Snippets - メインとなるCustom VCLと は別サイクルで更新ができ る - サブルーチン単位でデプロ
イ可能 - https://docs.fastly.com/en/g uides/using-dynamic-vcl-sn ippets
46 実装上の各ポイント
✏ Toggles API の処理を VCLで実装 47
- JSで定義されたToggleを読んで、 dynamic toggles 用のVCLを生 成している - Scheduling - リクエストされた時間と定
義ルールの時間を比較し てオンオフを決める - Segmentation - 何かしらのリクエストIDを 使いユーザのセグメントを 決定し定義ルールの範囲 と比較してオンオフを決め る 48
- 上の定義から、下の dynamic toggles 用の条件分岐を生成し ている - セグメンテーションで同じユーザが 複数の Toggle
で似たような判定 にならないように、条件範囲に random offset を含めている 49
50 ✏ 転送量を抑えた
51 Toggleの数や名前によって数が重くなる
52 長いキーを4 bytesのハッシュに変換
53 ハッシュをToggle定義とマッピング
54 リクエストごとに発生するこの部分を減らしたい
55 先頭にversionをつけ、toggle コンテンツのversioningをする
56 versioningされていることで、static toggles のメモ化ができる
57 ✏ TypeScriptで Toggle の取り扱いを安全に
58 型で toggle の名前を補完
59 消した toggle が使われていたら型エラー
60 ‘ xxx‘ で検索できる - 抽象化されているとtoggle がどこで使われているか追 えなくなる - toggle
のキーは必ず ‘ ‘ で始まるように強制(それ以 外を弾いている) - string literal タイプなので キーを抽象化できない - ✖ get(‘ ‘ + name)
- toggle を生成する関数を経由 - ここで name を string literal タイ
プで受け取る - string literal の name を返す Toggle オブジェクトの型引数に 渡して保持 型の推論 61
- 集めた toggles を Object.freeze で readonly に - typeof
で型に変えた toggles の name を ユニオンとして取り出す 型の推論 (2) 62
まとめ
- (ダーク)カナリアリリースは便利 - リリースの安全性が高まる - Feature Toggles で実現できることが多い - デプロイとリリースのタイミングをずらすことで色々できる
- 電子版では Feature Toggles を(結構)活用している - ダークカナリアリリース、スケジューリング、 A/Bテスト、... まとめ 64
まとめ (2) - Feature Toggles の運用を見返してシンプルに - 何でもできてしまう toggles は禁止、制約を強めに
- VCLを駆使すれば 外部のサーバは必要ない - VCL Snippets でデプロイフローも簡潔に - TypeScript でアプリケーションコードを安全に - 補完や検索、エラー検知も容易に 65
ありがとうございました 66
余談: restart_and_you_will_be_fired
VCL restart; 68
- 人類にはまだ早い - 使わずに済むなら使わない方が良い - これを消したかった、というのも今回のリプレースの動機の大きな一つ - 中々解決できない問題は大体 restart 起因であることが多い(個人の経験上)
- 様々なパターンを網羅的に知っておかないと思わぬ事故に繋がってしまう - 一度目のリクエストで( restartまでに)何が行われたのか - どんなHTTP ヘッダが付いてどう影響するのか - 次のリクエストでどうなるか ...etc. - もちろん必要なとき、有用なときはある - e.g. フレンドリーなエラーページに差し替えるとき VCL restart; 69