Springの機能フラグ

Springの機能フラグ

1. 概要

この記事では、機能フラグを簡単に定義し、SpringBootアプリケーションにそれらを実装するための意見があり実用的なアプローチを提案します。 次に、さまざまなSpring Boot機能を利用して、より洗練されたイテレーションを掘り下げます。

機能のフラグ付けが必要になる可能性のあるさまざまなシナリオについて説明し、考えられる解決策について説明します。 これは、BitcoinMinerサンプルアプリケーションを使用して行います。

2. 機能フラグ

機能フラグ(機能トグルと呼ばれることもあります)は、コードを変更したり、理想的にはアプリを再デプロイしたりすることなく、アプリケーションの特定の機能を有効または無効にできるメカニズムです。

特定の機能フラグに必要なダイナミクスに応じて、グローバルに、アプリインスタンスごとに、またはより詳細に(おそらくユーザーまたはリクエストごとに)構成する必要があります。

ソフトウェアエンジニアリングの多くの状況と同様に、不必要な複雑さを追加することなく、目前の問題に取り組む最も簡単なアプローチを使用するようにすることが重要です。

機能フラグは、賢明に使用すると、システムに信頼性と安定性をもたらすことができる強力なツールです。 ただし、誤用されたり、メンテナンスが不十分だったりすると、すぐに複雑さと頭痛の種になる可能性があります。

機能フラグが役立つ可能性のある多くのシナリオがあります。

トランクベースの開発と重要な機能

トランクベースの開発では、特に頻繁に統合を続けたい場合、特定の機能をリリースする準備ができていないことがあります。 機能フラグは、変更が完了するまで利用可能にせずにリリースを継続できるようにするのに役立ちます。

環境固有の構成

E2Eテスト環境のDBをリセットするには、特定の機能が必要になる場合があります。

または、非本番環境では、本番環境で使用されているものとは異なるセキュリティ構成を使用する必要があります。

したがって、機能フラグを利用して、適切な環境で適切なセットアップを切り替えることができます。

A/B testing

同じ問題に対して複数のソリューションをリリースし、影響を測定することは、機能フラグを使用して実装できる魅力的な手法です。

カナリア解放

新しい機能を展開するときは、少数のユーザーグループから始めて、その動作の正確性を検証しながら採用を拡大することで、徐々に機能を決定することがあります。 機能フラグにより​​、これを実現できます。

次のセクションでは、上記のシナリオに取り組むための実用的なアプローチを提供しようとします。

最も単純なシナリオから始めて、よりきめ細かくより複雑な設定に移行することから、機能のフラグ付けにさまざまな戦略を分解してみましょう。

3. アプリケーションレベルの機能フラグ

最初の2つのユースケースのいずれかに取り組む必要がある場合、アプリケーションレベルの機能フラグは、物事を機能させるための簡単な方法です。

単純な機能フラグには通常、プロパティとそのプロパティの値に基づいた構成が含まれます。

3.1. Springプロファイルを使用したフィーチャーフラグ

春にはtake advantage of profilesができます。 Conveniently, profiles enable us to configure certain beans selectively. With a few constructs around them, we can quickly create a simple and elegant solution for application-level feature flags.

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();
    }
}

次に、with the previous configuration, we simply need to include our profile to opt-in for our new functionality.一般にtons of ways of configuring our appenabling profiles in particularがあります。 同様に、私たちの生活を楽にするtesting utilitiesがあります。

私たちのシステムが十分に単純である限り、we could then create an environment-based configuration to determine which features flags to apply and which ones to ignore.

以前の実験的なマイナーと一緒に、テーブルではなくカードに基づく新しいUIがあると想像してみましょう。

受け入れ環境(UAT)で両方の機能を有効にしたいと考えています。 application-uat.ymlファイルを作成できます。

spring:
  profiles:
    include: experimental-miner,ui-cards

# More config here

前のファイルを配置したら、UAT環境でUATプロファイルを有効にして、必要な機能のセットを取得する必要があります。

spring.profiles.include.を活用する方法を理解することも重要です。spring.profiles.active,と比較すると、前者ではプロファイルを追加的に含めることができます。

この場合、uatプロファイルにexperimental-minerとui-cards.も含める必要があります。

3.2. カスタムプロパティを使用した機能フラグ

プロファイルは、仕事を成し遂げるための優れたシンプルな方法です。 ただし、他の目的のためにプロファイルが必要になる場合があります。 または、より構造化された機能フラグインフラストラクチャを構築することもできます。

これらのシナリオでは、カスタムプロパティが望ましいオプションです。

Let’s rewrite our previous example taking advantage of @ConditionalOnProperty and our namespace

@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のどちらに設定されているか(または完全に省略されているか)に応じて、1つのコンポーネントまたは別のコンポーネントを構成します。

