Бөлісу құралы:


Управление функциями .NET

Microsoft.FeatureManagement
Microsoft.FeatureManagement.AspNetCore

Microsoft.FeatureManagement
Microsoft.FeatureManagement.AspNetCore
Microsoft.FeatureManagement.Telemetry.ApplicationInsights
Microsoft.FeatureManagement.Telemetry.ApplicationInsights.AspNetCore

Библиотека управления функциями .NET позволяет разрабатывать и предоставлять функциональные возможности приложений на основе флагов компонентов. После разработки новой функции многие приложения имеют особые требования, например, когда эта функция должна быть включена и в каких условиях. Эта библиотека предоставляет способ определения этих связей, а также интеграции с общими шаблонами кода .NET для предоставления этих функций.

Флаги функций позволяют приложениям .NET и ASP.NET Core включать или отключать функции динамически. Разработчики могут использовать флаги функций в простых случаях использования, таких как условные инструкции для более сложных сценариев, таких как условное добавление маршрутов или фильтров MVC. Флаги компонентов основаны на системе конфигурации .NET Core. Любой поставщик конфигурации .NET Core может выступать в качестве магистрали флагов компонентов.

Ниже приведены некоторые преимущества использования библиотеки управления функциями .NET.

  • Общее соглашение об управлении функциями

  • Низкий барьер к входу

    • Построено на основе IConfiguration
    • Поддерживает настройку флага компонента JSON
  • Управление временем существования флага компонентов

    • Значения конфигурации могут изменяться в режиме реального времени; Флаги функций могут быть согласованы по всему запросу
  • Простые и сложные сценарии

    • Включение и отключение функций с помощью декларативного файла конфигурации
    • Динамическое вычисление состояния функции на основе вызова сервера
  • Расширения API для платформы ASP.NET Core и MVC

    • Маршрутизация
    • Фильтры
    • Атрибуты действия

    Библиотека управления функциями .NET открытый код. Дополнительные сведения см. в репозитории GitHub.

Флаги компонентов

Флаги компонентов состоят из двух частей, имени и списка фильтров функций, которые используются для включения функции.

Фильтры компонентов

Фильтры функций определяют сценарий, в котором должна быть включена функция. Если функция оценивается для того, включена ли она или отключена, список фильтров функций проходит до тех пор, пока один из фильтров не решит, что эта функция должна быть включена. На этом этапе функция считается включенной и обхода через фильтры компонентов останавливается. Если фильтр компонентов не указывает, что эта функция должна быть включена, считается отключенной.

Например, можно создать фильтр функций браузера Microsoft Edge. Этот фильтр функций активирует все функции, к ним присоединенные, если HTTP-запрос поступает из Microsoft Edge.

Конфигурация флага компонента

Система конфигурации .NET Core используется для определения состояния флагов компонентов. Основой этой системы является IConfiguration. Любой поставщик IConfiguration можно использовать в качестве поставщика состояния компонента для библиотеки флагов компонентов. Эта система позволяет сценариям от appsettings.json до Конфигурация приложений Azure и многое другое.

Объявление флага компонента

Библиотека управления функциями поддерживает appsettings.json в качестве источника флага компонентов, так как это поставщик системы .NET Core IConfiguration . Ниже приведен пример формата, используемого для настройки флагов компонентов в json-файле.

{
    "Logging": {
        "LogLevel": {
            "Default": "Warning"
        }
    },

    // Define feature flags in a json file
    "FeatureManagement": {
        "FeatureT": {
            "EnabledFor": [
                {
                    "Name": "AlwaysOn"
                }
            ]
        },
        "FeatureU": {
            "EnabledFor": []
        },
        "FeatureV": {
            "EnabledFor": [
                {
                    "Name": "TimeWindow",
                    "Parameters": {
                        "Start": "Wed, 01 May 2019 13:59:59 GMT",
                        "End": "Mon, 01 Jul 2019 00:00:00 GMT"
                    }
                }
            ]
        }
    }
}

Раздел FeatureManagement документа JSON используется по соглашению для загрузки параметров флага компонентов. В приведенном выше разделе мы видим три различных компонента. Функции определяют фильтры функций с помощью EnabledFor свойства. В фильтрах FeatureTфункций для , мы видим AlwaysOn. Этот фильтр функций встроенный, и если он указан, всегда будет включать эту функцию. Фильтр AlwaysOn компонентов не требует какой-либо конфигурации, поэтому он имеет Name только свойство. FeatureU не имеет фильтров в своем EnabledFor свойстве и поэтому никогда не будет включен. Все функции, использующие эту функцию, не будут доступны, пока фильтры функций остаются пустыми. Тем не менее, как только будет добавлен фильтр компонентов, который включает функцию, которую он может начать работать. FeatureV указывает фильтр признаков с именем TimeWindow. Это пример настраиваемого фильтра компонентов. Мы видим в примере, что фильтр имеет Parameters свойство. Используется для настройки фильтра. В этом случае настроено время начала и окончания для активной функции.

Подробные схемы FeatureManagement раздела можно найти здесь.

Дополнительно. Использование двоеточия ":" запрещено в именах флагов признаков.

Объявление "вкл./выкл."

В следующем фрагменте кода демонстрируется альтернативный способ определения функции, которая может использоваться для функций включено или выключение.

{
    "Logging": {
        "LogLevel": {
            "Default": "Warning"
        }
    },

    // Define feature flags in config file
    "FeatureManagement": {
        "FeatureT": true, // On feature
        "FeatureX": false // Off feature
    }
}

Тип требования

Свойство RequirementType флага компонента используется для определения того, должны ли фильтры использовать Any или All логику при оценке состояния компонента. Если RequirementType значение по умолчанию не указано, значение Anyпо умолчанию .

  • Any означает, что только один фильтр должен иметь значение true для включения функции.
  • All означает, что каждый фильтр должен иметь значение true для включения функции.

All Изменение RequirementType обхода. Во-первых, если фильтров нет, функция отключена. Затем фильтры функций проходят по одному из фильтров, пока один из фильтров не решит, что эта функция должна быть отключена. Если фильтр не указывает, что функция должна быть отключена, она считается включенной.

"FeatureW": {
    "RequirementType": "All",
    "EnabledFor": [
        {
            "Name": "TimeWindow",
            "Parameters": {
                "Start": "Mon, 01 May 2023 13:59:59 GMT",
                "End": "Sat, 01 Jul 2023 00:00:00 GMT"
            }
        },
        {
            "Name": "Percentage",
            "Parameters": {
                "Value": "50"
            }
        }
    ]
}

В приведенном выше примере указывает значение RequirementType All, FeatureW что означает, что все его фильтры должны иметь значение true, чтобы функция была включена. В этом случае функция включена для 50% пользователей в течение указанного периода времени.

Схема управления функциями Майкрософт

Библиотека управления функциями также поддерживает использование Microsoft Feature Management schema флагов компонентов. Эта схема не зависит от языка и поддерживается всеми библиотеками управления функциями Майкрософт.

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "FeatureT",
                "enabled": true,
                "conditions": {
                    "client_filters": [
                        {  
                            "name": "Microsoft.TimeWindow",
                            "parameters": {
                                "Start": "Mon, 01 May 2023 13:59:59 GMT",
                                "End": "Sat, 01 Jul 2023 00:00:00 GMT"
                            }
                        }
                    ]
                }
            }
        ]
    }
}

