Mendeteksi perubahan dengan token perubahan di ASP.NET Core
Catatan
Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.
Peringatan
Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Penting
Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.
Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.
Token perubahan adalah blok penyusun tingkat rendah tujuan umum yang digunakan untuk melacak perubahan status.
Melihat atau mengunduh kode sampel (cara mengunduh)
Antarmuka IChangeToken
IChangeToken menyebarluaskan pemberitahuan bahwa telah terjadi perubahan. IChangeToken
berada di Microsoft.Extensions.Primitives namespace layanan. Paket NuGet Microsoft.Extensions.Primitives secara implisit disediakan untuk aplikasi ASP.NET Core.
IChangeToken
memiliki dua properti:
- ActiveChangeCallbacks menunjukkan apakah token secara proaktif menaikkan panggilan balik. Jika
ActiveChangedCallbacks
diatur kefalse
, panggilan balik tidak pernah dipanggil, dan aplikasi harus melakukan pollingHasChanged
untuk perubahan. Token juga dimungkinkan untuk tidak pernah dibatalkan jika tidak ada perubahan yang terjadi atau pendengar perubahan yang mendasar dibuang atau dinonaktifkan. - HasChanged menerima nilai yang menunjukkan apakah perubahan telah terjadi.
Antarmuka IChangeToken
mencakup metode RegisterChangeCallback(Action<Object>, Object), yang mendaftarkan panggilan balik yang dipanggil ketika token telah berubah. HasChanged
harus diatur sebelum panggilan balik dipanggil.
Kelas ChangeToken
ChangeToken adalah kelas statis yang digunakan untuk menyebarluaskan pemberitahuan bahwa perubahan telah terjadi. ChangeToken
berada di Microsoft.Extensions.Primitives namespace layanan. Paket NuGet Microsoft.Extensions.Primitives secara implisit disediakan untuk aplikasi ASP.NET Core.
Metode ChangeToken.OnChange(Func<IChangeToken>, Action) mendaftarkan Action
untuk memanggil setiap kali token berubah:
Func<IChangeToken>
menghasilkan token.Action
dipanggil ketika token berubah.
Overload ChangeToken.OnChange<TState>(Func<IChangeToken>, Action<TState>, TState) mengambil parameter tambahan TState
yang diteruskan ke konsumen Action
token .
OnChange
IDisposablemengembalikan . Dispose Panggilan menghentikan token mendengarkan perubahan lebih lanjut dan merilis sumber daya token.
Contoh penggunaan token perubahan di ASP.NET Core
Token perubahan digunakan di area ASP.NET Core yang menonjol untuk memantau perubahan pada objek:
- Untuk memantau perubahan pada file, IFileProviderWatch metode membuat
IChangeToken
untuk file atau folder yang ditentukan untuk ditonton. IChangeToken
token dapat ditambahkan ke entri cache untuk memicu pengeluaran cache saat perubahan.- Untuk
TOptions
perubahan, implementasi IOptionsMonitor<TOptions> default OptionsMonitor<TOptions> memiliki kelebihan beban yang menerima satu atau beberapa IOptionsChangeTokenSource<TOptions> instans. Setiap instansIChangeToken
mengembalikan untuk mendaftarkan panggilan balik pemberitahuan perubahan untuk melacak perubahan opsi.
Memantau perubahan konfigurasi
Secara default, templat ASP.NET Core menggunakan file konfigurasi JSON (appsettings.json
, appsettings.Development.json
, dan appsettings.Production.json
) untuk memuat pengaturan konfigurasi aplikasi.
File-file ini dikonfigurasi menggunakan metode ekstensi AddJsonFile(IConfigurationBuilder, String, Boolean, Boolean) yang ConfigurationBuilder menerima reloadOnChange
parameter. reloadOnChange
menunjukkan apakah konfigurasi harus dimuat ulang pada perubahan file. Pengaturan ini muncul dalam Host metode CreateDefaultBuilderkenyamanan :
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true,
reloadOnChange: true);
Konfigurasi berbasis file diwakili oleh FileConfigurationSource. FileConfigurationSource
IFileProvider menggunakan untuk memantau file.
Secara default, IFileMonitor
disediakan oleh PhysicalFileProvider, yang menggunakan FileSystemWatcher untuk memantau perubahan file konfigurasi.
Aplikasi sampel menunjukkan dua implementasi untuk memantau perubahan konfigurasi. Jika salah satu appsettings
file berubah, kedua implementasi pemantauan file menjalankan kode kustom—aplikasi sampel menulis pesan ke konsol.
File FileSystemWatcher
konfigurasi dapat memicu beberapa panggilan balik token untuk perubahan file konfigurasi tunggal. Untuk memastikan bahwa kode kustom hanya dijalankan sekali ketika beberapa panggilan balik token dipicu, implementasi sampel memeriksa hash file. Sampel menggunakan hashing file SHA1. Coba lagi diimplementasikan dengan back-off eksponensial.
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];
}
Token perubahan startup sederhana
Daftarkan panggilan balik konsumen Action
token untuk mengubah pemberitahuan ke token reload konfigurasi.
Di Startup.Configure
:
ChangeToken.OnChange(
() => config.GetReloadToken(),
(state) => InvokeChanged(state),
env);
config.GetReloadToken()
menyediakan token. Panggilan balik adalah InvokeChanged
metode:
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)");
}
}
Panggilan state
balik digunakan untuk meneruskan IWebHostEnvironment
, yang berguna untuk menentukan file konfigurasi yang benar appsettings
untuk dipantau (misalnya, appsettings.Development.json
ketika di lingkungan Pengembangan). Hash file digunakan untuk mencegah WriteConsole
pernyataan berjalan beberapa kali karena beberapa panggilan balik token ketika file konfigurasi hanya berubah sekali.
Sistem ini berjalan selama aplikasi berjalan dan tidak dapat dinonaktifkan oleh pengguna.
Memantau perubahan konfigurasi sebagai layanan
Sampel mengimplementasikan:
- Pemantauan token startup dasar.
- Pemantauan sebagai layanan.
- Mekanisme untuk mengaktifkan dan menonaktifkan pemantauan.
Sampel menetapkan IConfigurationMonitor
antarmuka.
Extensions/ConfigurationMonitor.cs
:
public interface IConfigurationMonitor
{
bool MonitoringEnabled { get; set; }
string CurrentState { get; set; }
}
Konstruktor kelas yang diimplementasikan, ConfigurationMonitor
, mendaftarkan panggilan balik untuk pemberitahuan perubahan:
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()
memasok token. InvokeChanged
adalah metode panggilan balik. state
Dalam instans ini adalah referensi ke IConfigurationMonitor
instans yang digunakan untuk mengakses status pemantauan. Dua properti digunakan:
MonitoringEnabled
: Menunjukkan apakah panggilan balik harus menjalankan kode kustomnya.CurrentState
: Menjelaskan status pemantauan saat ini untuk digunakan di UI.
Metode InvokeChanged
ini mirip dengan pendekatan sebelumnya, kecuali:
- Tidak menjalankan kodenya kecuali
MonitoringEnabled
adalahtrue
. - Menghasilkan arus
state
dalam outputnyaWriteConsole
.
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}");
}
}
}
Instans ConfigurationMonitor
terdaftar sebagai layanan di Startup.ConfigureServices
:
services.AddSingleton<IConfigurationMonitor, ConfigurationMonitor>();
Halaman Indeks menawarkan kontrol pengguna atas pemantauan konfigurasi. Instans IConfigurationMonitor
disuntikkan ke IndexModel
dalam .
Pages/Index.cshtml.cs
:
public IndexModel(
IConfiguration config,
IConfigurationMonitor monitor,
FileService fileService)
{
_config = config;
_monitor = monitor;
_fileService = fileService;
}
Monitor konfigurasi (_monitor
) digunakan untuk mengaktifkan atau menonaktifkan pemantauan dan mengatur status saat ini untuk umpan balik UI:
public IActionResult OnPostStartMonitoring()
{
_monitor.MonitoringEnabled = true;
_monitor.CurrentState = "Monitoring!";
return RedirectToPage();
}
public IActionResult OnPostStopMonitoring()
{
_monitor.MonitoringEnabled = false;
_monitor.CurrentState = "Not monitoring";
return RedirectToPage();
}
Ketika OnPostStartMonitoring
dipicu, pemantauan diaktifkan, dan status saat ini dibersihkan. Saat OnPostStopMonitoring
dipicu, pemantauan dinonaktifkan, dan status diatur untuk mencerminkan bahwa pemantauan tidak terjadi.
Tombol di antarmuka pengguna mengaktifkan dan menonaktifkan pemantauan.
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>
Memantau perubahan file yang di-cache
Konten file dapat di-cache dalam memori menggunakan IMemoryCache. Penembolokan dalam memori dijelaskan dalam topik Cache dalam memori . Tanpa mengambil langkah tambahan, seperti implementasi yang dijelaskan di bawah ini, data basi (kedaluarsa) dikembalikan dari cache jika data sumber berubah.
Misalnya, tidak memperhitungkan status file sumber yang di-cache saat memperbarui periode kedaluwarsa geser menyebabkan data file cache kedaluwarsa. Setiap permintaan untuk data memperbarui periode kedaluwarsa geser, tetapi file tidak pernah dimuat ulang ke dalam cache. Fitur aplikasi apa pun yang menggunakan konten yang di-cache file mungkin tunduk pada penerimaan konten kedaluarsa.
Menggunakan token perubahan dalam skenario penembolokan file mencegah adanya konten file basi di cache. Aplikasi sampel menunjukkan implementasi pendekatan.
Sampel menggunakan GetFileContent
untuk:
- Mengembalikan konten file.
- Terapkan algoritma coba lagi dengan back-off eksponensial untuk mencakup kasus di mana masalah akses file menunda sementara membaca konten file.
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;
}
FileService
dibuat untuk menangani pencarian file yang di-cache. Panggilan GetFileContent
metode layanan mencoba mendapatkan konten file dari cache dalam memori dan mengembalikannya ke pemanggil (Services/FileService.cs
).
Jika konten yang di-cache tidak ditemukan menggunakan kunci cache, tindakan berikut diambil:
- Konten file diperoleh menggunakan
GetFileContent
. - Token perubahan diperoleh dari penyedia file dengan IFileProviders.Watch. Panggilan balik token dipicu saat file dimodifikasi.
- Konten file di-cache dengan periode kedaluwarsa geser. Token perubahan dilampirkan dengan MemoryCacheEntryExtensions.AddExpirationToken untuk mengeluarkan entri cache jika file berubah saat di-cache.
Dalam contoh berikut, file disimpan di akar konten aplikasi. IWebHostEnvironment.ContentRootFileProvider
digunakan untuk mendapatkan IFileProvider penunjuk pada aplikasi IWebHostEnvironment.ContentRootPath
. diperoleh filePath
dengan 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;
}
}
FileService
terdaftar dalam kontainer layanan bersama dengan layanan penembolokan memori.
Di Startup.ConfigureServices
:
services.AddMemoryCache();
services.AddSingleton<FileService>();
Model halaman memuat konten file menggunakan layanan .
Dalam metode halaman OnGet
Indeks (Pages/Index.cshtml.cs
):
var fileContent = await _fileService.GetFileContents("poem.txt");
Kelas CompositeChangeToken
Untuk mewakili satu atau beberapa IChangeToken
instans dalam satu objek, gunakan CompositeChangeToken kelas .
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
pada laporan true
token komposit jika ada token HasChanged
yang diwakili adalah true
. ActiveChangeCallbacks
pada laporan true
token komposit jika ada token ActiveChangeCallbacks
yang diwakili adalah true
. Jika beberapa peristiwa perubahan bersamaan terjadi, panggilan balik perubahan komposit dipanggil satu kali.
Token perubahan adalah blok penyusun tingkat rendah tujuan umum yang digunakan untuk melacak perubahan status.
Melihat atau mengunduh kode sampel (cara mengunduh)
Antarmuka IChangeToken
IChangeToken menyebarluaskan pemberitahuan bahwa telah terjadi perubahan. IChangeToken
berada di Microsoft.Extensions.Primitives namespace layanan. Untuk aplikasi yang tidak menggunakan metapackage Microsoft.AspNetCore.App, buat referensi paket untuk paket NuGet Microsoft.Extensions.Primitives .
IChangeToken
memiliki dua properti:
- ActiveChangeCallbacks menunjukkan apakah token secara proaktif menaikkan panggilan balik. Jika
ActiveChangedCallbacks
diatur kefalse
, panggilan balik tidak pernah dipanggil, dan aplikasi harus melakukan pollingHasChanged
untuk perubahan. Token juga dimungkinkan untuk tidak pernah dibatalkan jika tidak ada perubahan yang terjadi atau pendengar perubahan yang mendasar dibuang atau dinonaktifkan. - HasChanged menerima nilai yang menunjukkan apakah perubahan telah terjadi.
Antarmuka IChangeToken
mencakup metode RegisterChangeCallback(Action<Object>, Object), yang mendaftarkan panggilan balik yang dipanggil ketika token telah berubah. HasChanged
harus diatur sebelum panggilan balik dipanggil.
Kelas ChangeToken
ChangeToken adalah kelas statis yang digunakan untuk menyebarluaskan pemberitahuan bahwa perubahan telah terjadi. ChangeToken
berada di Microsoft.Extensions.Primitives namespace layanan. Untuk aplikasi yang tidak menggunakan metapackage Microsoft.AspNetCore.App, buat referensi paket untuk paket NuGet Microsoft.Extensions.Primitives .
Metode ChangeToken.OnChange(Func<IChangeToken>, Action) mendaftarkan Action
untuk memanggil setiap kali token berubah:
Func<IChangeToken>
menghasilkan token.Action
dipanggil ketika token berubah.
Overload ChangeToken.OnChange<TState>(Func<IChangeToken>, Action<TState>, TState) mengambil parameter tambahan TState
yang diteruskan ke konsumen Action
token .
OnChange
IDisposablemengembalikan . Dispose Panggilan menghentikan token mendengarkan perubahan lebih lanjut dan merilis sumber daya token.
Contoh penggunaan token perubahan di ASP.NET Core
Token perubahan digunakan di area ASP.NET Core yang menonjol untuk memantau perubahan pada objek:
- Untuk memantau perubahan pada file, IFileProviderWatch metode membuat
IChangeToken
untuk file atau folder yang ditentukan untuk ditonton. IChangeToken
token dapat ditambahkan ke entri cache untuk memicu pengeluaran cache saat perubahan.- Untuk
TOptions
perubahan, implementasi IOptionsMonitor<TOptions> default OptionsMonitor<TOptions> memiliki kelebihan beban yang menerima satu atau beberapa IOptionsChangeTokenSource<TOptions> instans. Setiap instansIChangeToken
mengembalikan untuk mendaftarkan panggilan balik pemberitahuan perubahan untuk melacak perubahan opsi.
Memantau perubahan konfigurasi
Secara default, templat ASP.NET Core menggunakan file konfigurasi JSON (appsettings.json
, appsettings.Development.json
, dan appsettings.Production.json
) untuk memuat pengaturan konfigurasi aplikasi.
File-file ini dikonfigurasi menggunakan metode ekstensi AddJsonFile(IConfigurationBuilder, String, Boolean, Boolean) yang ConfigurationBuilder menerima reloadOnChange
parameter. reloadOnChange
menunjukkan apakah konfigurasi harus dimuat ulang pada perubahan file. Pengaturan ini muncul dalam WebHost metode CreateDefaultBuilderkenyamanan :
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true,
reloadOnChange: true);
Konfigurasi berbasis file diwakili oleh FileConfigurationSource. FileConfigurationSource
IFileProvider menggunakan untuk memantau file.
Secara default, IFileMonitor
disediakan oleh PhysicalFileProvider, yang menggunakan FileSystemWatcher untuk memantau perubahan file konfigurasi.
Aplikasi sampel menunjukkan dua implementasi untuk memantau perubahan konfigurasi. Jika salah satu appsettings
file berubah, kedua implementasi pemantauan file menjalankan kode kustom—aplikasi sampel menulis pesan ke konsol.
File FileSystemWatcher
konfigurasi dapat memicu beberapa panggilan balik token untuk perubahan file konfigurasi tunggal. Untuk memastikan bahwa kode kustom hanya dijalankan sekali ketika beberapa panggilan balik token dipicu, implementasi sampel memeriksa hash file. Sampel menggunakan hashing file SHA1. Coba lagi diimplementasikan dengan back-off eksponensial.
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];
}
Token perubahan startup sederhana
Daftarkan panggilan balik konsumen Action
token untuk mengubah pemberitahuan ke token reload konfigurasi.
Di Startup.Configure
:
ChangeToken.OnChange(
() => config.GetReloadToken(),
(state) => InvokeChanged(state),
env);
config.GetReloadToken()
menyediakan token. Panggilan balik adalah InvokeChanged
metode:
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)");
}
}
Panggilan state
balik digunakan untuk meneruskan IHostingEnvironment
, yang berguna untuk menentukan file konfigurasi yang benar appsettings
untuk dipantau (misalnya, appsettings.Development.json
ketika di lingkungan Pengembangan). Hash file digunakan untuk mencegah WriteConsole
pernyataan berjalan beberapa kali karena beberapa panggilan balik token ketika file konfigurasi hanya berubah sekali.
Sistem ini berjalan selama aplikasi berjalan dan tidak dapat dinonaktifkan oleh pengguna.
Memantau perubahan konfigurasi sebagai layanan
Sampel mengimplementasikan:
- Pemantauan token startup dasar.
- Pemantauan sebagai layanan.
- Mekanisme untuk mengaktifkan dan menonaktifkan pemantauan.
Sampel menetapkan IConfigurationMonitor
antarmuka.
Extensions/ConfigurationMonitor.cs
:
public interface IConfigurationMonitor
{
bool MonitoringEnabled { get; set; }
string CurrentState { get; set; }
}
Konstruktor kelas yang diimplementasikan, ConfigurationMonitor
, mendaftarkan panggilan balik untuk pemberitahuan perubahan:
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()
memasok token. InvokeChanged
adalah metode panggilan balik. state
Dalam instans ini adalah referensi ke IConfigurationMonitor
instans yang digunakan untuk mengakses status pemantauan. Dua properti digunakan:
MonitoringEnabled
: Menunjukkan apakah panggilan balik harus menjalankan kode kustomnya.CurrentState
: Menjelaskan status pemantauan saat ini untuk digunakan di UI.
Metode InvokeChanged
ini mirip dengan pendekatan sebelumnya, kecuali:
- Tidak menjalankan kodenya kecuali
MonitoringEnabled
adalahtrue
. - Menghasilkan arus
state
dalam outputnyaWriteConsole
.
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}");
}
}
}
Instans ConfigurationMonitor
terdaftar sebagai layanan di Startup.ConfigureServices
:
services.AddSingleton<IConfigurationMonitor, ConfigurationMonitor>();
Halaman Indeks menawarkan kontrol pengguna atas pemantauan konfigurasi. Instans IConfigurationMonitor
disuntikkan ke IndexModel
dalam .
Pages/Index.cshtml.cs
:
public IndexModel(
IConfiguration config,
IConfigurationMonitor monitor,
FileService fileService)
{
_config = config;
_monitor = monitor;
_fileService = fileService;
}
Monitor konfigurasi (_monitor
) digunakan untuk mengaktifkan atau menonaktifkan pemantauan dan mengatur status saat ini untuk umpan balik UI:
public IActionResult OnPostStartMonitoring()
{
_monitor.MonitoringEnabled = true;
_monitor.CurrentState = "Monitoring!";
return RedirectToPage();
}
public IActionResult OnPostStopMonitoring()
{
_monitor.MonitoringEnabled = false;
_monitor.CurrentState = "Not monitoring";
return RedirectToPage();
}
Ketika OnPostStartMonitoring
dipicu, pemantauan diaktifkan, dan status saat ini dibersihkan. Saat OnPostStopMonitoring
dipicu, pemantauan dinonaktifkan, dan status diatur untuk mencerminkan bahwa pemantauan tidak terjadi.
Tombol di antarmuka pengguna mengaktifkan dan menonaktifkan pemantauan.
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>
Memantau perubahan file yang di-cache
Konten file dapat di-cache dalam memori menggunakan IMemoryCache. Penembolokan dalam memori dijelaskan dalam topik Cache dalam memori . Tanpa mengambil langkah tambahan, seperti implementasi yang dijelaskan di bawah ini, data basi (kedaluarsa) dikembalikan dari cache jika data sumber berubah.
Misalnya, tidak memperhitungkan status file sumber yang di-cache saat memperbarui periode kedaluwarsa geser menyebabkan data file cache kedaluwarsa. Setiap permintaan untuk data memperbarui periode kedaluwarsa geser, tetapi file tidak pernah dimuat ulang ke dalam cache. Fitur aplikasi apa pun yang menggunakan konten yang di-cache file mungkin tunduk pada penerimaan konten kedaluarsa.
Menggunakan token perubahan dalam skenario penembolokan file mencegah adanya konten file basi di cache. Aplikasi sampel menunjukkan implementasi pendekatan.
Sampel menggunakan GetFileContent
untuk:
- Mengembalikan konten file.
- Terapkan algoritma coba lagi dengan back-off eksponensial untuk mencakup kasus di mana masalah akses file menunda sementara membaca konten file.
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;
}
FileService
dibuat untuk menangani pencarian file yang di-cache. Panggilan GetFileContent
metode layanan mencoba mendapatkan konten file dari cache dalam memori dan mengembalikannya ke pemanggil (Services/FileService.cs
).
Jika konten yang di-cache tidak ditemukan menggunakan kunci cache, tindakan berikut diambil:
- Konten file diperoleh menggunakan
GetFileContent
. - Token perubahan diperoleh dari penyedia file dengan IFileProviders.Watch. Panggilan balik token dipicu saat file dimodifikasi.
- Konten file di-cache dengan periode kedaluwarsa geser. Token perubahan dilampirkan dengan MemoryCacheEntryExtensions.AddExpirationToken untuk mengeluarkan entri cache jika file berubah saat di-cache.
Dalam contoh berikut, file disimpan di akar konten aplikasi. IHostingEnvironment.ContentRootFileProvider digunakan untuk mendapatkan IFileProvider pointing pada aplikasi ContentRootPath. diperoleh filePath
dengan 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;
}
}
FileService
terdaftar dalam kontainer layanan bersama dengan layanan penembolokan memori.
Di Startup.ConfigureServices
:
services.AddMemoryCache();
services.AddSingleton<FileService>();
Model halaman memuat konten file menggunakan layanan .
Dalam metode halaman OnGet
Indeks (Pages/Index.cshtml.cs
):
var fileContent = await _fileService.GetFileContents("poem.txt");
Kelas CompositeChangeToken
Untuk mewakili satu atau beberapa IChangeToken
instans dalam satu objek, gunakan CompositeChangeToken kelas .
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
pada laporan true
token komposit jika ada token HasChanged
yang diwakili adalah true
. ActiveChangeCallbacks
pada laporan true
token komposit jika ada token ActiveChangeCallbacks
yang diwakili adalah true
. Jika beberapa peristiwa perubahan bersamaan terjadi, panggilan balik perubahan komposit dipanggil satu kali.
Sumber Daya Tambahan:
ASP.NET Core