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
19
7k
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
1.8k
Proxy-Status & Cache-Status
shqld
0
510
High Performance JavaScript / jsconfjp2019
shqld
0
500
ServiceWorkerの開発 / ServiceWorker Development
shqld
2
640
Loading Performanceとの向き合い方 / InsideFrontend 2019
shqld
9
2.1k
日経電子版とPWAのこれから / PWANight vol.2
shqld
2
4.7k
日経電子版のマイクロフロントエンドとPWA / devsum2019
shqld
8
12k
Other Decks in Technology
See All in Technology
Application Development WG Intro at AppDeveloperCon
salaboy
0
190
10XにおけるData Contractの導入について: Data Contract事例共有会
10xinc
6
660
Adopting Jetpack Compose in Your Existing Project - GDG DevFest Bangkok 2024
akexorcist
0
110
障害対応指揮の意思決定と情報共有における価値観 / Waroom Meetup #2
arthur1
5
480
心が動くエンジニアリング ── 私が夢中になる理由
16bitidol
0
100
エンジニア人生の拡張性を高める 「探索型キャリア設計」の提案
tenshoku_draft
1
130
生成AIが変えるデータ分析の全体像
ishikawa_satoru
0
170
Amplify Gen2 Deep Dive / バックエンドの型をいかにしてフロントエンドへ伝えるか #TSKaigi #TSKaigiKansai #AWSAmplifyJP
tacck
PRO
0
390
CysharpのOSS群から見るModern C#の現在地
neuecc
2
3.5k
Zennのパフォーマンスモニタリングでやっていること
ryosukeigarashi
0
150
安心してください、日本語使えますよ―Ubuntu日本語Remix提供休止に寄せて― 2024-11-17
nobutomurata
1
1k
日経電子版のStoreKit2フルリニューアル
shimastripe
1
140
Featured
See All Featured
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
6
420
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
506
140k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
Building an army of robots
kneath
302
43k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
27
840
jQuery: Nuts, Bolts and Bling
dougneiner
61
7.5k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
4
370
The Pragmatic Product Professional
lauravandoore
31
6.3k
How GitHub (no longer) Works
holman
310
140k
[RailsConf 2023] Rails as a piece of cake
palkan
52
4.9k
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