Примечание.

Если раздел feature_management можно найти в конфигурации, FeatureManagement раздел игнорируется.

Библиотека управления функциями поддерживает appsettings.json в качестве источника флага компонентов, так как это поставщик системы .NET Core IConfiguration . Флаги компонентов объявляются с помощью . Microsoft Feature Management schema. Эта схема не зависит от языка и поддерживается всеми библиотеками управления функциями Майкрософт.

Ниже приведен пример объявления флагов функций в json-файле.

{
    "Logging": {
        "LogLevel": {
            "Default": "Warning"
        }
    },

    // Define feature flags in a json file
    "feature_management": {
        "feature_flags": [
            {
                "id": "FeatureT",
                "enabled": false
            },
            {
                "id": "FeatureU",
                "enabled": true,
                "conditions": {}
            },
            {
                "id": "FeatureV",
                "enabled": true,
                "conditions": {
                    "client_filters": [
                        {  
                            "name": "Microsoft.TimeWindow",
                            "parameters": {
                                "Start": "Mon, 01 May 2023 13:59:59 GMT",
                                "End": "Sat, 01 July 2023 00:00:00 GMT"
                            }
                        }
                    ]
                }
            }
        ]
    }
}

Раздел feature_management документа JSON используется по соглашению для загрузки параметров флага компонентов. Объекты флага компонентов должны быть перечислены в массиве feature_flags feature_management в разделе. В приведенном выше разделе мы видим, что мы предоставили три различных функции. Флаг компонента имеет id и enabled свойства. Это id имя, используемое для идентификации и ссылки на флаг компонента. Свойство enabled указывает состояние включенного флага компонента. Функция отключена, если enabled имеет значение false. Если enabled задано значение true, состояние функции зависит от conditionsзначения. Если нетconditions, функция включена. Если есть conditions и они выполнены, функция включена. Если есть conditions и они не выполнены, функция отключена. Свойство conditions объявляет условия, используемые для динамического включения функции. Функции определяют фильтры функций в массиве client_filters . FeatureV указывает фильтр признаков с именем Microsoft.TimeWindow. Это пример настраиваемого фильтра компонентов. Мы видим в примере, что фильтр имеет Parameters свойство. Используется для настройки фильтра. В этом случае настроено время начала и окончания для активной функции.

Дополнительно. Использование двоеточия ":" запрещено в именах флагов признаков.

Тип требования

Свойство requirement_type conditions используется для определения того, должны ли фильтры использовать Any или All логику при оценке состояния компонента. Если requirement_type значение по умолчанию не указано, значение Anyпо умолчанию .

  • Any означает, что только один фильтр должен иметь значение true для включения функции.
  • All означает, что каждый фильтр должен иметь значение true для включения функции.

All Изменение requirement_type обхода. Во-первых, если фильтр отсутствует, функция будет отключена. Если существуют фильтры, то фильтры функций проходят до тех пор, пока один из фильтров не решит, что эта функция должна быть отключена. Если фильтр не указывает, что компонент должен быть отключен, он будет считаться включенным.

{
    "id": "FeatureW",
    "enabled": true,
    "conditions": {
        "requirement_type": "All",
        "client_filters": [
            {
                "name": "Microsoft.TimeWindow",
                "parameters": {
                    "Start": "Mon, 01 May 2023 13:59:59 GMT",
                    "End": "Sat, 01 Jul 2023 00:00:00 GMT"
                }
            },
            {
                "name": "Microsoft.Percentage",
                "parameters": {
                    "Value": "50"
                }
            }
        ]
    }
}

В приведенном выше примере указывает значение requirement_type All, FeatureW что означает, что все его фильтры должны иметь значение true, чтобы функция была включена. В этом случае функция будет включена для 50% пользователей в течение указанного периода времени.

Схема управления функциями .NET

В предыдущих версиях основная схема библиотеки управления функциями была основной .NET feature management schema. Начиная с версии 4.0.0 новые функции, включая варианты и данные телеметрии, не будут поддерживаться для схемы управления функциями .NET.

Примечание.

Если флаг компонента, написанный с Microsoft Feature Management schema помощью конфигурации, можно найти в конфигурации, любой флаг компонента, записанный с ним .NET feature management schema , будет игнорироваться.

Потребление

Базовая форма управления функциями проверяет, включен ли флаг компонента, а затем выполняет действия на основе результата. Это делается с помощью IFeatureManagerIsEnabledAsync метода.

…
IFeatureManager featureManager;
…
if (await featureManager.IsEnabledAsync("FeatureX"))
{
    // Do something
}

Регистрация службы

Управление функциями зависит от внедрения зависимостей .NET Core. Мы можем зарегистрировать службы управления функциями с помощью стандартных соглашений.

using Microsoft.FeatureManagement;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddFeatureManagement();
    }
}

По умолчанию диспетчер компонентов получает конфигурацию флага компонента из раздела "FeatureManagement" данных конфигурации .NET Core. Если раздел FeatureManagement не существует, конфигурация считается пустой.

Примечание.

Можно также указать, что конфигурация флага компонентов должна быть получена из другого раздела конфигурации, передав раздел в AddFeatureManagement. В следующем примере диспетчер функций сообщает диспетчеру функций прочитать из другого раздела "MyFeatureFlags" вместо этого:

services.AddFeatureManagement(configuration.GetSection("MyFeatureFlags"));

Внедрение зависимостей

При использовании библиотеки управления функциями с MVC IFeatureManager можно получить с помощью внедрения зависимостей.

public class HomeController : Controller
{
    private readonly IFeatureManager _featureManager;
    
    public HomeController(IFeatureManager featureManager)
    {
        _featureManager = featureManager;
    }
}

Службы управления функциями с областью действия

Этот AddFeatureManagement метод добавляет службы управления функциями в качестве одноэлементных в приложении, но существуют сценарии, в которых может потребоваться добавить службы управления функциями в качестве областных служб. Например, пользователи могут использовать фильтры функций, использующие службы с областью действия для контекстной информации. В этом случае AddScopedFeatureManagement вместо этого следует использовать метод. Это гарантирует, что службы управления функциями, включая фильтры компонентов, добавляются в качестве служб с областью действия.

services.AddScopedFeatureManagement();

интеграция ASP.NET Core

Библиотека управления функциями предоставляет функциональные возможности в ASP.NET Core и MVC для включения распространенных сценариев флагов функций в веб-приложениях. Эти возможности доступны, ссылаясь на пакет NuGet Microsoft.FeatureManagement.AspNetCore .

Контроллеры и действия

Для выполнения контроллера и действий MVC может потребоваться включить определенную функцию или один из всех списков функций. Это можно сделать с помощью FeatureGateAttributeэлемента, который можно найти в Microsoft.FeatureManagement.Mvc пространстве имен.

[FeatureGate("FeatureX")]
public class HomeController : Controller
{
    …
}

Приведенный HomeController выше элемент имеет значение FeatureX. Параметр FeatureX должен быть включен перед выполнением любого действия HomeController , содержащегося в нем.

[FeatureGate("FeatureX")]
public IActionResult Index()
{
    return View();
}

Для Index включения действия MVC выше требуется включить FeatureX, прежде чем его можно будет выполнить.

Обработка отключенных действий

