内容简介:遇到一個問題,.NET Core 的 File Watcher 機制(在檔案新增修改刪除時觸發 .NET 事件,註:File Watcher 可做到 Config 檔修改讀取生效、程式檔案異動時重新編譯,或是資料檔改變清除 Cache,非常實用。以下是我重現問題的範例:
遇到一個問題,.NET Core 的 File Watcher 機制(在檔案新增修改刪除時觸發 .NET 事件, 參考 )在 Docker 中可能失效。
註:File Watcher 可做到 Config 檔修改讀取生效、程式檔案異動時重新編譯,或是資料檔改變清除 Cache,非常實用。
以下是我重現問題的範例:
class Program { private static PhysicalFileProvider _fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory()); static void Main(string[] args) { Task.Factory.StartNew(() => { Thread.Sleep(5000); Console.WriteLine("update quotes after 5 seconds"); File.WriteAllText("quotes.txt", DateTime.Now.ToString()); }); WaitFileChange().GetAwaiter().GetResult(); Console.WriteLine("done"); } static async Task WaitFileChange() { IChangeToken token = _fileProvider.Watch("quotes.txt"); var tcs = new TaskCompletionSource<object>(); token.RegisterChangeCallback(state => ((TaskCompletionSource<object>)state).TrySetResult(null), tcs); await tcs.Task.ConfigureAwait(false); Console.WriteLine("quotes.txt changed"); } }
程式的運作原理為使用 PhysicalFileProvider.Watch()
觀注 quotes.txt 檔案,以 IChangeToken.RegisterChangeCallback()
註冊檔案變更事件並利用 TaskCompletionSource 同步化,在檔案變更時印出 "quotes.txt changed"。在此同時,另開一條 Thread 在 5 秒後複寫 quotes.txt 檔案以觸發事件,故正常狀況應為,程式開始後等待五秒出現 "update quotes after 5 seconds",隨即印出 "quotes.txt changed",最後顯示 "done" 測試完成。
程式在 Windows 測試 OK,部署到 Linux 執行也沒問題,包進 Docker 裡跑結果也正確,但若使用 Docker Volume 將 /app/quotes.txt 對映到實體主機的 /home/jeffrey/dockers/fwt/quotes.txt 時,本機的 quotes.txt 檔案會被覆寫,但 RegisterChangeCallback() 事件不會被觸發。
.NET Core File Providers 文件 是有提到這點:
Some file systems, such as Docker containers and network shares, may not reliably send change notifications. Set the DOTNET_USE_POLLING_FILE_WATCHER environment variable to 1 or true to poll the file system for changes every four seconds (not configurable).
意思是這個機制遇到 Docker 檔案系統可能失效,必須設定 DOTNET_USE_POLLING_FILE_WATCHER 環境變數為 1 或 true,改用 4 秒一次的輪詢取代。實務上可在啟動 Docker 時透過 docker run ... -e DOTNET_USE_POLLING_FILE_WATCHER=1 ... 參數指定,更治本的解法則是在 Dockerfile 宣告 ENV 內嵌到容器裡:
FROM microsoft/dotnet:2.1-runtime ENV DOTNET_USE_POLLING_FILE_WATCHER=1 WORKDIR /app COPY ./publish ./ ENTRYPOINT ["dotnet", "FileWatcherTest.dll"]
貌似一行搞定,但我卻在這裡陷入泥坑,設好 DOTNET_USE_POLLING_FILE_WATCHER 卻不見無效,原以為可以輕鬆寫完的文章,反覆試了近兩多小時,將近午夜電腦都要變回南瓜仍然無解,讓我萬念俱灰了無生趣。
爬文時由一則 Github Issue 追到另一則被合併至 2.2 版的相關 PR ,浮現靈感,查詢我安裝 Microsoft.Extensions.FileProviders.Physical 的 NuGet 套件版本為 2.1 穩定版,改裝 2.2 Preview 姑且一試。
喵的,就這麼成功了~
這枚升級 2.2 預覽才解掉的茶包,算是我第一次踩到的 .NET Core + Docker 地雷,不怕不怕,呵。
補充今天查到的 Docker Image 版本補充 ,你知道 2.1-runtime-deps、2.1-runtime 有什麼不同? 什麼情況該用哪一種?
- microsoft/dotnet:2.1.0-runtime-deps - use for deploying self-contained deployment apps
- microsoft/dotnet:2.1.0-runtime - use for deploying .NET Core console apps
- microsoft/dotnet:2.1.0-aspnetcore-runtime - use for deploying ASP.NET Core apps
- microsoft/dotnet:2.1.300-sdk - use for building .NET Core (or ASP.NET Core apps)
Using an example to reproduce file watcher issue in Docker with volume mapping. Setting DOTNET_USE_POLLING_FILE_WATCHER=1 doesn't works with Microsoft.Extensions.FileProviders.Physical 2.1, upgrade to 2.2 preview is the workaround.
以上所述就是小编给大家介绍的《【茶包射手日記】.NET Core File Watcher 在 Docker 環境下失效》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Unity实例开发-太空射手
- 【茶包射手日記】憑證儲存區的選擇
- 【茶包射手日記】SQLPlus Script 檔編碼問題
- 【茶包射手日記】IIS 每天早上無法登入疑案
- 【茶包射手日記】怪異的虛擬記憶體不足錯誤
- 【茶包射手日記】組件版本導向 bindingRedirect 注意事項兩則
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。