Springの機能フラグ
1概要
この記事では、機能フラグを簡単に定義し、それらをSpring Bootアプリケーションに実装するための、慎重で実用的なアプローチを提案します。それから、さまざまなSpring Boot機能を利用して、より洗練された反復処理について詳しく説明します。
機能のフラグ付けが必要となる可能性があるさまざまなシナリオについて説明し、可能な解決策について説明します。これは、Bitcoin Minerサンプルアプリケーションを使用して行います。
2機能フラグ
-
機能フラグ – 機能トグルとも呼ばれます – コードを変更したり、理想的にはアプリケーションを再デプロイしたりすることなく、アプリケーションの特定の機能を有効または無効にできるメカニズムです。
特定の機能フラグに必要なダイナミクスに応じて、アプリインスタンスごとに、またはもっと細かく – おそらくユーザーまたはリクエストごとに、グローバルにそれらを設定する必要があるかもしれません。
ソフトウェアエンジニアリングの多くの状況と同様に、不要な複雑さを追加することなく、当面の問題に取り組む最も直接的なアプローチを使用することを試みることが重要です。
-
機能フラグは、賢く使用すると、システムに信頼性と安定性をもたらすことができる強力なツールです。しかし、彼らが誤用されたり保守が不十分な場合、それらはすぐに複雑さと頭痛の種になる可能性があります。
機能フラグが役に立つ可能性があるシナリオはたくさんあります。
トランクベースの開発では、特に頻繁に統合を続けたい場合は、特定の機能をリリースする準備ができていない可能性があります。機能フラグは、変更が完了するまで利用可能にすることなくリリースし続けることができるようにするのに役立ちます。
E2Eテスト環境用にデータベースをリセットするためには、特定の機能が必要になる可能性があります。
あるいは、実稼働環境で使用されているものとは異なる非実稼働環境用のセキュリティー構成を使用する必要があるかもしれません。
したがって、適切な環境で適切な設定を切り替えるために機能フラグを利用することができます。
同じ問題に対する複数の解決策を公開してその影響を測定することは、機能フラグを使用して実装できる魅力的な手法です。
新しい機能をデプロイするときは、少人数のユーザーグループから始めて、その動作の正確性を検証するためにその採用を拡大することで、徐々に行うことにするかもしれません。機能フラグにより、これを実現できます。
次のセクションでは、上記のシナリオに取り組むための実用的なアプローチを提供します。
最も簡単なシナリオから始めて、よりきめ細かくより複雑な設定に移行するという、フラグを立てるためのさまざまな戦略を打ち切りましょう。
3アプリケーションレベルの機能フラグ
単純な機能フラグには通常、プロパティとそのプロパティの値に基づく設定が含まれます。
3.1. スプリングプロファイルを使用した機能フラグ
BitCoinマイニングシステムを構築しているとしましょう。私たちのソフトウェアはすでに生産段階にあり、実験的で改良されたマイニングアルゴリズムを作成することが私たちの仕事です。
JavaConfig
では、コンポーネントをプロファイルできます。
@Configuration
public class ProfiledMiningConfig {
@Bean
@Profile("!experimental-miner")
public BitcoinMiner defaultMiner() {
return new DefaultBitcoinMiner();
}
@Bean
@Profile("experimental-miner")
public BitcoinMiner experimentalMiner() {
return new ExperimentalBitcoinMiner();
}
}
それから、
以前の設定で、私たちの新しい機能のためにオプトインするために私たちのプロファイルを単に含める必要があります。
我々のアプリを設定するためのたくさんの方法
とhttps://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html[特にプロファイルを有効にする]。同様に、私たちの生活を楽にするためにhttps://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#activeprofiles[テストユーティリティ]があります。
私たちのシステムが十分に単純である限り、どの機能フラグを適用し、どの機能フラグを無視するかを決定するために環境ベースの設定を作成することができます。
テーブルの代わりにカードをベースにした新しいUIが、以前の実験的なマイナーと共にいると想像してみてください。
受け入れ環境(UAT)で両方の機能を有効にしたいです。
application-uat.yml
ファイルを作成できます。
spring:
profiles:
include: experimental-miner,ui-cards
# More config here
前のファイルを作成したら、UAT環境でUATプロファイルを有効にして必要な機能セットを取得するだけで済みます。
spring.profiles.include.
を利用する方法を理解することも重要です。
私たちの場合は、
uat
プロファイルに、experimental-minerとui-cardを含めることを
__.
__とします。
3.2. カスタムプロパティを使用した機能フラグ
プロファイルは、仕事を終わらせるための素晴らしい簡単な方法です。ただし、他の目的でプロファイルが必要になる場合があります。あるいは、より構造化された機能フラグのインフラストラクチャを構築することをお勧めします。
これらのシナリオでは、カスタムプロパティが望ましい選択肢になるかもしれません。
-
@ ConditionalOnProperty
と名前空間を利用して、前の例を書き換えてみましょう。
@Configuration
public class CustomPropsMiningConfig {
@Bean
@ConditionalOnProperty(
name = "features.miner.experimental",
matchIfMissing = true)
public BitcoinMiner defaultMiner() {
return new DefaultBitcoinMiner();
}
@Bean
@ConditionalOnProperty(
name = "features.miner.experimental")
public BitcoinMiner experimentalMiner() {
return new ExperimentalBitcoinMiner();
}
}
-
前の例は、Spring Bootの条件付き設定に基づいて構築されており、プロパティが
true
または
false
に設定されている(またはまったく省略されている)かどうかに応じて、コンポーネントを設定します。
結果は3.1の結果と非常によく似ていますが、今、名前空間があります。名前空間を持つことで、意味のあるYAML/propertiesファイルを作成することができます。
#[...]Some Spring config
features:
miner:
experimental: true
ui:
cards: true
#[...]Other feature flags
また、この新しい設定では、機能フラグにプレフィックスを付けることができます。この場合は、
features
プレフィックス
__.
__を使用します。
細部のように思えるかもしれませんが、私たちのアプリケーションが大きくなり複雑さが増すにつれて、この単純な繰り返しは私たちの機能フラグを管理下に置くのを助けるでしょう。
このアプローチの他の利点について話しましょう。
3.3. @
ConfigurationProperties
を使用する
接頭辞の付いた一連のプロパティを取得したら、すぐにリンクを作成します。
私たちの進行中の例に従う:
@Component
@ConfigurationProperties(prefix = "features")
public class ConfigProperties {
private MinerProperties miner;
private UIProperties ui;
//standard getters and setters
public static class MinerProperties {
private boolean experimental;
//standard getters and setters
}
public static class UIProperties {
private boolean cards;
//standard getters and setters
}
}
-
機能フラグの状態をまとまりのある単位にすることで、新しい可能性を切り開き、その情報をシステムの他の部分(UIなど)や下流のシステムに簡単に公開できるようにします。
3.4. 機能構成の公開
私たちのBitcoinマイニングシステムは、まだ完全には準備ができていないUIアップグレードを得ました。そのため、機能フラグを立てることにしました。 React、Angular、またはVueを使用した単一ページのアプリがあるかもしれません。
テクノロジに関係なく、ページを適切にレンダリングできるように、どの機能が有効になっているかを知る必要があります。
必要に応じてUIがバックエンドを照会できるように、設定を提供する簡単なエンドポイントを作成しましょう。
@RestController
public class FeaturesConfigController {
private ConfigProperties properties;
//constructor
@GetMapping("/feature-flags")
public ConfigProperties getProperties() {
return properties;
}
}
カスタムのアクチュエーターエンドポイントの作成
など、この情報を提供するためのより洗練された方法があるかもしれません。しかし、このガイドでは、コントローラエンドポイントは十分に優れた解決策のように感じます。
3.5. キャンプを清潔に保つ
明らかに思えるかもしれませんが、機能フラグを慎重に実装した後は、不要になったフラグを削除することに懲戒を続けることも同様に重要です。
-
最初の使用例(トランクベースの開発と自明ではない機能)の機能フラグは、通常は短命です** 。つまり、
ConfigProperties、Javaの設定、および
YAML__の各ファイルを常に最新の状態に保つ必要があります。
4より詳細な機能フラグ
-
時には、私たちはもっと複雑なシナリオで自分自身を見つけることができます。 A/Bテストやカナリアリリースの場合、以前のアプローチでは不十分です。
機能フラグをより詳細なレベルで取得するには、ソリューションを作成する必要があります。これには、機能固有の情報を含めるようにユーザーエンティティをカスタマイズすること、またはおそらくWebフレームワークを拡張することが含まれます。
しかし、機能フラグを使ってユーザーを汚染することは、すべての人にとって魅力的なアイデアではないかもしれませんが、他にも解決策があります。
代替手段として、いくつかの組み込みツールhttps://www.togglz.org/[Togglzなど]を利用することもできます。このツールは複雑さを増しますが、すぐに使える優れた解決策とhttps://www.togglz.org/documentation/spring-boot-starter.html[Spring Bootとのファーストクラスの統合を提供します]。
Togglzはさまざまなhttps://www.togglz.org/documentation/activation-strategies.html[アクティベーション戦略]をサポートしています。
-
Username:
特定のユーザーに関連したフラグ -
段階的な展開:
ユーザーベースの割合に対してフラグが有効になりました.
これはCanaryのリリースに便利です。
機能の動作を検証する
。
リリース日:
特定の時点でフラグが有効になるようにスケジュールすることができます
日時。これは製品の発売、調整された
リリース、またはオファーや割引
。
クライアントIP:
クライアントIPに基づいて機能にフラグを付けました。これらが来るかもしれません
特定の顧客に特定の設定を適用するときに便利です。
静的IPがあることを考えると
。
サーバーIP:
この場合、サーバーのIPを使用して決定します。
機能を有効にするかどうか。これは役に立ちます。
カナリアリリースも、段階的なものとはわずかに異なるアプローチで
ロールアウト – 当社のパフォーマンスへの影響を評価したい場合など
インスタンス
。
ScriptEngine:
に基づいて機能フラグを有効にできます
arbitrary
スクリプト
。これは間違いなく最も柔軟な選択肢です。
。
システムのプロパティ:
特定のシステムのプロパティを
機能フラグの状態を決定します。これは、私たちが最も直接的なアプローチで達成したことと非常によく似ています。
5概要
-
この記事では、機能フラグについて説明する機会がありました。
さらに、新しいライブラリを追加せずにSpringがこの機能のいくつかを達成するのにどのように役立つかについても説明しました。
まず、このパターンがいくつかの一般的なユースケースでどのように役立つかを定義することから始めました。
次に、SpringとSpring Bootの標準ツールを使用して、いくつかの簡単なソリューションを構築しました。それで、私たちはシンプルで強力な機能フラグを立てる構文を思いついた。
以下では、いくつかの選択肢を比較しました。より単純で柔軟性の低いソリューションから、より複雑ではあるがより洗練されたパターンへの移行。
最後に、より堅牢なソリューションを構築するためのガイドラインをいくつか簡単に説明しました。これはより高度な粒度が必要なときに便利です。