Если контроллер или действие MVC заблокированы, так как ни одна из указанных функций не включена, будет вызываться зарегистрированный IDisabledFeaturesHandler контроллер или действие. По умолчанию регистрируется минималистичный обработчик, который возвращает HTTP 404. Это можно переопределить с помощью IFeatureManagementBuilder флагов функций регистрации.

public interface IDisabledFeaturesHandler
{
    Task HandleDisabledFeature(IEnumerable<string> features, ActionExecutingContext context);
}

Представления

В тегах представлений <feature> MVC можно использовать для условной отрисовки содержимого в зависимости от того, включена ли функция.

<feature name="FeatureX">
  <p>This can only be seen if 'FeatureX' is enabled.</p>
</feature>

Вы также можете отменить вспомогательное вычисление тега для отображения содержимого при отключении компонента или набора компонентов. negate="true" Установив в приведенном ниже примере, содержимое отображается только при FeatureX отключении.

<feature negate="true" name="FeatureX">
  <p>This can only be seen if 'FeatureX' is disabled.</p>
</feature>

Тег <feature> может ссылаться на несколько функций, указав разделенный запятыми список функций в атрибуте name .

<feature name="FeatureX,FeatureY">
  <p>This can only be seen if 'FeatureX' and 'FeatureY' are enabled.</p>
</feature>

По умолчанию все перечисленные компоненты должны быть включены для отрисовки тега компонента. Это поведение можно переопределить, добавив requirement атрибут, как показано в приведенном ниже примере.

<feature name="FeatureX,FeatureY" requirement="Any">
  <p>This can only be seen if either 'FeatureX' or 'FeatureY' or both are enabled.</p>
</feature>

В тегах представлений <feature> MVC можно использовать для условной отрисовки содержимого в зависимости от того, включена ли функция или назначен конкретный вариант функции. Дополнительные сведения см. в разделе "Варианты ".

<feature name="FeatureX">
  <p>This can only be seen if 'FeatureX' is enabled.</p>
</feature>
<feature name="FeatureX" variant="Alpha">
  <p>This can only be seen if variant 'Alpha' of 'FeatureX' is assigned.</p>
</feature>

Вы также можете отменить вспомогательное вычисление тега для отображения содержимого при отключении компонента или набора компонентов. negate="true" Установив в приведенном ниже примере, содержимое отображается только при FeatureX отключении.

<feature negate="true" name="FeatureX">
  <p>This can only be seen if 'FeatureX' is disabled.</p>
</feature>
<feature negate="true" name="FeatureX" variant="Alpha">
  <p>This can only be seen if variant 'Alpha' of 'FeatureX' isn't assigned.</p>
</feature>

Тег <feature> может ссылаться на несколько функций и вариантов, указав разделенный запятыми список функций и вариантов в атрибуте name/variant .

<feature name="FeatureX,FeatureY">
  <p>This can only be seen if 'FeatureX' and 'FeatureY' are enabled.</p>
</feature>
<feature name="FeatureX" variant="Alpha,Beta">
  <p>This can only be seen if variant 'Alpha' or 'Beta' of 'FeatureX' is assigned.</p>
</feature>

Примечание.

Если variant задано, необходимо указать только одну функцию.

По умолчанию все перечисленные компоненты должны быть включены для отрисовки тега компонента. Это поведение можно переопределить, добавив requirement атрибут, как показано в приведенном ниже примере.

Примечание.

requirement And Если используется в сочетании с variant ошибкой, возникает ошибка, так как нельзя назначать несколько вариантов.

<feature name="FeatureX,FeatureY" requirement="Any">
  <p>This can only be seen if either 'FeatureX' or 'FeatureY' or both are enabled.</p>
</feature>

Для <feature> тега требуется вспомогательный элемент тега. Это можно сделать, добавив вспомогательный тег управления функциями в файл ViewImports.cshtml .

@addTagHelper *, Microsoft.FeatureManagement.AspNetCore

Фильтры MVC

Фильтры действий MVC можно настроить для условного выполнения на основе состояния компонента. Это делается путем регистрации фильтров MVC в многофункциональном режиме. Конвейер управления функциями поддерживает асинхронные фильтры действий MVC, которые реализуют IAsyncActionFilter.

services.AddMvc(o => 
{
    o.Filters.AddForFeature<SomeMvcFilter>("FeatureX");
});

Приведенный выше код добавляет фильтр MVC с именем SomeMvcFilter. Этот фильтр активируется только в конвейере MVC, если включен параметр FeatureX.

Razor Pages

Для выполнения страниц Razor MVC может потребоваться включить определенную функцию или один из всех списков функций. Это можно сделать с помощью FeatureGateAttributeэлемента, который можно найти в Microsoft.FeatureManagement.Mvc пространстве имен.

[FeatureGate("FeatureX")]
public class IndexModel : PageModel
{
    public void OnGet()
    {
    }
}

Приведенный выше код настраивает страницу Razor для включения компонента FeatureX. Если функция не включена, страница создает результат HTTP 404 (NotFound).

При использовании на страницах FeatureGateAttribute Razor необходимо поместить его в тип обработчика страниц. Его нельзя поместить в отдельные методы обработчика.

Сборка приложений

Библиотеку управления функциями можно использовать для добавления ветвей приложений и ПО промежуточного слоя, которые выполняются условно на основе состояния компонента.

app.UseMiddlewareForFeature<ThirdPartyMiddleware>("FeatureX");

При приведенном выше вызове приложение добавляет компонент ПО промежуточного слоя, который отображается только в конвейере запросов, если включена функция FeatureX. Если функция включена или отключена во время выполнения, конвейер ПО промежуточного слоя может быть динамически изменен.

Это создает более универсальную возможность для ветвления всего приложения на основе функции.

app.UseForFeature(featureName, appBuilder => 
{
    appBuilder.UseMiddleware<T>();
});

Реализация фильтра компонентов

Создание фильтра функций позволяет включить функции на основе заданных критериев. Для реализации фильтра IFeatureFilter функций интерфейс должен быть реализован. IFeatureFilter имеет один метод с именем EvaluateAsync. Если компонент указывает, что его можно включить для фильтра компонентов, EvaluateAsync вызывается метод. Если EvaluateAsync возвращается true, это означает, что эта функция должна быть включена.

В следующем фрагменте кода показано, как добавить настраиваемый фильтр MyCriteriaFilterкомпонентов.

services.AddFeatureManagement()
        .AddFeatureFilter<MyCriteriaFilter>();

Фильтры функций регистрируются путем вызова AddFeatureFilter<T> возвращаемого IFeatureManagementBuilder объекта AddFeatureManagement. Эти фильтры функций имеют доступ к службам, существующим в коллекции служб, которая использовалась для добавления флагов компонентов. Внедрение зависимостей можно использовать для получения этих служб.

Примечание.

Если фильтры ссылаются в параметрах флага компонентов (например, appsettings.json), следует опустить часть фильтра имени типа. Дополнительные сведения см. в Filter Alias Attribute разделе.

Параметризованные фильтры компонентов

Некоторые фильтры функций требуют параметров, чтобы решить, следует ли включить или нет функцию. Например, фильтр функций браузера может включить функцию для определенного набора браузеров. Возможно, требуется, чтобы браузеры Edge и Chrome могли включить функцию, в то время как Firefox не поддерживает. Для этого можно настроить фильтр компонентов для ожидания параметров. Эти параметры будут указаны в конфигурации компонента, и в коде будет доступен с помощью FeatureFilterEvaluationContext параметра IFeatureFilter.EvaluateAsync.