結果は3.1の結果と非常に似ていますが、現在は名前空間があります。 名前空間を持つことで、意味のあるYAML /プロパティファイルを作成できます。

#[...] Some Spring config

features:
  miner:
    experimental: true
  ui:
    cards: true

#[...] Other feature flags

また、この新しい設定により、機能フラグにプレフィックスを付けることができます。この場合、featuresプレフィックス.を使用します。

細かい点のように思えるかもしれませんが、アプリケーションが成長し複雑さが増すにつれて、この単純な反復は機能フラグを制御し続けるのに役立ちます。

このアプローチの他の利点について話しましょう。

3.3. @ConfigurationPropertiesの使用

プレフィックス付きのプロパティセットを取得するとすぐに、POJO decorated with @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. 機能構成の公開

私たちのビットコインマイニングシステムは、まだ完全に準備が整っていないUIアップグレードを取得しました。 そのため、機能フラグを立てることにしました。 React、Angular、またはVueを使用する単一ページのアプリがあるかもしれません。

テクノロジーに関係なく、we need to know what features are enabled so that we can render our page accordingly.

UIが必要なときにバックエンドにクエリを実行できるように、構成を提供する簡単なエンドポイントを作成しましょう。

@RestController
public class FeaturesConfigController {

    private ConfigProperties properties;

    // constructor

    @GetMapping("/feature-flags")
    public ConfigProperties getProperties() {
        return properties;
    }
}

creating custom actuator endpointsなど、この情報を提供するためのより洗練された方法があるかもしれません。 しかし、このガイドでは、コントローラーエンドポイントは十分なソリューションのように感じます。

3.5. キャンプを清潔に保つ

当たり前のように聞こえるかもしれませんが、機能フラグを慎重に実装した後は、不要になった機能フラグを取り除くための規律を維持することも同様に重要です。

Feature flags for the first use case – trunk-based development and non-trivial features – are typically short-lived。 つまり、ConfigProperties,がJava構成であり、YAMLファイルがクリーンで最新の状態に保たれていることを確認する必要があります。

4. より詳細な機能フラグ

より複雑なシナリオに陥ることもあります。 A / Bテストまたはカナリアリリースの場合、以前のアプローチでは不十分です。

機能フラグをより詳細なレベルで取得するには、ソリューションを作成する必要がある場合があります。 これには、ユーザーエンティティをカスタマイズして機能固有の情報を含めるか、Webフレームワークを拡張することが含まれます。

ただし、機能フラグを使用してユーザーを汚染することは、誰にとっても魅力的なアイデアではない場合があり、他の解決策もあります。

別の方法として、いくつかの組み込みツールsuch as Togglzを利用することもできます。 このツールは複雑さを増しますが、すぐに使える優れたソリューションとprovides first-class integration with Spring Bootを提供します。

Togglzはさまざまなactivation strategiesをサポートしています。

  1. Username:特定のユーザーに関連付けられたフラグ

  2. Gradual rollout:ユーザーベースのパーセンテージに対して有効になっているフラグ。 これは、機能の動作を検証する場合など、カナリアリリースに便利です。

  3. Release date:特定の日時にフラグを有効にするようにスケジュールできます。 これは、製品の発売、調整されたリリース、またはオファーと割引に役立つ場合があります

  4. Client IP:クライアントのIPに基づいてフラグが立てられた機能。 特定の構成を特定の顧客に適用する場合、これらは静的IPを持っているので、これらが便利になる場合があります

  5. Server IP:この場合、サーバーのIPを使用して、機能を有効にするかどうかを決定します。 これは、インスタンスのパフォーマンスへの影響を評価する場合のように、段階的なロールアウトとは少し異なるアプローチで、カナリアリリースにも役立ちます。

  6. ScriptEngine:arbitrary scriptsに基づいて機能フラグを有効にすることができます。 これはおそらく最も柔軟なオプションです

  7. System Properties:特定のシステムプロパティを設定して、機能フラグの状態を判別できます。 これは、最も単純なアプローチで達成したものと非常に似ています。

5. 概要

この記事では、フィーチャートグルについて話す機会がありました。 さらに、Springが新しいライブラリを追加せずにこの機能の一部を実現するのにどのように役立つかについても説明しました。

最初に、このパターンがいくつかの一般的なユースケースでどのように役立つかを定義することから始めました。

次に、SpringおよびSpring Bootのすぐに使えるツールを使用して、いくつかの簡単なソリューションを構築しました。 それで、シンプルでありながら強力な機能フラグ付け構造を思い付きました。

以下では、いくつかの選択肢を比較しました。 より単純で柔軟性の低いソリューションから、より複雑ではあるがより洗練されたパターンへの移行。

最後に、より堅牢なソリューションを構築するためのガイドラインを簡単に提供しました。 これは、より高度な粒度が必要な場合に便利です。