11

私がやろうとしていること: Azure App Configuration でセンチネル キーを使用して .net core 2.1 mvc Web アプリケーションを使用して Azure App Configuration をセットアップしようとしています。目的は、Azure でキーを変更できるようにすることです。センチネル値が変更されるまで、アプリで更新されます。理論的には、これにより構成を安全にホットスワップできるはずです。

私の問題は次のとおりです。 これを行うと、IWebHostBuilder でセンチネルを監視するために使用できる WatchAndReloadAll() メソッドがありません。

背景情報と試したこと: 先週、サンディエゴの VS Live に参加し、Azure App Configuration のデモを見ました。アプリケーションを実装するときに構成値を更新する際に問題が発生したため、これを行う方法を説明するこのデモも参照しました。関連セクションは約 10 分です。ただし、そのメソッドは IWebHostBuilder では使用できないようです。

私が参照 しているドキュメント: 公式ドキュメントには、このメソッドへの参照はありません。doc quickstart .net coreおよびdoc dynamic configuration .net coreを参照してください。

私の環境: Microsoft.Azure.AppConfiguration.AspNetCore 2.0.0-preview-010060003-1250 の最新のプレビュー nuget パッケージを使用して、Visual Studio Enterprise 2019 から実行されているドット ネット コア 2.1 を使用

私のコード: デモでは、次のように CreateWebHostBuilder(string[] args) メソッドを介して IWebHostBuilder を作成しました。

public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
    return WebHost.CreateDefaultBuilder(args)
    .ConfigureAppConfiguration((hostingContext, config) =>
    {
        var settings = config.Build();
        config.AddAzureAppConfiguration(options =>
        {
            options.Connect(settings["ConnectionStrings:AzureConfiguration"])
            .Use(keyFilter: "TestApp:*")
            .WatchAndReloadAll(key: "TestApp:Sentinel", pollInterval: TimeSpan.FromSeconds(5));
        }); 
    })
    .UseStartup<Startup>();
}

現在のドキュメントを使用して、この方法でも試しました。

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
    .ConfigureAppConfiguration((hostingContext, config) =>
    {
        var settings = config.Build();

        config.AddAzureAppConfiguration(options =>
        {
            // fetch connection string from local config. Could use KeyVault, or Secrets as well.
            options.Connect(settings["ConnectionStrings:AzureConfiguration"])
            // filter configs so we are only searching against configs that meet this pattern
            .Use(keyFilter: "WebApp:*")
            .ConfigureRefresh(refreshOptions =>
            { 
                // In theory, when this value changes, on the next refresh operation, the config will update all modified configs since it was last refreshed.
                refreshOptions.Register("WebApp:Sentinel", true);
                refreshOptions.Register("WebApp:Settings:BackgroundColor", false);
                refreshOptions.Register("WebApp:Settings:FontColor", false);
                refreshOptions.Register("WebApp:Settings:FontSize", false);
                refreshOptions.Register("WebApp:Settings:Message", false);
            });
        });
    })
    .UseStartup<Startup>();

次に、私のスタートアップ クラスで:

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.Configure<Settings>(Configuration.GetSection("WebApp:Settings"));
    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseAzureAppConfiguration();
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

そして最後に私の設定構成モデル:

public class Settings
{
    public string BackgroundColor { get; set; }
    public long FontSize { get; set; }
    public string FontColor { get; set; }
    public string Message { get; set; }
}

ここで、コントローラーでこれらの設定を取得し、ビュー バッグにスローしてビューに表示します。

public class HomeController : Controller
{
    private readonly Settings _Settings;

    public HomeController(IOptionsSnapshot<Settings> settings)
    {
        _Settings = settings.Value;
    }

    public IActionResult Index()
    {
        ViewData["BackgroundColor"] = _Settings.BackgroundColor;
        ViewData["FontSize"] = _Settings.FontSize;
        ViewData["FontColor"] = _Settings.FontColor;
        ViewData["Message"] = _Settings.Message;

        return View();
    }
}

変更を表示する簡単なビュー:

<!DOCTYPE html>
<html lang="en">
<style>
    body {
        background-color: @ViewData["BackgroundColor"]
    }
    h1 {
        color: @ViewData["FontColor"];
        font-size: @ViewData["FontSize"];
    }
</style>
<head>
    <title>Index View</title>
</head>
<body>
    <h1>@ViewData["Message"]</h1>
</body>
</html>

初めて構成をプルダウンすることはできますが、更新機能はまったく機能していないようです。

最後の例では、センチネルが新しい値に設定されたときに構成が更新されるか、少なくとも変更されてから 30 秒後に値が更新されることを期待していました。値が更新されるのを待つ時間はなく、アプリを完全にシャットダウンして再起動するだけで、新しい構成が読み込まれます。

更新: app.UseAzureAppConfiguration(); の追加 起動時の構成メソッドで、構成のキャッシュに明示的なタイムアウトを設定すると、更新メソッドが一定時間後に更新されるように修正されましたが、センチネル機能は引き続き機能せず、更新メソッドの updateAll フラグも機能しません。

4

1 に答える 1