public class FeatureFilterEvaluationContext
{
    /// <summary>
    /// The name of the feature being evaluated.
    /// </summary>
    public string FeatureName { get; set; }

    /// <summary>
    /// The settings provided for the feature filter to use when evaluating whether the feature should be enabled.
    /// </summary>
    public IConfiguration Parameters { get; set; }
}

FeatureFilterEvaluationContext имеет свойство с именем Parameters. Эти параметры представляют необработанную конфигурацию, которую фильтр компонентов может использовать для определения того, следует ли включить или нет эту функцию. Чтобы использовать фильтр функций браузера в качестве примера, фильтр может использовать Parameters для извлечения набора разрешенных браузеров, которые будут указаны для функции, а затем проверить, отправляется ли запрос из одного из этих браузеров.

[FilterAlias("Browser")]
public class BrowserFilter : IFeatureFilter
{
    …

    public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context)
    {
        BrowserFilterSettings settings = context.Parameters.Get<BrowserFilterSettings>() ?? new BrowserFilterSettings();

        //
        // Here we would use the settings and see if the request was sent from any of BrowserFilterSettings.AllowedBrowsers
    }
}

Атрибут псевдонима фильтра

При регистрации фильтра компонентов для флага компонента псевдоним, используемый в конфигурации, — это имя типа фильтра компонентов с суффиксом фильтра , если таковые имеются, удалены. Например, MyCriteriaFilter в конфигурации будет называться MyCriteria .

"MyFeature": {
    "EnabledFor": [
        {
            "Name": "MyCriteria"
        }
    ]
}

Это можно переопределить с помощью .FilterAliasAttribute Фильтр компонентов можно декорировать этим атрибутом, чтобы объявить имя, которое должно использоваться в конфигурации для ссылки на этот фильтр компонентов в флаге компонента.

Отсутствующие фильтры компонентов

Если функция настроена для определенного фильтра компонентов и этот фильтр компонентов не зарегистрирован, при оценке компонента возникает исключение. Исключение можно отключить с помощью параметров управления функциями.

services.Configure<FeatureManagementOptions>(options =>
{
    options.IgnoreMissingFeatureFilters = true;
});

Использование HttpContext

Фильтры функций могут оценить, должна ли функция быть включена на основе свойств HTTP-запроса. Это выполняется путем проверки контекста HTTP. Фильтр функций может получить ссылку на контекст HTTP, получив IHttpContextAccessor путем внедрения зависимостей.

public class BrowserFilter : IFeatureFilter
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public BrowserFilter(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
    }
}

Он IHttpContextAccessor должен быть добавлен в контейнер внедрения зависимостей при запуске, чтобы он был доступен. Его можно зарегистрировать в следующем методе IServiceCollection .

public void ConfigureServices(IServiceCollection services)
{
    …
    services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    …
}

Дополнительно: IHttpContextAccessor/HttpContext не следует использовать в компонентах Razor серверных приложений Blazor. Рекомендуемый подход к передаче контекста HTTP в приложениях Blazor заключается в копировании данных в службу с областью действия. Для приложений AddScopedFeatureManagement Blazor следует использовать для регистрации служб управления функциями. Дополнительные сведения см. в Scoped Feature Management Services разделе.

Предоставление контекста для оценки компонентов

В консольных приложениях нет контекста окружающей среды, например HttpContext фильтров компонентов, может получить и использовать, чтобы проверить, должна ли функция быть включена или отключена. В этом случае приложениям необходимо предоставить объект, представляющий контекст в системе управления функциями для использования фильтрами компонентов. Это делается с помощью IFeatureManager.IsEnabledAsync<TContext>(string featureName, TContext appContext). Объект appContext, предоставляемый диспетчеру функций, можно использовать фильтрами компонентов для оценки состояния компонента.

MyAppContext context = new MyAppContext
{
    AccountId = current.Id;
}

if (await featureManager.IsEnabledAsync(feature, context))
{
…
}

Контекстные фильтры компонентов

Контекстные фильтры функций реализуют IContextualFeatureFilter<TContext> интерфейс. Эти фильтры специальных функций могут воспользоваться контекстом, передаваемым при IFeatureManager.IsEnabledAsync<TContext> вызове. Параметр TContext типа в IContextualFeatureFilter<TContext> описании типа контекста, который фильтр может обрабатывать. Это позволяет разработчику контекстного фильтра функций описать, что необходимо для тех, кто хочет использовать его. Так как каждый тип является потомком объекта, фильтр, реализующий IContextualFeatureFilter<object> его, можно вызывать для любого предоставленного контекста. Чтобы проиллюстрировать пример более конкретного контекстного фильтра функций, рассмотрите функцию, которая включена, если учетная запись находится в настроенном списке включенных учетных записей.

public interface IAccountContext
{
    string AccountId { get; set; }
}

[FilterAlias("AccountId")]
class AccountIdFilter : IContextualFeatureFilter<IAccountContext>
{
    public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext featureEvaluationContext, IAccountContext accountId)
    {
        //
        // Evaluate if the feature should be on with the help of the provided IAccountContext
    }
}

Мы видим, что AccountIdFilter требуется, чтобы объект, реализуемый IAccountContext для предоставления, мог оценить состояние компонента. При использовании этого фильтра функций вызывающий объект должен убедиться, что переданный в объект реализуется IAccountContext.

Примечание.

Только один интерфейс фильтра признаков может быть реализован одним типом. При попытке добавить фильтр компонентов, реализующий более одного интерфейса фильтра признаков, приводит к тому, что ArgumentException

Использование контекстных и не контекстных фильтров с одинаковым псевдонимом

IFeatureFilter Фильтры и IContextualFeatureFilter могут совместно использовать один и тот же псевдоним. В частности, у вас может быть один псевдоним фильтра, которым предоставлен общий доступ к 0 или 1 IFeatureFilter и 0 или NIContextualFeatureFilter<ContextType>, если существует не более одного применимого фильтра.ContextType

В следующем фрагменте описывается процесс выбора фильтра при регистрации контекстных и не контекстных фильтров того же имени в приложении.

Предположим, что у вас есть не контекстный фильтр, называемый FilterA и два контекстных фильтра FilterB и FilterC, которые принимают TypeB и TypeC контексты соответственно. Все три фильтра имеют одинаковый псевдоним SharedFilterName.

У вас также есть флаг MyFeature компонента, использующий фильтр SharedFilterName компонентов в его конфигурации.

Если регистрируются все три фильтра:

  • При вызове IsEnabledAsync("MyFeature") FilterA используется для оценки флага функции.
  • При вызове IsEnabledAsync("MyFeature", context), если используется TypeBFilterB тип контекста. Если используется TypeCтип контекста, FilterC используется.
  • При вызове IsEnabledAsync("MyFeature", context), если используется TypeFFilterA тип контекста.

Встроенные фильтры компонентов

Существует несколько фильтров функций, которые поставляется с пакетомMicrosoft.FeatureManagement: PercentageFilter, TimeWindowFilterContextualTargetingFilter и TargetingFilter. Все фильтры, кроме TargetingFilterэтого, добавляются автоматически , когда управление функциями регистрируется методом AddFeatureManagement . Он TargetingFilter добавляется с WithTargeting помощью метода, подробно описанного в Targeting разделе ниже.

Каждый из встроенных фильтров функций имеет собственные параметры. Ниже приведен список фильтров функций вместе с примерами.

