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
元旅行会社の情シス部員が教えるおすすめなre:Inventへの行き方 / What is the most efficient way to re:Invent
naospon
2
330
Terraform未経験の御様に対してどの ように導⼊を進めていったか
tkikuchi
2
430
ドメイン名の終活について - JPAAWG 7th -
mikit
33
20k
Lambdaと地方とコミュニティ
miu_crescent
2
370
データプロダクトの定義からはじめる、データコントラクト駆動なデータ基盤
chanyou0311
2
280
TypeScriptの次なる大進化なるか!? 条件型を返り値とする関数の型推論
uhyo
2
1.6k
The Role of Developer Relations in AI Product Success.
giftojabu1
0
120
Exadata Database Service on Dedicated Infrastructure(ExaDB-D) UI スクリーン・キャプチャ集
oracle4engineer
PRO
2
3.2k
【若手エンジニア応援LT会】ソフトウェアを学んできた私がインフラエンジニアを目指した理由
kazushi_ohata
0
150
インフラとバックエンドとフロントエンドをくまなく調べて遅いアプリを早くした件
tubone24
1
430
OCI Security サービス 概要
oracle4engineer
PRO
0
6.5k
Incident Response Practices: Waroom's Features and Future Challenges
rrreeeyyy
0
160
Featured
See All Featured
Designing Experiences People Love
moore
138
23k
Building a Modern Day E-commerce SEO Strategy
aleyda
38
6.9k
BBQ
matthewcrist
85
9.3k
Product Roadmaps are Hard
iamctodd
PRO
49
11k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
246
1.3M
What's new in Ruby 2.0
geeforr
343
31k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.1k
Adopting Sorbet at Scale
ufuk
73
9.1k
Speed Design
sergeychernyshev
24
610
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
6
410
GraphQLの誤解/rethinking-graphql
sonatard
67
10k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
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