Detekce změn pomocí tokenů změn v ASP.NET Core
Poznámka:
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.
Upozorňující
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v tématu .NET a .NET Core Zásady podpory. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.
Důležité
Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Aktuální verzi najdete ve verzi .NET 8 tohoto článku.
Token změn je univerzální stavební blok nízké úrovně, který se používá ke sledování změn stavu.
Zobrazení nebo stažení ukázkového kódu (postup stažení)
IChangeToken – rozhraní
IChangeToken šíří oznámení, že došlo ke změně. IChangeToken
se nachází v Microsoft.Extensions.Primitives oboru názvů. Balíček NuGet Microsoft.Extensions.Primitives se implicitně poskytuje aplikacím ASP.NET Core.
IChangeToken
má dvě vlastnosti:
- ActiveChangeCallbacks označuje, jestli token proaktivně vyvolává zpětná volání. Pokud
ActiveChangedCallbacks
je nastavená hodnotafalse
, zpětné volání se nikdy nevolá a aplikace se musí dotazovatHasChanged
na změny. Token je také možné nikdy zrušit, pokud nedojde k žádným změnám nebo se základní naslouchací proces změn odstraní nebo zakáže. - HasChanged obdrží hodnotu, která označuje, jestli došlo ke změně.
Rozhraní IChangeToken
zahrnuje RegisterChangeCallback(Action<Object>, Object), která registruje zpětné volání, které je vyvoláno při změně tokenu. HasChanged
musí být nastavena před vyvolání zpětného volání.
ChangeToken – třída
ChangeToken je statická třída používaná k šíření oznámení, že došlo ke změně. ChangeToken
se nachází v Microsoft.Extensions.Primitives oboru názvů. Balíček NuGet Microsoft.Extensions.Primitives se implicitně poskytuje aplikacím ASP.NET Core.
Metoda ChangeToken.OnChange(Func<IChangeToken>, Action) zaregistruje Action
volání při každé změně tokenu:
Func<IChangeToken>
vytvoří token.Action
je volána při změně tokenu.
ChangeToken.OnChange <TState>(Func<IChangeToken>, Action<TState, TState>) přetížení přebírá další TState
parametr, který je předán do příjemce Action
tokenu .
OnChange
vrátí hodnotu IDisposable. Volání Dispose zastaví naslouchání tokenu dalším změnám a uvolní prostředky tokenu.
Příklad použití tokenů změn v ASP.NET Core
Tokeny změn se používají v hlavních oblastech ASP.NET Core k monitorování změn objektů:
- Pro monitorování změn souborů IFileProviderWatch metoda vytvoří
IChangeToken
pro zadané soubory nebo složku, které se mají sledovat. IChangeToken
tokeny lze přidat do položek mezipaměti, aby se při změně aktivovaly vyřazení mezipaměti.- U
TOptions
změn má výchozí OptionsMonitor<TOptions> implementace IOptionsMonitor<TOptions> přetížení, které přijímá jednu nebo více IOptionsChangeTokenSource<TOptions> instancí. Každá instance vrátí metoduIChangeToken
pro registraci zpětného volání oznámení o změnách pro sledování změn možností.
Monitorování změn konfigurace
Ve výchozím nastavení ASP.NET šablony Core používají konfigurační soubory JSON (appsettings.json
appsettings.Development.json
aappsettings.Production.json
) k načtení nastavení konfigurace aplikace.
Tyto soubory se konfigurují pomocí metody ConfigurationBuilder rozšíření AddJsonFile(IConfigurationBuilder, String, Boolean, Boolean), která přijímá reloadOnChange
parametr. reloadOnChange
označuje, jestli by se při změně souboru měla znovu načíst konfigurace. Toto nastavení se zobrazí v Host metodě CreateDefaultBuilderusnadnění:
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true,
reloadOnChange: true);
Konfigurace založená na souborech je reprezentována .FileConfigurationSource FileConfigurationSource
používá IFileProvider k monitorování souborů.
Ve výchozím nastavení IFileMonitor
je poskytována nástrojem PhysicalFileProvider, který používá FileSystemWatcher ke sledování změn konfiguračního souboru.
Ukázková aplikace ukazuje dvě implementace pro monitorování změn konfigurace. Pokud se některý ze appsettings
souborů změní, spustí se v obou implementacích monitorování souborů vlastní kód – ukázková aplikace zapíše zprávu do konzoly.
Konfigurační soubor FileSystemWatcher
může aktivovat více zpětných volání tokenů pro změnu jednoho konfiguračního souboru. Aby se zajistilo, že se vlastní kód spustí jenom jednou, když se aktivuje více zpětných volání tokenů, zkontroluje implementace ukázky hodnoty hash souboru. Ukázka používá hashování souborů SHA1. Opakování se implementuje s exponenciálním zpětným vypnutím.
Utilities/Utilities.cs
:
public static byte[] ComputeHash(string filePath)
{
var runCount = 1;
while(runCount < 4)
{
try
{
if (File.Exists(filePath))
{
using (var fs = File.OpenRead(filePath))
{
return System.Security.Cryptography.SHA1
.Create().ComputeHash(fs);
}
}
else
{
throw new FileNotFoundException();
}
}
catch (IOException ex)
{
if (runCount == 3)
{
throw;
}
Thread.Sleep(TimeSpan.FromSeconds(Math.Pow(2, runCount)));
runCount++;
}
}
return new byte[20];
}
Jednoduchý token změny spuštění
Zaregistrujte zpětné volání příjemce Action
tokenu pro oznámení o změnách do tokenu opětovného načtení konfigurace.
V Startup.Configure
:
ChangeToken.OnChange(
() => config.GetReloadToken(),
(state) => InvokeChanged(state),
env);
config.GetReloadToken()
poskytuje token. Zpětné volání je InvokeChanged
metoda:
private void InvokeChanged(IWebHostEnvironment env)
{
byte[] appsettingsHash = ComputeHash("appSettings.json");
byte[] appsettingsEnvHash =
ComputeHash($"appSettings.{env.EnvironmentName}.json");
if (!_appsettingsHash.SequenceEqual(appsettingsHash) ||
!_appsettingsEnvHash.SequenceEqual(appsettingsEnvHash))
{
_appsettingsHash = appsettingsHash;
_appsettingsEnvHash = appsettingsEnvHash;
WriteConsole("Configuration changed (Simple Startup Change Token)");
}
}
Zpětné state
volání se používá k předání IWebHostEnvironment
, což je užitečné pro určení správného appsettings
konfiguračního souboru pro monitorování (například appsettings.Development.json
v prostředí pro vývoj). Hodnoty hash souborů se používají k tomu, aby příkaz neběžil WriteConsole
několikrát kvůli více zpětným voláním tokenů, když se konfigurační soubor změnil pouze jednou.
Tento systém běží, pokud je aplikace spuštěná a uživatel ji nemůže zakázat.
Monitorování změn konfigurace jako služby
Ukázka implementuje:
- Základní monitorování spouštěcích tokenů
- Monitorování jako služba
- Mechanismus pro povolení a zakázání monitorování.
Ukázka vytvoří IConfigurationMonitor
rozhraní.
Extensions/ConfigurationMonitor.cs
:
public interface IConfigurationMonitor
{
bool MonitoringEnabled { get; set; }
string CurrentState { get; set; }
}
Konstruktor implementované třídy , ConfigurationMonitor
zaregistruje zpětné volání pro oznámení o změnách:
public ConfigurationMonitor(IConfiguration config, IWebHostEnvironment env)
{
_env = env;
ChangeToken.OnChange<IConfigurationMonitor>(
() => config.GetReloadToken(),
InvokeChanged,
this);
}
public bool MonitoringEnabled { get; set; } = false;
public string CurrentState { get; set; } = "Not monitoring";
config.GetReloadToken()
poskytuje token. InvokeChanged
je metoda zpětného volání. V state
této instanci je odkaz na IConfigurationMonitor
instanci, která se používá pro přístup ke stavu monitorování. Používají se dvě vlastnosti:
MonitoringEnabled
: Označuje, jestli má zpětné volání spustit vlastní kód.CurrentState
: Popisuje aktuální stav monitorování pro použití v uživatelském rozhraní.
Metoda InvokeChanged
se podobá dřívějšímu přístupu s tím rozdílem, že:
- Nespouští jeho kód, pokud
MonitoringEnabled
nenítrue
. - Vypíše aktuální výsledek
state
výstupuWriteConsole
.
private void InvokeChanged(IConfigurationMonitor state)
{
if (MonitoringEnabled)
{
byte[] appsettingsHash = ComputeHash("appSettings.json");
byte[] appsettingsEnvHash =
ComputeHash($"appSettings.{_env.EnvironmentName}.json");
if (!_appsettingsHash.SequenceEqual(appsettingsHash) ||
!_appsettingsEnvHash.SequenceEqual(appsettingsEnvHash))
{
string message = $"State updated at {DateTime.Now}";
_appsettingsHash = appsettingsHash;
_appsettingsEnvHash = appsettingsEnvHash;
WriteConsole("Configuration changed (ConfigurationMonitor Class) " +
$"{message}, state:{state.CurrentState}");
}
}
}
Instance ConfigurationMonitor
je zaregistrovaná jako služba v Startup.ConfigureServices
:
services.AddSingleton<IConfigurationMonitor, ConfigurationMonitor>();
Stránka Index nabízí uživateli kontrolu nad monitorováním konfigurace. Instance IConfigurationMonitor
je vložena IndexModel
do .
Pages/Index.cshtml.cs
:
public IndexModel(
IConfiguration config,
IConfigurationMonitor monitor,
FileService fileService)
{
_config = config;
_monitor = monitor;
_fileService = fileService;
}
Monitorování konfigurace (_monitor
) slouží k povolení nebo zakázání monitorování a nastavení aktuálního stavu pro zpětnou vazbu uživatelského rozhraní:
public IActionResult OnPostStartMonitoring()
{
_monitor.MonitoringEnabled = true;
_monitor.CurrentState = "Monitoring!";
return RedirectToPage();
}
public IActionResult OnPostStopMonitoring()
{
_monitor.MonitoringEnabled = false;
_monitor.CurrentState = "Not monitoring";
return RedirectToPage();
}
Po OnPostStartMonitoring
aktivaci se povolí monitorování a aktuální stav se vymaže. Když OnPostStopMonitoring
se aktivuje, monitorování je zakázané a stav je nastavený tak, aby odrážel, že se monitorování neprojevuje.
Tlačítka v uživatelském rozhraní umožňují a zakazují monitorování.
Pages/Index.cshtml
:
<button class="btn btn-success" asp-page-handler="StartMonitoring">
Start Monitoring
</button>
<button class="btn btn-danger" asp-page-handler="StopMonitoring">
Stop Monitoring
</button>
Monitorování změn souborů uložených v mezipaměti
Obsah souboru lze ukládat do mezipaměti pomocí .IMemoryCache Ukládání do mezipaměti je popsáno v tématu Mezipaměť v paměti . Bez provedení dalších kroků, jako je implementace popsaná níže, se zastaralá (zastaralá) data vrátí z mezipaměti, pokud se zdrojová data změní.
Například při obnovování období vypršení platnosti se stavem zdrojového souboru uloženého v mezipaměti vede k zastaralým datům souborů uložených v mezipaměti. Každá žádost o data prodlužuje dobu vypršení platnosti, ale soubor se nikdy znovu nenačte do mezipaměti. Na všechny funkce aplikace, které používají obsah uložený v mezipaměti souboru, se můžou dostat zastaralý obsah.
Použití tokenů změn ve scénáři ukládání souborů do mezipaměti brání přítomnosti zastaralého obsahu souboru v mezipaměti. Ukázková aplikace demonstruje implementaci přístupu.
Ukázka používá GetFileContent
:
- Vrátí obsah souboru.
- Implementujte algoritmus opakování s exponenciálním zpětným vypnutím, aby zahrnoval případy, kdy problém s přístupem k souboru dočasně zpožďuje čtení obsahu souboru.
Utilities/Utilities.cs
:
public async static Task<string> GetFileContent(string filePath)
{
var runCount = 1;
while(runCount < 4)
{
try
{
if (File.Exists(filePath))
{
using (var fileStreamReader = File.OpenText(filePath))
{
return await fileStreamReader.ReadToEndAsync();
}
}
else
{
throw new FileNotFoundException();
}
}
catch (IOException ex)
{
if (runCount == 3)
{
throw;
}
Thread.Sleep(TimeSpan.FromSeconds(Math.Pow(2, runCount)));
runCount++;
}
}
return null;
}
Vytvoří se a FileService
zpracuje vyhledávání souborů uložených v mezipaměti. Volání GetFileContent
metody služby se pokusí získat obsah souboru z mezipaměti v paměti a vrátit ho volajícímu (Services/FileService.cs
).
Pokud se obsah uložený v mezipaměti pomocí klíče mezipaměti nenajde, provede se následující akce:
- Obsah souboru je získán pomocí
GetFileContent
. - Token změny se získá od zprostředkovatele souborů pomocí IFileProviders.Watch. Zpětné volání tokenu se aktivuje při změně souboru.
- Obsah souboru se ukládá do mezipaměti s posunutým obdobím vypršení platnosti . Token změny je připojen k MemoryCacheEntryExtensions.AddExpirationToken k vyřazení položky mezipaměti, pokud se soubor změní v mezipaměti.
V následujícím příkladu jsou soubory uložené v kořenovém adresáři obsahu aplikace. IWebHostEnvironment.ContentRootFileProvider
slouží k získání IFileProvider bodu na aplikaci IWebHostEnvironment.ContentRootPath
. Získá se filePath
pomocí IFileInfo.PhysicalPath.
public class FileService
{
private readonly IMemoryCache _cache;
private readonly IFileProvider _fileProvider;
private List<string> _tokens = new List<string>();
public FileService(IMemoryCache cache, IWebHostEnvironment env)
{
_cache = cache;
_fileProvider = env.ContentRootFileProvider;
}
public async Task<string> GetFileContents(string fileName)
{
var filePath = _fileProvider.GetFileInfo(fileName).PhysicalPath;
string fileContent;
// Try to obtain the file contents from the cache.
if (_cache.TryGetValue(filePath, out fileContent))
{
return fileContent;
}
// The cache doesn't have the entry, so obtain the file
// contents from the file itself.
fileContent = await GetFileContent(filePath);
if (fileContent != null)
{
// Obtain a change token from the file provider whose
// callback is triggered when the file is modified.
var changeToken = _fileProvider.Watch(fileName);
// Configure the cache entry options for a five minute
// sliding expiration and use the change token to
// expire the file in the cache if the file is
// modified.
var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromMinutes(5))
.AddExpirationToken(changeToken);
// Put the file contents into the cache.
_cache.Set(filePath, fileContent, cacheEntryOptions);
return fileContent;
}
return string.Empty;
}
}
Je FileService
zaregistrovaný v kontejneru služby spolu se službou ukládání do mezipaměti paměti.
V Startup.ConfigureServices
:
services.AddMemoryCache();
services.AddSingleton<FileService>();
Stránkový model načte obsah souboru pomocí služby.
V metodě indexové stránky OnGet
(Pages/Index.cshtml.cs
):
var fileContent = await _fileService.GetFileContents("poem.txt");
CompositeChangeToken – třída
Pro reprezentaci jedné nebo více IChangeToken
instancí v jednom objektu použijte CompositeChangeToken třídu.
var firstCancellationTokenSource = new CancellationTokenSource();
var secondCancellationTokenSource = new CancellationTokenSource();
var firstCancellationToken = firstCancellationTokenSource.Token;
var secondCancellationToken = secondCancellationTokenSource.Token;
var firstCancellationChangeToken = new CancellationChangeToken(firstCancellationToken);
var secondCancellationChangeToken = new CancellationChangeToken(secondCancellationToken);
var compositeChangeToken =
new CompositeChangeToken(
new List<IChangeToken>
{
firstCancellationChangeToken,
secondCancellationChangeToken
});
HasChanged
v sestavách true
složeného tokenu, pokud je true
nějaký reprezentovaný token HasChanged
. ActiveChangeCallbacks
v sestavách true
složeného tokenu, pokud je true
nějaký reprezentovaný token ActiveChangeCallbacks
. Pokud dojde k více souběžných událostem změn, vyvolá se jednou zpětné volání složené změny.
Token změn je univerzální stavební blok nízké úrovně, který se používá ke sledování změn stavu.
Zobrazení nebo stažení ukázkového kódu (postup stažení)
IChangeToken – rozhraní
IChangeToken šíří oznámení, že došlo ke změně. IChangeToken
se nachází v Microsoft.Extensions.Primitives oboru názvů. Pro aplikace, které nepoužívají metabalík Microsoft.AspNetCore.App, vytvořte odkaz na balíček NuGet Microsoft.Extensions.Primitives .
IChangeToken
má dvě vlastnosti:
- ActiveChangeCallbacks označuje, jestli token proaktivně vyvolává zpětná volání. Pokud
ActiveChangedCallbacks
je nastavená hodnotafalse
, zpětné volání se nikdy nevolá a aplikace se musí dotazovatHasChanged
na změny. Token je také možné nikdy zrušit, pokud nedojde k žádným změnám nebo se základní naslouchací proces změn odstraní nebo zakáže. - HasChanged obdrží hodnotu, která označuje, jestli došlo ke změně.
Rozhraní IChangeToken
zahrnuje RegisterChangeCallback(Action<Object>, Object), která registruje zpětné volání, které je vyvoláno při změně tokenu. HasChanged
musí být nastavena před vyvolání zpětného volání.
ChangeToken – třída
ChangeToken je statická třída používaná k šíření oznámení, že došlo ke změně. ChangeToken
se nachází v Microsoft.Extensions.Primitives oboru názvů. Pro aplikace, které nepoužívají metabalík Microsoft.AspNetCore.App, vytvořte odkaz na balíček NuGet Microsoft.Extensions.Primitives .
Metoda ChangeToken.OnChange(Func<IChangeToken>, Action) zaregistruje Action
volání při každé změně tokenu:
Func<IChangeToken>
vytvoří token.Action
je volána při změně tokenu.
ChangeToken.OnChange <TState>(Func<IChangeToken>, Action<TState, TState>) přetížení přebírá další TState
parametr, který je předán do příjemce Action
tokenu .
OnChange
vrátí hodnotu IDisposable. Volání Dispose zastaví naslouchání tokenu dalším změnám a uvolní prostředky tokenu.
Příklad použití tokenů změn v ASP.NET Core
Tokeny změn se používají v hlavních oblastech ASP.NET Core k monitorování změn objektů:
- Pro monitorování změn souborů IFileProviderWatch metoda vytvoří
IChangeToken
pro zadané soubory nebo složku, které se mají sledovat. IChangeToken
tokeny lze přidat do položek mezipaměti, aby se při změně aktivovaly vyřazení mezipaměti.- U
TOptions
změn má výchozí OptionsMonitor<TOptions> implementace IOptionsMonitor<TOptions> přetížení, které přijímá jednu nebo více IOptionsChangeTokenSource<TOptions> instancí. Každá instance vrátí metoduIChangeToken
pro registraci zpětného volání oznámení o změnách pro sledování změn možností.
Monitorování změn konfigurace
Ve výchozím nastavení ASP.NET šablony Core používají konfigurační soubory JSON (appsettings.json
appsettings.Development.json
aappsettings.Production.json
) k načtení nastavení konfigurace aplikace.
Tyto soubory se konfigurují pomocí metody ConfigurationBuilder rozšíření AddJsonFile(IConfigurationBuilder, String, Boolean, Boolean), která přijímá reloadOnChange
parametr. reloadOnChange
označuje, jestli by se při změně souboru měla znovu načíst konfigurace. Toto nastavení se zobrazí v WebHost metodě CreateDefaultBuilderusnadnění:
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true,
reloadOnChange: true);
Konfigurace založená na souborech je reprezentována .FileConfigurationSource FileConfigurationSource
používá IFileProvider k monitorování souborů.
Ve výchozím nastavení IFileMonitor
je poskytována nástrojem PhysicalFileProvider, který používá FileSystemWatcher ke sledování změn konfiguračního souboru.
Ukázková aplikace ukazuje dvě implementace pro monitorování změn konfigurace. Pokud se některý ze appsettings
souborů změní, spustí se v obou implementacích monitorování souborů vlastní kód – ukázková aplikace zapíše zprávu do konzoly.
Konfigurační soubor FileSystemWatcher
může aktivovat více zpětných volání tokenů pro změnu jednoho konfiguračního souboru. Aby se zajistilo, že se vlastní kód spustí jenom jednou, když se aktivuje více zpětných volání tokenů, zkontroluje implementace ukázky hodnoty hash souboru. Ukázka používá hashování souborů SHA1. Opakování se implementuje s exponenciálním zpětným vypnutím.
Utilities/Utilities.cs
:
public static byte[] ComputeHash(string filePath)
{
var runCount = 1;
while(runCount < 4)
{
try
{
if (File.Exists(filePath))
{
using (var fs = File.OpenRead(filePath))
{
return System.Security.Cryptography.SHA1
.Create().ComputeHash(fs);
}
}
else
{
throw new FileNotFoundException();
}
}
catch (IOException ex)
{
if (runCount == 3)
{
throw;
}
Thread.Sleep(TimeSpan.FromSeconds(Math.Pow(2, runCount)));
runCount++;
}
}
return new byte[20];
}
Jednoduchý token změny spuštění
Zaregistrujte zpětné volání příjemce Action
tokenu pro oznámení o změnách do tokenu opětovného načtení konfigurace.
V Startup.Configure
:
ChangeToken.OnChange(
() => config.GetReloadToken(),
(state) => InvokeChanged(state),
env);
config.GetReloadToken()
poskytuje token. Zpětné volání je InvokeChanged
metoda:
private void InvokeChanged(IHostingEnvironment env)
{
byte[] appsettingsHash = ComputeHash("appSettings.json");
byte[] appsettingsEnvHash =
ComputeHash($"appSettings.{env.EnvironmentName}.json");
if (!_appsettingsHash.SequenceEqual(appsettingsHash) ||
!_appsettingsEnvHash.SequenceEqual(appsettingsEnvHash))
{
_appsettingsHash = appsettingsHash;
_appsettingsEnvHash = appsettingsEnvHash;
WriteConsole("Configuration changed (Simple Startup Change Token)");
}
}
Zpětné state
volání se používá k předání IHostingEnvironment
, což je užitečné pro určení správného appsettings
konfiguračního souboru pro monitorování (například appsettings.Development.json
v prostředí pro vývoj). Hodnoty hash souborů se používají k tomu, aby příkaz neběžil WriteConsole
několikrát kvůli více zpětným voláním tokenů, když se konfigurační soubor změnil pouze jednou.
Tento systém běží, pokud je aplikace spuštěná a uživatel ji nemůže zakázat.
Monitorování změn konfigurace jako služby
Ukázka implementuje:
- Základní monitorování spouštěcích tokenů
- Monitorování jako služba
- Mechanismus pro povolení a zakázání monitorování.
Ukázka vytvoří IConfigurationMonitor
rozhraní.
Extensions/ConfigurationMonitor.cs
:
public interface IConfigurationMonitor
{
bool MonitoringEnabled { get; set; }
string CurrentState { get; set; }
}
Konstruktor implementované třídy , ConfigurationMonitor
zaregistruje zpětné volání pro oznámení o změnách:
public ConfigurationMonitor(IConfiguration config, IHostingEnvironment env)
{
_env = env;
ChangeToken.OnChange<IConfigurationMonitor>(
() => config.GetReloadToken(),
InvokeChanged,
this);
}
public bool MonitoringEnabled { get; set; } = false;
public string CurrentState { get; set; } = "Not monitoring";
config.GetReloadToken()
poskytuje token. InvokeChanged
je metoda zpětného volání. V state
této instanci je odkaz na IConfigurationMonitor
instanci, která se používá pro přístup ke stavu monitorování. Používají se dvě vlastnosti:
MonitoringEnabled
: Označuje, jestli má zpětné volání spustit vlastní kód.CurrentState
: Popisuje aktuální stav monitorování pro použití v uživatelském rozhraní.
Metoda InvokeChanged
se podobá dřívějšímu přístupu s tím rozdílem, že:
- Nespouští jeho kód, pokud
MonitoringEnabled
nenítrue
. - Vypíše aktuální výsledek
state
výstupuWriteConsole
.
private void InvokeChanged(IConfigurationMonitor state)
{
if (MonitoringEnabled)
{
byte[] appsettingsHash = ComputeHash("appSettings.json");
byte[] appsettingsEnvHash =
ComputeHash($"appSettings.{_env.EnvironmentName}.json");
if (!_appsettingsHash.SequenceEqual(appsettingsHash) ||
!_appsettingsEnvHash.SequenceEqual(appsettingsEnvHash))
{
string message = $"State updated at {DateTime.Now}";
_appsettingsHash = appsettingsHash;
_appsettingsEnvHash = appsettingsEnvHash;
WriteConsole("Configuration changed (ConfigurationMonitor Class) " +
$"{message}, state:{state.CurrentState}");
}
}
}
Instance ConfigurationMonitor
je zaregistrovaná jako služba v Startup.ConfigureServices
:
services.AddSingleton<IConfigurationMonitor, ConfigurationMonitor>();
Stránka Index nabízí uživateli kontrolu nad monitorováním konfigurace. Instance IConfigurationMonitor
je vložena IndexModel
do .
Pages/Index.cshtml.cs
:
public IndexModel(
IConfiguration config,
IConfigurationMonitor monitor,
FileService fileService)
{
_config = config;
_monitor = monitor;
_fileService = fileService;
}
Monitorování konfigurace (_monitor
) slouží k povolení nebo zakázání monitorování a nastavení aktuálního stavu pro zpětnou vazbu uživatelského rozhraní:
public IActionResult OnPostStartMonitoring()
{
_monitor.MonitoringEnabled = true;
_monitor.CurrentState = "Monitoring!";
return RedirectToPage();
}
public IActionResult OnPostStopMonitoring()
{
_monitor.MonitoringEnabled = false;
_monitor.CurrentState = "Not monitoring";
return RedirectToPage();
}
Po OnPostStartMonitoring
aktivaci se povolí monitorování a aktuální stav se vymaže. Když OnPostStopMonitoring
se aktivuje, monitorování je zakázané a stav je nastavený tak, aby odrážel, že se monitorování neprojevuje.
Tlačítka v uživatelském rozhraní umožňují a zakazují monitorování.
Pages/Index.cshtml
:
<button class="btn btn-success" asp-page-handler="StartMonitoring">
Start Monitoring
</button>
<button class="btn btn-danger" asp-page-handler="StopMonitoring">
Stop Monitoring
</button>
Monitorování změn souborů uložených v mezipaměti
Obsah souboru lze ukládat do mezipaměti pomocí .IMemoryCache Ukládání do mezipaměti je popsáno v tématu Mezipaměť v paměti . Bez provedení dalších kroků, jako je implementace popsaná níže, se zastaralá (zastaralá) data vrátí z mezipaměti, pokud se zdrojová data změní.
Například při obnovování období vypršení platnosti se stavem zdrojového souboru uloženého v mezipaměti vede k zastaralým datům souborů uložených v mezipaměti. Každá žádost o data prodlužuje dobu vypršení platnosti, ale soubor se nikdy znovu nenačte do mezipaměti. Na všechny funkce aplikace, které používají obsah uložený v mezipaměti souboru, se můžou dostat zastaralý obsah.
Použití tokenů změn ve scénáři ukládání souborů do mezipaměti brání přítomnosti zastaralého obsahu souboru v mezipaměti. Ukázková aplikace demonstruje implementaci přístupu.
Ukázka používá GetFileContent
:
- Vrátí obsah souboru.
- Implementujte algoritmus opakování s exponenciálním zpětným vypnutím, aby zahrnoval případy, kdy problém s přístupem k souboru dočasně zpožďuje čtení obsahu souboru.
Utilities/Utilities.cs
:
public async static Task<string> GetFileContent(string filePath)
{
var runCount = 1;
while(runCount < 4)
{
try
{
if (File.Exists(filePath))
{
using (var fileStreamReader = File.OpenText(filePath))
{
return await fileStreamReader.ReadToEndAsync();
}
}
else
{
throw new FileNotFoundException();
}
}
catch (IOException ex)
{
if (runCount == 3 || ex.HResult != -2147024864)
{
throw;
}
else
{
await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, runCount)));
runCount++;
}
}
}
return null;
}
Vytvoří se a FileService
zpracuje vyhledávání souborů uložených v mezipaměti. Volání GetFileContent
metody služby se pokusí získat obsah souboru z mezipaměti v paměti a vrátit ho volajícímu (Services/FileService.cs
).
Pokud se obsah uložený v mezipaměti pomocí klíče mezipaměti nenajde, provede se následující akce:
- Obsah souboru je získán pomocí
GetFileContent
. - Token změny se získá od zprostředkovatele souborů pomocí IFileProviders.Watch. Zpětné volání tokenu se aktivuje při změně souboru.
- Obsah souboru se ukládá do mezipaměti s posunutým obdobím vypršení platnosti . Token změny je připojen k MemoryCacheEntryExtensions.AddExpirationToken k vyřazení položky mezipaměti, pokud se soubor změní v mezipaměti.
V následujícím příkladu jsou soubory uložené v kořenovém adresáři obsahu aplikace. IHostingEnvironment.ContentRootFileProvider se používá k získání IFileProvider bodu na aplikaci ContentRootPath. Získá se filePath
pomocí IFileInfo.PhysicalPath.
public class FileService
{
private readonly IMemoryCache _cache;
private readonly IFileProvider _fileProvider;
private List<string> _tokens = new List<string>();
public FileService(IMemoryCache cache, IHostingEnvironment env)
{
_cache = cache;
_fileProvider = env.ContentRootFileProvider;
}
public async Task<string> GetFileContents(string fileName)
{
var filePath = _fileProvider.GetFileInfo(fileName).PhysicalPath;
string fileContent;
// Try to obtain the file contents from the cache.
if (_cache.TryGetValue(filePath, out fileContent))
{
return fileContent;
}
// The cache doesn't have the entry, so obtain the file
// contents from the file itself.
fileContent = await GetFileContent(filePath);
if (fileContent != null)
{
// Obtain a change token from the file provider whose
// callback is triggered when the file is modified.
var changeToken = _fileProvider.Watch(fileName);
// Configure the cache entry options for a five minute
// sliding expiration and use the change token to
// expire the file in the cache if the file is
// modified.
var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromMinutes(5))
.AddExpirationToken(changeToken);
// Put the file contents into the cache.
_cache.Set(filePath, fileContent, cacheEntryOptions);
return fileContent;
}
return string.Empty;
}
}
Je FileService
zaregistrovaný v kontejneru služby spolu se službou ukládání do mezipaměti paměti.
V Startup.ConfigureServices
:
services.AddMemoryCache();
services.AddSingleton<FileService>();
Stránkový model načte obsah souboru pomocí služby.
V metodě indexové stránky OnGet
(Pages/Index.cshtml.cs
):
var fileContent = await _fileService.GetFileContents("poem.txt");
CompositeChangeToken – třída
Pro reprezentaci jedné nebo více IChangeToken
instancí v jednom objektu použijte CompositeChangeToken třídu.
var firstCancellationTokenSource = new CancellationTokenSource();
var secondCancellationTokenSource = new CancellationTokenSource();
var firstCancellationToken = firstCancellationTokenSource.Token;
var secondCancellationToken = secondCancellationTokenSource.Token;
var firstCancellationChangeToken = new CancellationChangeToken(firstCancellationToken);
var secondCancellationChangeToken = new CancellationChangeToken(secondCancellationToken);
var compositeChangeToken =
new CompositeChangeToken(
new List<IChangeToken>
{
firstCancellationChangeToken,
secondCancellationChangeToken
});
HasChanged
v sestavách true
složeného tokenu, pokud je true
nějaký reprezentovaný token HasChanged
. ActiveChangeCallbacks
v sestavách true
složeného tokenu, pokud je true
nějaký reprezentovaný token ActiveChangeCallbacks
. Pokud dojde k více souběžných událostem změn, vyvolá se jednou zpětné volání složené změny.
Další materiály
- Ukládání do mezipaměti v paměti v ASP.NET Core
- Distribuované ukládání do mezipaměti v ASP.NET Core
- Ukládání odpovědí do mezipaměti v ASP.NET Core
- Middleware pro ukládání odpovědí do mezipaměti v ASP.NET Core
- Pomocná rutina značek mezipaměti v ASP.NET Core MVC
- Pomocná rutina značek distribuované mezipaměti v ASP.NET Core