Microsoft.Percentage

Этот фильтр предоставляет возможность включить функцию на основе заданного процента.

"EnhancedPipeline": {
    "EnabledFor": [
        {
            "Name": "Microsoft.Percentage",
            "Parameters": {
                "Value": 50
            }
        }
    ]
}

Microsoft.TimeWindow

Этот фильтр предоставляет возможность включить функцию на основе периода времени. Если указан только End этот параметр, функция рассматривается до этого времени. Если указан только Start этот параметр, функция рассматривается во всех точках после этого времени.

"EnhancedPipeline": {
    "EnabledFor": [
        {
            "Name": "Microsoft.TimeWindow",
            "Parameters": {
                "Start": "Wed, 01 May 2019 13:59:59 GMT",
                "End": "Mon, 01 Jul 2019 00:00:00 GMT"
            }
        }
    ]
}

Период времени можно настроить для периодического повторения. Это может быть полезно для сценариев, когда может потребоваться включить функцию в течение низкого или высокого периода трафика в день или определенные дни недели. Чтобы развернуть отдельное окно времени до повторяющихся окон времени, правило повторения должно быть указано в параметре Recurrence .

Примечание.

Start и End должны быть указаны как для включения Recurrence.

"EnhancedPipeline": {
    "EnabledFor": [
        {
            "Name": "Microsoft.TimeWindow",
            "Parameters": {
                "Start": "Fri, 22 Mar 2024 20:00:00 GMT",
                "End": "Sat, 23 Mar 2024 02:00:00 GMT",
                "Recurrence": {
                    "Pattern": {
                        "Type": "Daily",
                        "Interval": 1
                    },
                    "Range": {
                        "Type": "NoEnd"
                    }
                }
            }
        }
    ]
}

Параметры Recurrence состоят из двух частей: Pattern (как часто повторяется временное окно) и Range (как долго повторяется шаблон повторения повторения).

Шаблон повторения

Существует два возможных типа шаблонов повторения: Daily и Weekly. Например, период времени может повторять "каждый день", "каждые три дня", "каждый понедельник" или "каждую другую пятницу".

В зависимости от типа определенные поля Pattern обязательны, необязательные или игнорируются.

  • Daily

    Шаблон ежедневного повторения приводит к повтору периода времени на основе нескольких дней между каждым вхождением.

    Свойство С сортировкой по релевантности Описание
    Тип Обязательное поле Должен иметь значениеDaily.
    Интервал Необязательно Указывает количество дней между каждым вхождением. Значение по умолчанию — 1.
  • Weekly

    Еженедельный шаблон повторения приводит к тому, что период времени повторяется в один или несколько дней недели в зависимости от количества недель между каждым набором вхождения.

    Свойство С сортировкой по релевантности Описание
    Тип Обязательное поле Должен иметь значениеWeekly.
    DaysOfWeek Обязательное поле Указывает, в каких днях недели происходит событие.
    Интервал Необязательно Указывает количество недель между каждым набором вхождений. Значение по умолчанию — 1.
    FirstDayOfWeek Необязательно Указывает, какой день считается первым днем недели. Значение по умолчанию: Sunday.

    В следующем примере повторяется время каждого другого понедельника и вторника

    "Pattern": {
        "Type": "Weekly",
        "Interval": 2,
        "DaysOfWeek": ["Monday", "Tuesday"]
    }
    

Примечание.

Start должно быть допустимым первым вхождением, которое соответствует шаблону повторения. Кроме того, продолжительность периода времени не может превышать частоту ее возникновения. Например, недопустимо, чтобы каждый день повторялось 25-часовое окно времени.

Диапазон повторений

Существует три возможных типа диапазонов повторений: NoEndEndDate и Numbered.

  • NoEnd

    Диапазон NoEnd приводит к тому, что повторение происходит на неопределенный срок.

    Свойство С сортировкой по релевантности Описание
    Тип Обязательное поле Должен иметь значениеNoEnd.
  • EndDate

    Диапазон EndDate приводит к возникновению периода времени в течение всех дней, которые соответствуют применимому шаблону до даты окончания.

    Свойство С сортировкой по релевантности Описание
    Тип Обязательное поле Должен иметь значениеEndDate.
    EndDate Обязательное поле Указывает время даты для остановки применения шаблона. До тех пор, пока время начала последнего вхождения истекает до даты окончания, время окончания этого вхождения может быть расширено.

    Следующий пример будет повторять период времени каждый день до последнего вхождения 1 апреля 2024 года.

    "Start": "Fri, 22 Mar 2024 18:00:00 GMT",
    "End": "Fri, 22 Mar 2024 20:00:00 GMT",
    "Recurrence":{
        "Pattern": {
            "Type": "Daily",
            "Interval": 1
        },
        "Range": {
            "Type": "EndDate",
            "EndDate": "Mon, 1 Apr 2024 20:00:00 GMT"
        }
    }
    
  • Numbered

    Диапазон Numbered приводит к возникновению фиксированного количества времени (на основе шаблона).

    Свойство С сортировкой по релевантности Описание
    Тип Обязательное поле Должен иметь значениеNumbered.
    NumberOfOccurrences Обязательное поле Указывает количество вхождения.

    В следующем примере будет повторяться временное окно в понедельник и вторник, пока не будет три вхождения, которые соответственно происходят 1 апреля, 2(Tue) и 8 апреля (Mon).

    "Start": "Mon, 1 Apr 2024 18:00:00 GMT",
    "End": "Mon, 1 Apr 2024 20:00:00 GMT",
    "Recurrence":{
        "Pattern": {
            "Type": "Weekly",
            "Interval": 1,
            "DaysOfWeek": ["Monday", "Tuesday"]
        },
        "Range": {
            "Type": "Numbered",
            "NumberOfOccurrences": 3
        }
    }
    

Чтобы создать правило повторения, необходимо указать оба Pattern и Range. Любой тип шаблона может работать с любым типом диапазона.

Дополнительно: смещение часового пояса Start свойства применяется к параметрам повторения.

Microsoft.Targeting

Этот фильтр предоставляет возможность включить функцию для целевой аудитории. Подробное объяснение целевого назначения объясняется в приведенном ниже разделе о целевом объекте . Параметры фильтра включают Audience объект, описывающий пользователей, групп, исключенных пользователей и групп, а также процент базы пользователей по умолчанию, который должен иметь доступ к этой функции. Каждый объект группы, указанный в Groups разделе, также должен указывать, какой процент членов группы должен иметь доступ. Если пользователь указан в Exclusion разделе, либо непосредственно, либо если пользователь находится в исключенной группе, функция отключена. В противном случае, если пользователь указан в Users разделе напрямую, или если пользователь находится в процентах от любого из развернутых групп или если пользователь попадает в процент развертывания по умолчанию, то этот пользователь будет включен.

"EnhancedPipeline": {
    "EnabledFor": [
        {
            "Name": "Microsoft.Targeting",
            "Parameters": {
                "Audience": {
                    "Users": [
                        "Jeff",
                        "Alicia"
                    ],
                    "Groups": [
                        {
                            "Name": "Ring0",
                            "RolloutPercentage": 100
                        },
                        {
                            "Name": "Ring1",
                            "RolloutPercentage": 50
                        }
                    ],
                    "DefaultRolloutPercentage": 20,
                    "Exclusion": {
                        "Users": [
                            "Ross"
                        ],
                        "Groups": [
                            "Ring2"
                        ]
                    }
                }
            }
        }
    ]
}

