配置的同步涉及到兩個方面:第一,對原始的配置文件實施監控并在其發生變化之后從新加載配置;第二,配置重新加載之后及時通知應用程序進而使后者能夠使用最新的配置。接下來我們利用一個簡單的.NET Core控制臺應用來演示針對文件的配置會涉及到數據同步的問題,我們希望應用能夠對原始配置文件實施監控,并在文件內容發生改變的時候從新加載并應用新的配置。針對JSON文件的配置源通過JsonConfigurationSource類型來表示,該類型定義在“Microsoft.Extensions.Configuration.Json”這個NuGet包中,所以我們需要在project.json文件中按照如下的形式添加針對這個NuGet包的依賴。[ 本文已經同步到《ASP.NET Core框架揭秘》之中]
1: {
2: ...
3: "dependencies": {
4: ...
5: "Microsoft.Extensions.Configuration.Json": "1.0.0"
6: }
7: }
假設我們需要通過配置來當前應用使用的線程池的容量,這樣的設置需要根據當前的負載進行調整,所以需要很高的時效性,我們希望一旦修改了JSON文件的配置,應用程序中針對線程池的相關設置可以立即生效。簡單起見,我們僅僅定義MinThreads 和MaxThreads這兩個分別決定線程池容量區間的配置項,如下所示的ThreadPoolOptions是對應的Options類型。
1: public class ThreadPoolOptions
2: {
3: public int MinThreads { get; set; }
4: public int MaxThreads { get; set; }
5:
6: public override string ToString()
7: {
8: return $"Thread pool size: [{MinThreads}, {MaxThreads}]";
9: }
10: }
我們在項目中添加一個名為threadPool.json的文件來定義線程池的配置。除此之外,我們需要通過修改project.json與編譯相關的配置讓該文件在編譯的時候自動拷貝到輸出目錄下(默認為bin目錄)。具體來說,我們只需要按照如下的方式將該文件的路徑設置為“builtOptions/copyToOutput”配置選購的值就可以了。
1: {
2: ...
3: "buildOptions": {
4: ...
5: "copyToOutput": "threadPool.json"
6: }
7: }
接下來我們編寫了如下一段程序來演示應用中使用的配置如何與配置文件的內容保持同步。我們首先創建了一個ConfigurationBuilder對象,并在它上面注冊了一個JsonConfigurationSource。在創建這個JsonConfigurationSource對象的時候,除了指定配置文件(“threadPool.json”)的路徑之外,我們還將它的ReloadOnChange屬性設置為True。顧名思義,這個ReloadOnChange屬性的含義就是當原始配置文件的內容發生改變的時候是否需要重新加載配置。
1: IConfiguration config = new ConfigurationBuilder()
2: .Add(new JsonConfigurationSource {Path = "threadPool.json", ReloadOnChange = true })
3: .Build();
4:
5: Action changeCallBack = () => {
6: ThreadPoolOptions options = new ServiceCollection()
7: .AddOptions()
8: .Configure<ThreadPoolOptions>(config)
9: .BuildServiceProvider()
10: .GetService<IOptions<ThreadPoolOptions>>()
11: .Value;
12: Console.WriteLine(options);
13: };
14:
15: ChangeToken.OnChange(()=>config.GetReloadToken(), changeCallBack);
16:
17: Random random = new Random();
18: while (true)
19: {
20: ThreadPoolOptions options = new ThreadPoolOptions
21: {
22: MinThreads = random.Next(10, 20),
23: MaxThreads = random.Next(40, 50)
24: };
25: File.WriteAllText(Path.Combine(AppContext.BaseDirectory, "threadPool.json"), JsonConvert.SerializeObject(options));
26: Task.Delay(5000).Wait();
27: }
在利用ConfigurationBuilder得到Configuration對象之后,我們調用它的GetReloadToken方法得到一個ChangeToken對象,后者會幫助我們判斷配置是否被重新加載。我們調用ChangeToken類型的靜態方法OnChange為這個ChangeToken對象注冊了一個回調,該回調會在配置被重新加載時自動執行。至于這個注冊的回調,我們僅僅是采用Options模式得到配置綁定生成的ThreadPoolOptions對象,并將它的相關信息打印在控制臺上。
在這段程序的最后,我們在一個無限循環中以5秒鐘的間隔對threadPool.json文件進行更新。按照這段程序的意圖,當我們每次完成了針對threadPool.json的更新之后,我們創建的Configuration對象會自動重新加載。Configuration一旦重新加載,之前調用它的GetReloadToken方法得到ChangeToken對象的HasChanged屬性將變成True,注冊在它上面的回調將被執行。所以最終的結果就是重新設置的配置會實時出現在控制臺上,如下所示的輸出結果證實了這一點。(S04)
文章列表