森 俊介 / 黒曜
@kokuyouwind
株式会社Misoca
SRE
アジャイルプラクティス
素早く価値を届けられる
フィードバックを速く得られる
変更粒度が小さくなることで……
コードレビューしやすくなる
コードが衝突しづらくなる
問題の原因特定がしやすくなる
現実にはそう簡単にいかないときもある
プレスリリース合わせで全部出す
ちょっとずつ出すとデータ不整合
一揃いの機能がないとUXが悪い
etc...
機能を動的にOn/Offできる仕組み
ある環境でだけ有効にする
あるユーザにだけ有効にする
管理者が全体の有効/無効を切り替える
etc...
一般ユーザに見せないコードを入れられる
一般公開と別の単位でリリースできる
公開前の機能を本番で試せる
様々な目的に利用できる
カナリヤリリース
A/Bテスト
etc...
FeatureFlagの基本と分類
MisocaでのFeatureFlagの使い方
まとめ
FeatureFlagの基本と分類
MisocaでのFeatureFlagの使い方
まとめ
if feature_enabled?
process_with_feature
else
process_without_feature
end
機能を動的にOn/Offする仕組み
システム全体で共通
デプロイ時
ホットリロード
リクエストごとに判定
特定ユーザにだけ機能を有効化
特定割合のユーザに機能を有効化
特定属性のユーザに機能を有効化
設定管理の方法は色々
環境変数
設定ファイル
KVS
クラウドサービス
etc.
Feature Toggles (aka Feature Flags) / Pete Hodgson https://martinfowler.com/articles/feature-toggles.html
Feature Toggles (aka Feature Flags) / Pete Hodgson https://martinfowler.com/articles/feature-toggles.html
リリース前機能を隠すための分岐
不完全なコードのデプロイ
デプロイとリリースの分離
短期(リリースしたら消される)
静的(環境全体の設定)
Feature Toggles (aka Feature Flags) / Pete Hodgson https://martinfowler.com/articles/feature-toggles.html
実ユーザで機能を実験するための分岐
短期〜中期(実験期間による)
動的(ユーザコホートごとに振り分ける)
Feature Toggles (aka Feature Flags) / Pete Hodgson https://martinfowler.com/articles/feature-toggles.html
性能をコントロールするための分岐
中期〜永続(上記のいずれの目的かによる)
静的(環境全体の設定)
Feature Toggles (aka Feature Flags) / Pete Hodgson https://martinfowler.com/articles/feature-toggles.html
特定のユーザに提供機能を変える分岐
長期〜永続
動的(リクエストごとに振り分ける)
すべてのFeatureFlagを同じ仕組みで管理するのは危険な道
カテゴリごとに異なる設計を要する
同じ方法で管理すると、将来の痛みにつながる
Feature Toggles (aka Feature Flags) / Pete Hodgson https://martinfowler.com/articles/feature-toggles.html
短期的なFeatureFlagでの静的/動的の別はさほど重要ではない
柔軟に管理できたほうが便利
内部ユーザでの動作確認
カナリヤリリース
短いスパンで消えるコードなので管理上のつらさも表面化しない
FeatureFlagの基本と分類
MisocaでのFeatureFlagの使い方
まとめ
Feature Toggles (aka Feature Flags) / Pete Hodgson https://martinfowler.com/articles/feature-toggles.html
主にこのへん
リリーストグル
リリースせず開発期間が長期に渡る機能
時間合わせでのリリースが必要な機能
実験トグル・Opsトグル
パフォーマンス改善
(A/Bテスト、カナリヤテストを兼ねる)
LaunchDarklyを検討したが見送り
Redisをバックエンドに自作
# initialize
Misoca.feature_flag = Misoca::FeatureFlag.new
Misoca.feature_flag.add_target(
:new_feature,
'なんかすごい新機能'
)
# use
if Misoca.feature_flag.enabled?(:new_feature, current_user)
Misoca::UseCase::NewFeature.new.call
else
Misoca::UseCase::CurrentFeature.new.call
end
class Misoca::FeatureFlag::Target
def enable_for_user(user)
redis.sadd(user_key, user.id)
end
end
Misoca.feature_flag.enable_for_user(user)
feature_flag:new_feature:users
(有効化したユーザidの集合)
42
123456
114514
user id: 123456
redis.sadd
123456
feature_flag:new_feature:segments
(有効化したユーザid下2桁の集合)
00
12
33
redis.sadd 04 87
04
87
例: 有効化率を3% から 5% に
元々含まれない
2桁の数を2つ選ぶ
(3%から5%なので+2)
04
87
class Misoca::FeatureFlag::Target
def enable_percentage(percent)
current_segments = redis.smembers(segment_key)
unused_segments = ALL_SEGMENTS - current_segments
diff_percent = percent - current_segments.count
diff_percent.positive?
? redis.sadd(segment_key,
unused_segments.sample(diff_percent))
: redis.spop(segment_key, diff_percent.abs)
end
end
Misoca.feature_flag.enable_percentage(50)
有効化したユーザidの集合
42
123456
114514
user id: 123456
redis.sismember 123456
有効化したユーザid下2桁の集合
00
12
33
redis.sismember 56
04
87
内部ユーザ向けページから有効状況を見れる
フラグの切り替え
内部ユーザ向けページ(自分のみ)
Thorタスク実行(比率指定)
軽減税率対応
電卓機能
PDFのS3キャッシュ
スモールリリースの難しい機能
リリーストグルを使用
ヘルプ更新のため、時間合わせリリース
リリーストグルを使用
事前に内部ユーザで動作確認
デプロイせず設定変更のみでリリース
デプロイ絡みでのトラブルの心配がない
PDF生成が重いため、S3に2次キャッシュ
どの程度改善するか見積りづらい
S3へのwrite処理が増える
S3 Readの重さによっては改善しない可能性も
10%のユーザにリリース→APMで効果測定
PDF Render: 800ms
S3 PUT: 94ms
S3 GET(miss): 40ms
S3 GET(hit): 72ms
生成時に+134ms,
読み込み時に728ms改善
いける!
富山県 30代会社員
H.Mさん
デプロイとリリースが競合しないので
予想外のトラブルを避けられますし、
ロールバックも本当に簡単でした。
分岐処理を後から徐々に外せるのも良いですね。
不満は一切ないです。
FeatureFlag最高!
※効果には個人差があります
汎用のフラグを使わない
リリースしたらきちんとフラグを消す
うっかりすると無限にフラグが増える
うっかりするとリリース前に巻き戻る
パフォーマンス影響をチェックする
FeatureFlagの基本と分類
MisocaでのFeatureFlagの使い方
まとめ
大きいリリースはFeatureFlagを使って
小分けにデプロイすると便利
小さいものでもFeatureFlagを使うと
デプロイせずにリリースできて便利
簡単にフラグを足せる/消せる仕組みを
整備するのが必要