Пространства имен фильтра компонентов

Все встроенные псевдонимы фильтра функций находятся в Microsoft пространстве имен фильтра компонентов. Это позволяет предотвратить конфликты с другими фильтрами функций, которые могут использовать тот же псевдоним. Сегменты пространства имен фильтра функций разделяются символом ". Фильтр признаков можно ссылаться на его полный псевдоним, например Microsoft.Percentage или последним сегментом, который в случае Microsoft.Percentage имеет значение Percentage.

Таргетинг

Цель — это стратегия управления функциями, которая позволяет разработчикам постепенно развертывать новые функции в своей пользовательской базе. Стратегия основана на концепции целевой аудитории для набора пользователей, известных как целевая аудитория. Аудитория состоит из конкретных пользователей, групп, исключенных пользователей и групп, и указанного процента всей базы пользователей. Группы, включенные в аудиторию, могут быть разбиты дальше на проценты их общих членов.

Ниже приведен пример прогрессивного развертывания для новой функции Beta:

  1. Отдельные пользователи Джефф и Алисия получают доступ к бета-версии
  2. Другой пользователь, Mark, просит принять участие и включен.
  3. Двадцать процентов группы, известной как "Ring1", включены в бета-версию.
  4. Число пользователей Ring1, включенных в бета-версию, составляет до 100 процентов.
  5. Пять процентов пользовательской базы включены в бета-версию.
  6. Процент развертывания вырос до 100 процентов, и функция полностью развернута.

Эта стратегия развертывания компонента встроена в библиотеку с помощью включенного фильтра компонентов Microsoft.Targeting .

Назначение в веб-приложении

Пример веб-приложения, использующего фильтр функций целевого объекта, доступен в примере проекта FeatureFlagDemo .

Чтобы начать использование TargetingFilter приложения, его необходимо добавить в коллекцию служб приложения так же, как и любой другой фильтр компонентов. В отличие от других встроенных фильтров, служба TargetingFilter использует другую службу для добавления в коллекцию служб приложения. Эта служба является .ITargetingContextAccessor

Тип реализации, используемый для ITargetingContextAccessor службы, должен быть реализован приложением, использующим целевой фильтр. Ниже приведен пример настройки управления функциями в веб-приложении для использования TargetingFilter с реализацией вызываемой ITargetingContextAccessor HttpContextTargetingContextAccessorфункции.

services.AddFeatureManagement()
        .WithTargeting<HttpContextTargetingContextAccessor>();

Целевой метод доступа к контексту и TargetingFilter регистрируется путем вызова IFeatureManagementBuilderWithTargeting<T> .

ITargetingContextAccessor

Для использования TargetingFilter в веб-приложении требуется реализация ITargetingContextAccessor . Это связано с тем, что при выполнении целевой оценки требуются такие сведения, как то, что пользователь в настоящее время оценивает. Эта информация называется контекстом целевого объекта. Различные веб-приложения могут извлекать эти сведения из разных мест. Некоторые распространенные примеры того, где приложение может извлечь контекст целевого объекта, — это контекст HTTP запроса или база данных.

Пример, который извлекает сведения о контексте целевого объекта из контекста HTTP приложения, включен в пример проекта FeatureFlagDemo . Этот метод зависит от использования IHttpContextAccessor, который обсуждается здесь.

Назначение в консольном приложении

Фильтр целевых объектов зависит от контекста целевого объекта, чтобы оценить, следует ли включить функцию. Этот контекст целевого объекта содержит такие сведения, как оценка пользователя и группы пользователей. В консольных приложениях обычно нет контекста окружающей среды для потока этих сведений в целевой фильтр, поэтому он должен передаваться непосредственно при FeatureManager.IsEnabledAsync вызове. Это поддерживается с помощью .ContextualTargetingFilter Приложения, которые должны с плавать контекстом целевого объекта в диспетчере функций, должны использовать это вместо TargetingFilter.

Так как ContextualTargetingFilter это IContextualTargetingFilter<ITargetingContext>реализация ITargetingContext должна передаваться IFeatureManager.IsEnabledAsync в нее, чтобы она могла оценивать и включать функцию.

IFeatureManager fm;
…
// userId and groups defined somewhere earlier in application
TargetingContext targetingContext = new TargetingContext
{
   UserId = userId,
   Groups = groups
};

await fm.IsEnabledAsync(featureName, targetingContext);

По-прежнему ContextualTargetingFilter используется псевдоним фильтра компонентов Microsoft.Targeting, поэтому конфигурация этого фильтра согласована с тем, что упоминалось в этом разделе.

Пример использования консольного ContextualTargetingFilter приложения доступен в примере TargetingConsoleApp .

Параметры целевой оценки

Параметры доступны для настройки того, как выполняется оценка целевых объектов во всех функциях. Эти параметры можно настроить при настройке управления функциями.

services.Configure<TargetingEvaluationOptions>(options =>
{
    options.IgnoreCase = true;
});

Исключение целевого объекта

При определении аудитории пользователи и группы могут быть исключены из аудитории. Это полезно, если функция развертывается в группе пользователей, но из развертывания необходимо исключить несколько пользователей или групп. Исключение определяется путем добавления списка пользователей и групп в Exclusion свойство аудитории.

"Audience": {
    "Users": [
        "Jeff",
        "Alicia"
    ],
    "Groups": [
        {
            "Name": "Ring0",
            "RolloutPercentage": 100
        }
    ],
    "DefaultRolloutPercentage": 0
    "Exclusion": {
        "Users": [
            "Mark"
        ]
    }
}

В приведенном выше примере функция включена для пользователей с именем Jeff и Alicia. Он также включен для пользователей в группе с именем Ring0. Однако если пользователь называется Mark, функция отключена независимо от того, находятся ли они в группе Ring0 или нет. Исключения занимают приоритет от остальной части фильтра целевого объекта.

Варианты

При добавлении новых функций в приложение может возникнуть время, когда функция имеет несколько различных предлагаемых вариантов проектирования. Общее решение для принятия решения о проектировании — это некоторая форма тестирования A/B, которая включает в себя предоставление другой версии функции различным сегментам пользовательской базы и выбор версии на основе взаимодействия с пользователем. В этой библиотеке эта функция включена путем представления различных конфигураций компонента с вариантами.

Варианты позволяют флагу функции стать более простым флагом включения и выключения. Вариант представляет значение флага компонента, которое может быть строкой, числом, логическим или даже объектом конфигурации. Флаг компонента, объявляющий варианты, должен определять, в каких обстоятельствах следует использовать каждый вариант, который подробно рассматривается в разделе "Выделение вариантов ".

public class Variant
{
    /// <summary>
    /// The name of the variant.
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// The configuration of the variant.
    /// </summary>
    public IConfigurationSection Configuration { get; set; }
}

Получение вариантов

Для каждой функции можно получить вариант с помощью IVariantFeatureManagerGetVariantAsync метода.

…
IVariantFeatureManager featureManager;
…
Variant variant = await featureManager.GetVariantAsync(MyFeatureFlags.FeatureU, CancellationToken.None);

IConfigurationSection variantConfiguration = variant.Configuration;

// Do something with the resulting variant and its configuration

После получения варианта конфигурация варианта может использоваться непосредственно в качестве IConfigurationSection свойства варианта Configuration . Другим вариантом является привязка конфигурации к объекту с помощью. Шаблон привязки конфигурации NET.

IConfigurationSection variantConfiguration = variant.Configuration;

MyFeatureSettings settings = new MyFeatureSettings();

variantConfiguration.Bind(settings);

Возвращаемый вариант зависит от вычисляемого пользователя, и эта информация получается из экземпляра TargetingContext. Этот контекст может передаваться при вызове GetVariantAsync или автоматически извлекаться из реализации ITargetingContextAccessor , если он зарегистрирован.

Объявление флага компонента Variant

По сравнению с обычными флагами функций флаги вариантов имеют два дополнительных свойства: variants и allocation. Это variants массив, содержащий варианты, определенные для этой функции. Свойство allocation определяет, как эти варианты должны быть выделены для функции. Как и объявление обычных флагов функций, можно настроить флаги вариантных функций в json-файле. Ниже приведен пример флага функции variant.

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "MyVariantFeatureFlag",
                "enabled": true,
                "allocation": {
                    "default_when_enabled": "Small",
                    "group": [
                        {
                            "variant": "Big",
                            "groups": [
                                "Ring1"
                            ]
                        }
                    ]
                },
                "variants": [
                    { 
                        "name": "Big"
                    },  
                    { 
                        "name": "Small"
                    } 
                ]
            }
        ]
    }
}

Определение вариантов

Каждый вариант имеет два свойства: имя и конфигурацию. Имя используется для ссылки на конкретный вариант, а конфигурация — это значение этого варианта. Конфигурацию можно задать с помощью либо configuration_reference configuration_value свойств. configuration_reference — это строковый путь, ссылающийся на раздел текущей конфигурации, содержащей объявление флага компонента. configuration_value — это встроенная конфигурация, которая может быть строкой, номером, логическим объектом или объектом конфигурации. Если указаны оба значения, используется configuration_value. Если ни указано, свойство возвращаемого варианта Configuration будет иметь значение NULL.

Список всех возможных вариантов определяется для каждой функции в свойстве variants .

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "MyVariantFeatureFlag",
                "variants": [
                    { 
                        "name": "Big", 
                        "configuration_reference": "ShoppingCart:Big" 
                    },  
                    { 
                        "name": "Small", 
                        "configuration_value": {
                            "Size": 300
                        }
                    } 
                ]
            }
        ]
    },

    "ShoppingCart": {
        "Big": {
            "Size": 600,
            "Color": "green"
        },
        "Small": {
            "Size": 300,
            "Color": "gray"
        }
    }
}

Выделение вариантов

Процесс выделения вариантов компонента определяется свойством allocation функции.

"allocation": { 
    "default_when_enabled": "Small", 
    "default_when_disabled": "Small",  
    "user": [ 
        { 
            "variant": "Big", 
            "users": [ 
                "Marsha" 
            ] 
        } 
    ], 
    "group": [ 
        { 
            "variant": "Big", 
            "groups": [ 
                "Ring1" 
            ] 
        } 
    ],
    "percentile": [ 
        { 
            "variant": "Big", 
            "from": 0, 
            "to": 10 
        } 
    ], 
    "seed": "13973240" 
},
"variants": [
    { 
        "name": "Big", 
        "configuration_reference": "ShoppingCart:Big" 
    },  
    { 
        "name": "Small", 
        "configuration_value": "300px"
    } 
]

Параметр allocation компонента имеет следующие свойства:

Свойство Description
default_when_disabled Указывает, какой вариант следует использовать при запросе варианта во время отключения функции.
default_when_enabled Указывает, какой вариант следует использовать при запросе варианта, если компонент считается включенным, и другой вариант не был назначен пользователю.
user Задает вариант и список пользователей, которым должен быть назначен этот вариант.
group Задает вариант и список групп. Вариант будет назначен, если пользователь находится по крайней мере в одной из групп.
percentile Задает вариант и процентный диапазон, в котором вычисляемый процент пользователя должен соответствовать назначенному варианту.
seed Значение, на котором основаны процентные расчеты percentile . Процентное вычисление для конкретного пользователя будет одинаковым для всех функций, если используется одно и то же seed значение. Если значение не seed указано, то начальное значение по умолчанию создается на основе имени функции.

В приведенном выше примере, если функция не включена, диспетчер функций назначит вариант, помеченный текущим default_when_disabled пользователем, что в Small данном случае.

Если функция включена, диспетчер функций проверит usergroupи percentile выделения в этом порядке, чтобы назначить вариант. В этом примере, если вычисляемый пользователь называется Marsha, в группе с именем Ring1или пользователь попадает между 0 и 10-м процентилем, то указанный вариант назначается пользователю. В этом случае все эти варианты возвращаются Big . Если ни одно из этих выделений не соответствует, пользователю назначается default_when_enabled вариант.Small

Логика выделения аналогична фильтру функций Microsoft.Targeting , но существуют некоторые параметры, которые присутствуют в целевом расположении, которые не находятся в выделении, и наоборот. Результаты целевого и распределения не связаны.

Примечание.

Чтобы разрешить выделение вариантов функций, необходимо зарегистрировать ITargetingContextAccessor. Это можно сделать, вызвав WithTargeting<T> метод.

Переопределение состояния с включенным вариантом

Варианты можно использовать для переопределения состояния включенного флага компонента. Это дает возможность расширить оценку флага функции. Если вызывающий объект проверяет, включен ли флаг с вариантами, диспетчер функций проверяет, настроен ли вариант, назначенный текущему пользователю, для переопределения результата. Это делается с помощью необязательного свойства status_overridevariant. По умолчанию это свойство имеет значение None, что означает, что вариант не влияет на то, включен или отключен флаг. Параметр status_override позволяет варианту Enabled при выборе переопределить флаг, который необходимо включить. Параметр status_override для Disabled получения противоположной функциональности, поэтому отключение флага при выборе варианта. Невозможно переопределить функцию enabled с состоянием false переопределения.

Если вы используете флаг функции с двоичными вариантами, status_override это свойство может оказаться очень полезным. Он позволяет продолжать использовать API, такие как IsEnabledAsync и FeatureGateAttribute в приложении, все время воспользоваться новыми функциями, которые приходят с вариантами, такими как выделение процентиля и начальное значение.

{
    "id": "MyVariantFeatureFlag",
    "enabled": true,
    "allocation": {
        "percentile": [
            {
                "variant": "On",
                "from": 10,
                "to": 20
            }
        ],
        "default_when_enabled":  "Off",
        "seed": "Enhanced-Feature-Group"
    },
    "variants": [
        {
            "name": "On"
        },
        {
            "name": "Off",
            "status_override": "Disabled"
        }
    ]
}

В приведенном выше примере функция всегда включена. Если текущий пользователь находится в вычисляемом диапазоне процентиля от 10 до 20, On возвращается вариант. Off В противном случае возвращается вариант и, так как status_override равенDisabled, функция теперь будет считаться отключенной.

Варианты внедрения зависимостей

Флаги функций variant можно использовать в сочетании с внедрением зависимостей для поверхности различных реализаций службы для разных пользователей. Это достигается с помощью IVariantServiceProvider<TService> интерфейса.

IVariantServiceProvider<IAlgorithm> algorithmServiceProvider;
...

IAlgorithm forecastAlgorithm = await algorithmServiceProvider.GetServiceAsync(cancellationToken); 

В приведенном выше IVariantServiceProvider<IAlgorithm> фрагменте извлекается реализация IAlgorithm из контейнера внедрения зависимостей. Выбранная реализация зависит от:

  • Флаг компонента, в который IAlgorithm была зарегистрирована служба.
  • Выделенный вариант для этой функции.

Приложение IVariantServiceProvider<T> становится доступным путем вызова IFeatureManagementBuilder.WithVariantService<T>(string featureName). Пример см. ниже.

services.AddFeatureManagement() 
        .WithVariantService<IAlgorithm>("ForecastAlgorithm");

Приведенный выше вызов предоставляется IVariantServiceProvider<IAlgorithm> в коллекции служб. IAlgorithm Реализации должны быть добавлены отдельно с помощью метода добавления, напримерservices.AddSingleton<IAlgorithm, SomeImplementation>(). Реализация IAlgorithm этого IVariantServiceProvider метода зависит от флага ForecastAlgorithm функции variant. Если реализация IAlgorithm не добавлена в коллекцию служб, IVariantServiceProvider<IAlgorithm>.GetServiceAsync() возвращает задачу с пустым результатом.

{
    // The example variant feature flag
    "id": "ForecastAlgorithm",
    "enabled": true,
    "variants": [
        { 
            "Name": "AlgorithmBeta" 
        },
        ...
    ] 
}

Атрибут псевдонима службы variant

[VariantServiceAlias("Beta")]
public class AlgorithmBeta : IAlgorithm
{
    ...
}

Поставщик услуг variant будет использовать имена типов реализаций для сопоставления выделенного варианта. Если служба вариантов украшена VariantServiceAliasAttributeатрибутом, имя, объявленное в этом атрибуте, должно использоваться в конфигурации для ссылки на эту службу вариантов.

Телеметрия

При развертывании изменения флага функции часто важно проанализировать его влияние на приложение. Например, вот несколько вопросов, которые могут возникнуть:

  • Включены ли флаги и отключены ли они должным образом?
  • Получают ли целевые пользователи доступ к определенной функции должным образом?
  • Какой вариант отображает конкретный пользователь?

Эти типы вопросов можно ответить с помощью выбросов и анализа событий оценки флага признаков. Эта библиотека поддерживает выдачу этих событий с помощью издателей телеметрии. Один или несколько издателей телеметрии могут быть зарегистрированы для публикации событий при оценке флагов компонентов.

Включение телеметрии

По умолчанию флаги компонентов не создают данные телеметрии. Чтобы опубликовать данные телеметрии для заданного флага компонента, флаг ДОЛЖЕН объявить, что он включен для выбросов телеметрии.

Для флагов компонентов, определенных в appsettings.json, это делается с помощью telemetry свойства.

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "MyFeatureFlag",
                "enabled": true,
                "telemetry": {
                    "enabled": true
                }
            }
        ]
    }
}

Приведенный выше фрагмент кода приложения определяет флаг компонента, который MyFeatureFlag включен для телеметрии. Это указывает telemetry объект, который задает enabled значение true. Значение enabled свойства должно быть true для публикации телеметрии для флага.

Раздел telemetry флага компонента имеет следующие свойства:

Свойство Description
enabled Указывает, следует ли публиковать данные телеметрии для флага компонента.
metadata Коллекция пар "ключ-значение", моделироваемая как словарь, которая может использоваться для присоединения пользовательских метаданных о флаге компонента для оценки событий.

Пользовательские издатели телеметрии

Пользовательская обработка телеметрии флага компонента возможна путем реализации ITelemetryPublisher и регистрации его в диспетчере функций. При оценке флага компонента с включенной телеметрией зарегистрированный издатель телеметрии получает возможность опубликовать соответствующее событие оценки.

public interface ITelemetryPublisher
{
    ValueTask PublishEvent(EvaluationEvent evaluationEvent, CancellationToken cancellationToken);
}

Тип EvaluationEvent можно найти здесь для справки.

Регистрация издателей телеметрии выполняется при вызове AddFeatureManagement(). Ниже приведен пример настройки управления функциями для отправки данных телеметрии с реализацией вызываемой ITelemetryPublisher MyTelemetryPublisherфункции.

builder.services
    .AddFeatureManagement()
    .AddTelemetryPublisher<MyTelemetryPublisher>();

Издатель телеметрии Application Insights

Пакет Microsoft.FeatureManagement.Telemetry.ApplicationInsights предоставляет встроенную реализацию издателя телеметрии, которая отправляет данные оценки флага компонента в Application Insights. Чтобы воспользоваться этим, добавьте ссылку на пакет и зарегистрируйте издателя телеметрии Application Insights, как показано ниже.

builder.services
    .AddFeatureManagement()
    .AddTelemetryPublisher<ApplicationInsightsTelemetryPublisher>();

Примечание.

Базовый Microsoft.FeatureManagement пакет не включает этот издатель телеметрии.

Пример его использования можно найти в примере EvaluationDataToApplicationInsights .

Необходимые условия

Этот издатель телеметрии зависит от уже настроенной и зарегистрированной в качестве службы приложений Application Insights. Например, это сделано в примере приложения.

Кэширование

Состояние компонента предоставляется IConfiguration системой. Ожидается, что любое кэширование и динамическое обновление обрабатывается поставщиками конфигурации. Диспетчер функций запрашивает IConfiguration последнее значение состояния компонента всякий раз, когда функция будет включена.

Снимок

Существуют сценарии, которые требуют, чтобы состояние функции оставалось согласованным в течение времени существования запроса. Значения, IFeatureManager возвращаемые стандартом, могут измениться, если IConfiguration источник, из который он извлекается, обновляется во время запроса. Это можно предотвратить с помощью IFeatureManagerSnapshot. IFeatureManagerSnapshot можно получить таким же образом, как IFeatureManagerи . IFeatureManagerSnapshot реализует интерфейс IFeatureManager, но кэширует первое вычисляемое состояние компонента во время запроса и возвращает то же состояние функции во время его существования.

Поставщики пользовательских функций

Реализация пользовательского поставщика функций позволяет разработчикам извлекать флаги функций из источников, таких как база данных или служба управления функциями. Включенный поставщик функций, используемый по умолчанию, извлекает флаги компонентов из системы конфигурации .NET Core. Это позволяет определять функции в файле appsettings.json или в поставщиках конфигурации, таких как Конфигурация приложений Azure. Это поведение можно заменить, чтобы обеспечить полный контроль над тем, откуда считываются определения компонентов.

Чтобы настроить загрузку определений компонентов, необходимо реализовать IFeatureDefinitionProvider интерфейс.

public interface IFeatureDefinitionProvider
{
    Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName);

    IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync();
}

Чтобы использовать реализацию IFeatureDefinitionProvider, ее необходимо добавить в коллекцию служб перед добавлением управления функциями. В следующем примере добавляется реализация IFeatureDefinitionProvider именованных InMemoryFeatureDefinitionProvider.

services.AddSingleton<IFeatureDefinitionProvider, InMemoryFeatureDefinitionProvider>()
        .AddFeatureManagement()

Следующие шаги

Чтобы узнать, как использовать флаги функций в приложениях, перейдите к следующим кратким руководствам.

Чтобы узнать, как использовать фильтры функций, перейдите к следующим руководствам.

Чтобы узнать, как выполнять эксперименты с флагами функций variant, перейдите к следующему руководству.