JuiceFS on Windows: 首個(gè) Beta 版的探索與優(yōu)化之路
在近期發(fā)布的 JuiceFS 社區(qū)版1.3 和企業(yè)版 5.2 中,我們對(duì) Windows 客戶端進(jìn)行了大量的優(yōu)化工作。在早期版本中,JuiceFS 也嘗試支持 Windows 平臺(tái),但是在使用體驗(yàn)和穩(wěn)定性方面存在諸多問題,無(wú)法達(dá)到一個(gè)穩(wěn)定的可用狀態(tài)。
去年,我們決定重新對(duì) Windows 客戶端 進(jìn)行全面改進(jìn),力求在提高性能的同時(shí),提供更加穩(wěn)定和高質(zhì)量的用戶體驗(yàn)。在近期的一次云端渲染場(chǎng)景測(cè)試中,我們對(duì) 3000 臺(tái) Windows 客戶端進(jìn)行了小文件讀寫性能測(cè)試,結(jié)果表明性能已能滿足大規(guī)模使用需求。我們將在下一篇博客中分享此次測(cè)試的詳細(xì)情況。
在此次歷時(shí)一年的優(yōu)化過程中,由于 Windows 客戶端相關(guān)文檔和資料相對(duì)有限,我們面臨了諸多挑戰(zhàn)。本文將詳細(xì)闡述過程中遇到的關(guān)鍵問題、采取的方案以及目前已取得的進(jìn)展。需要注意的是,目前的版本處于 Beta 階段,即主要功能已完成,但仍需通過持續(xù)的測(cè)試和用戶反饋進(jìn)行優(yōu)化。希望有需求的用戶積極使用,并在社區(qū)中提出建議,我們也將積極支持并解決大家的問題。
01 目標(biāo)是什么?
對(duì)于 Windows 版本 的開發(fā),核心任務(wù)是將現(xiàn)有文件系統(tǒng)邏輯遷移到 Windows 平臺(tái)。接入方式主要有兩種:
-
一是通過 Linux 掛載并啟動(dòng) Samba 服務(wù),將文件共享給 Windows 使用;這種方式可能帶來(lái)額外的協(xié)議開銷和配置復(fù)雜性,進(jìn)而影響性能和穩(wěn)定性。
-
二是直接在 Windows 上運(yùn)行客戶端,這種方式更接近 Windows 原生的使用體驗(yàn),但歷史版本存在較多 bug。在此次 Beta 版本 中,我們主要針對(duì)第二種方式對(duì) Windows 客戶端進(jìn)行優(yōu)化。
我們希望這個(gè)版本能夠達(dá)到真正可用的狀態(tài),包括確保大多數(shù) Windows 應(yīng)用程序能夠在 JuiceFS 的文件系統(tǒng)上正常運(yùn)行,支持?jǐn)?shù)據(jù)讀寫操作以及文件管理功能;確保系統(tǒng)具有合格的性能。為此,Beta 版本需要完成的工作可以分為幾個(gè)方面:
1. 修復(fù)工具集
工具集是 JuiceFS 使用過程中的重要組成部分,但許多常用命令在 Windows 客戶端上無(wú)法正常使用。我們將在下文詳細(xì)描述各個(gè)主要命令,所進(jìn)行的優(yōu)化和改進(jìn)工作。
2. 優(yōu)化使用體驗(yàn)
在過去的版本中,用戶體驗(yàn)存在許多問題,尤其在性能方面和操作簡(jiǎn)便性方面。因此,我們需要著重優(yōu)化這些方面,使得使用過程更加流暢、簡(jiǎn)便。
3. 修復(fù) Bug
- 與身份驗(yàn)證和權(quán)限管理相關(guān)的問題,過去的版本在這些方面比較混亂。
- 與 Windows API 相關(guān)的 Bug,特別是錯(cuò)誤碼返回值和某些邏輯問題。
- 一些零散的 Bug,需要在 Beta 版本中一并修復(fù)。
02 怎么做 ?
在這個(gè)優(yōu)化過程中,我們依舊借助了一個(gè)非常重要的組件——WinFsp(Windows File System Proxy),它是一個(gè)開源庫(kù),提供了兩個(gè)至關(guān)重要的特性:
- 提供了一個(gè)高效的文件系統(tǒng)驅(qū)動(dòng)接口,實(shí)現(xiàn)了 Windows 文件系統(tǒng)驅(qū)動(dòng)(FSD, File System Driver)。
- 還提供了 FUSE(Filesystem in Userspace)接口中的 high-level 接口。FUSE 本身提供了兩套接口——high-level 接口和 low-level 接口。在JuiceFS 中,我們使用的是 low-level 的接口,但通過做一些路徑轉(zhuǎn)換,我們已經(jīng)可以成功對(duì)接 FUSE 層。
在引入 WinFsp 后,Windows 上的讀取流程大致是這樣的。下圖中上半部分代表用戶空間,下半部分代表內(nèi)核空間。
圖中展示的流程是數(shù)據(jù)從應(yīng)用程序到驅(qū)動(dòng)程序之間的流轉(zhuǎn)路徑。在用戶空間中,應(yīng)用程序執(zhí)行 I/O 操作(如文件讀寫)會(huì)傳遞到內(nèi)核空間,并流轉(zhuǎn)到 Windows 內(nèi)核中的一個(gè)核心組件 —— Windows I/O Manager。該組件負(fù)責(zé)管理所有的 I/O 操作。

接下來(lái),Windows I/O Manager 會(huì)將這些 I/O 操作轉(zhuǎn)換為 Windows I/O Request Package(IRP),然后將其轉(zhuǎn)發(fā)到文件系統(tǒng)驅(qū)動(dòng)層。此處簡(jiǎn)化了部分層級(jí),最終這些請(qǐng)求會(huì)傳遞到文件系統(tǒng)驅(qū)動(dòng)層,具體來(lái)說就是 WinFsp 文件系統(tǒng)驅(qū)動(dòng)。
當(dāng)文件系統(tǒng)驅(qū)動(dòng)接收到請(qǐng)求時(shí),它會(huì)將請(qǐng)求轉(zhuǎn)發(fā)給 WinFsp 的 DLL。這個(gè) DLL 承擔(dān)了與 Windows 系統(tǒng)內(nèi)核數(shù)據(jù)進(jìn)行接口轉(zhuǎn)換的責(zé)任。
在我們 JuiceFS 的實(shí)現(xiàn)中,應(yīng)用程序通過鏈接 WinFsp DLL 來(lái)處理 I/O 請(qǐng)求。當(dāng) Windows I/O 請(qǐng)求被傳遞到 DLL 時(shí),WinFsp 會(huì)將其轉(zhuǎn)換為 FUSE 接口,并通過 Windows FUSE 兼容層 進(jìn)行回調(diào)處理。絕大部分的工作集中在這一層,包括 bug 修復(fù)和性能優(yōu)化。
處理完這些操作后,最終的請(qǐng)求會(huì)交給 JuiceFS 核心 VFS(虛擬文件系統(tǒng))層,核心 VFS 負(fù)責(zé)執(zhí)行具體的文件系統(tǒng)邏輯和請(qǐng)求處理。
還有 4 個(gè)困難
1. Unix vs Windows
盡管 WinFsp 已經(jīng)幫助我們將 I/O 請(qǐng)求轉(zhuǎn)換為 FUSE 接口,但我們依然需要面對(duì) Unix 和 Windows 之間的本質(zhì)性差異。
權(quán)限管理差異
例如,Linux 中的文件權(quán)限(可讀、可寫、可執(zhí)行等)和擴(kuò)展權(quán)限(如 ACL)與 Windows 中的權(quán)限模型完全不同。Windows 使用 DACL(Discretionary Access Control List)進(jìn)行權(quán)限定義,同時(shí)支持權(quán)限繼承,這與 Unix 的權(quán)限模型有很大差異。因此,雖然 WinFsp 處理了一部分權(quán)限的轉(zhuǎn)換,但我們?nèi)孕杞鉀Q如何將這兩種
權(quán)限體系進(jìn)行有效映射,以便更好地支持 Windows 應(yīng)用。
系統(tǒng)特性的差異
Unix 和 Windows 在文件系統(tǒng)特性方面也存在較多的本質(zhì)差異。諸如硬鏈接、軟鏈接、掛載方式、目錄長(zhǎng)度、字符限制等、文件屬性等,而我們的 JuiceFS 核心文件系統(tǒng)是基于 Unix 的文件系統(tǒng)設(shè)計(jì),因此我們需要解決或者繞開這些差異,以確保在 Windows 平臺(tái)上也能正常運(yùn)行。
API 差異
Unix 和 Windows 在系統(tǒng) API 上也有許多差異,盡管我們使用了 Go 語(yǔ)言來(lái)簡(jiǎn)化部分 API 差異的處理,但依然存在一些需要手動(dòng)解決的情況。例如,獲取 UID 和 GID 等信息,在 Windows 系統(tǒng)中并沒有直接的對(duì)應(yīng)方式。雖然 Go 語(yǔ)言在跨平臺(tái)處理上做了很多優(yōu)化,但一些特定的系統(tǒng) API 仍然需要我們自行處理這些差異,確保系統(tǒng)的兼容性和穩(wěn)定性。
2. Linux FUSE vs WinFsp FUSE
之前,JuiceFS 一直與 low-level FUSE 接口進(jìn)行對(duì)接,而 WinFsp FUSE 則是一個(gè) high-level FUSE 接口,這兩者存在本質(zhì)的區(qū)別。
首先,low-level FUSE 通常使用 inode 作為回調(diào)參數(shù),而高級(jí) FUSE 則主要使用路徑作為回調(diào)參數(shù),這是兩者的一個(gè)顯著差異。然而,差異不僅限于此。
盡管 WinFsp 提供了一個(gè) high-level的 FUSE 回調(diào)接口,但其實(shí)現(xiàn)邏輯并未完全遵循 Linux 中 libfuse 的實(shí)現(xiàn)方式。因此,在使用 WinFsp FUSE 時(shí),我們常常會(huì)遇到一種情況:在 Linux 中,某些行為表現(xiàn)得很自然和一致,完全如FUSE文檔所述的一致,但在 WinFsp 中,這些行為的回調(diào)邏輯卻有所不同。這使得我們需要特別注意并解決這些平臺(tái)之間的行為差異。
3. 黑盒的 Windows 內(nèi)核
在開發(fā)過程中,我們還需要面對(duì)一個(gè) 黑盒的 Windows 內(nèi)核。由于 Windows 內(nèi)核沒有開源,且相關(guān)文檔資料非常有限,調(diào)試和觀察 Windows 內(nèi)核的行為變得較為困難。這使得整個(gè)開發(fā)過程充滿了不確定性,對(duì)于開發(fā)人員來(lái)說,Windows 內(nèi)核的工作機(jī)制就像一個(gè)封閉的黑盒,需要通過不斷的實(shí)驗(yàn)和反向工程來(lái)理解和適應(yīng)。
4. 有限的 FSD 文檔資源
除了 Windows 內(nèi)核本身的黑盒特性外,關(guān)于文件系統(tǒng)驅(qū)動(dòng)(FSD)的文檔資源也非常有限。微軟并未公開完整的 Windows 內(nèi)核開發(fā)文檔,很多 API 僅由第三方整理,官方文檔稀缺。事實(shí)上,唯一一本專注于 Windows 文件系統(tǒng)驅(qū)動(dòng)的書籍是 1997 年出版的 《Windows NT File System Internals: A Developer's Guide》。盡管該書中包含大量錯(cuò)誤(多數(shù)是由于不適用于當(dāng)前版本),直到今天,Windows 文件系統(tǒng)驅(qū)動(dòng)的開發(fā)者仍然只能依賴這本書作為參考。這些有限的文檔資源使得我們?cè)谂挪閱栴}和理解 Windows 文件系統(tǒng)行為時(shí),必須付出更多的時(shí)間和精力來(lái)收集資料并進(jìn)行學(xué)習(xí)。
03 做到了哪些?
接下來(lái),我們將介紹我們?cè)?Beta 版本中進(jìn)行的具體工作。主要可以分為兩個(gè)部分:JuiceFS 端的工作以及 WinFsp 端的工作。
1. JuiceFS 部分
工具集
首先,工具集在我們?nèi)粘J褂?JuiceFS 時(shí)至關(guān)重要。使用者在部署之后,都需要借助工具集來(lái)進(jìn)行性能測(cè)試、監(jiān)控等操作。例如,最基本的性能測(cè)試通常會(huì)運(yùn)行 bench 命令。然而,在早期版本中,這個(gè)命令在 Windows 平臺(tái)上無(wú)法運(yùn)行,系統(tǒng)會(huì)提示命令不支持 Windows。
此外,掛載文件系統(tǒng)后,我們通常需要觀察一些關(guān)鍵的性能指標(biāo),例如原始數(shù)據(jù)的延遲、吞吐量、對(duì)象存儲(chǔ)的表現(xiàn),以及分布式緩存的吞吐量等。然而,在之前的版本中,這些監(jiān)控功能也無(wú)法正常使用,系統(tǒng)會(huì)提示無(wú)法打開 .control 文件。
JuiceFS 1.3 和 企業(yè)版 5.2 中,這些問題都得到了修復(fù)。目前,工具集已經(jīng)從幾乎完全不可用,發(fā)展到了基本可用的狀態(tài)。
API 兼容性
在早期版本中,一些用戶可能會(huì)遇到問題,特別是當(dāng)將 JuiceFS 用作 Git 目錄時(shí)。有些用戶發(fā)現(xiàn)直接執(zhí)行 Git 命令時(shí),操作無(wú)法正常執(zhí)行。問題的主要原因在于錯(cuò)誤碼的處理不兼容 Windows 系統(tǒng)。我們沒有像 Windows 本身那樣處理特定的錯(cuò)誤碼,導(dǎo)致應(yīng)用程序依賴于某些特定錯(cuò)誤碼時(shí)無(wú)法正常工作。這一部分主要涉及到 API 兼容性 的改進(jìn)。
此外,早期版本中還可能出現(xiàn)掛載狀態(tài)異常的情況。例如,掛載過程完成后,系統(tǒng)提示掛載失敗,實(shí)際上文件系統(tǒng)已經(jīng)掛載;或是掛載成功的提示顯示不正確。在當(dāng)前的 Beta 版本中,我們已經(jīng)對(duì)這些行為進(jìn)行了修復(fù)和優(yōu)化,包括 Git 命令相關(guān)的錯(cuò)誤。
本質(zhì)上,Linux 和 Windows 在錯(cuò)誤碼方面的差異是難以完全匹配的,因此實(shí)現(xiàn) 100% 的一致性非常困難。盡管如此,我們依然通過持續(xù)的反饋和改進(jìn),不斷優(yōu)化這些兼容性問題,力求提供更穩(wěn)定的 Windows 版本。
User/permission
在早期版本中,我們的權(quán)限管理還存在一些模糊之處。比如,當(dāng)用戶 A 設(shè)置了某些權(quán)限或在其他區(qū)域設(shè)置了權(quán)限時(shí),我們并沒有清晰的預(yù)期和統(tǒng)一的處理方式。這導(dǎo)致了一些問題,例如,用戶 A 掛載了文件系統(tǒng)后,他希望同事能夠讀取文件,但當(dāng)時(shí)我們沒有明確的方案來(lái)處理這種情況。為了實(shí)現(xiàn)文件共享,我們?cè)褂靡粋€(gè)名為 as-root 的參數(shù),將所有用戶權(quán)限提升為 root 權(quán)限,這種做法雖然能暫時(shí)解決問題,但并不理想。
而在 Beta 版本中,我們對(duì)權(quán)限管理進(jìn)行了優(yōu)化。重新設(shè)計(jì)了權(quán)限機(jī)制,明確了權(quán)限管理的目標(biāo),確保在 Windows API 的正常工作下,盡可能地與 POSIX 行為保持一致。具體來(lái)說,我們?cè)跊]有開啟 UID 映射的情況下,確保 Linux 用戶的 UID(如 1001)能夠在 Windows 系統(tǒng)中正確映射和共享,保證相同 UID 的用戶被視為相同的用戶。
此外,如果啟用了 UID 映射功能,這是一個(gè)更為復(fù)雜的話題,但我們也將提供支持。總之,我們的目標(biāo)是確保 Windows 系統(tǒng)的權(quán)限管理盡可能與 POSIX 行為一致,為用戶提供更清晰、可靠的權(quán)限控制。
掛載相關(guān)
在早期版本中,掛載操作只能在前臺(tái)進(jìn)行,無(wú)法支持后臺(tái)掛載。這導(dǎo)致了一個(gè)問題:如果用戶希望后臺(tái)掛載文件系統(tǒng)以便共享給其他用戶,他們不得不依賴第三方工具或手動(dòng)配置。例如,他們可能需要使用微軟自帶的命令行工具來(lái)創(chuàng)建系統(tǒng)服務(wù),或者手寫 YAML 配置文件,這樣的過程既繁瑣又容易出錯(cuò)。
在 JuiceFS 1.3 和 企業(yè)版 5.2 中,我們解決了這一問題,直接支持了后臺(tái)掛載。與 Linux 版本一致,用戶可以通過 -d 參數(shù)在社區(qū)版中實(shí)現(xiàn)后臺(tái)掛載,而企業(yè)版默認(rèn)支持后臺(tái)掛載。如果用戶需要前臺(tái)掛載,則可以使用 -f 參數(shù)。
此外,過去的社區(qū)版也不支持將同一個(gè)文件系統(tǒng)掛載到多個(gè)盤符上。現(xiàn)在,在 企業(yè)版 中,我們已實(shí)現(xiàn)了這一功能,允許用戶將同一個(gè)文件系統(tǒng)掛載到多個(gè)盤符上。目前,這項(xiàng)功能僅在企業(yè)版中可用。
性能提升
在早期版本中,存在一個(gè)廣泛且嚴(yán)重的問題,那就是小文件的讀寫性能非常差,文件屬性的讀取效率也很低。
在 JuiceFS 1.3 和 企業(yè)版 5.2 版本中,我們進(jìn)行了大幅優(yōu)化,顯著提升了小文件的讀寫性能。具體的優(yōu)化進(jìn)展可以通過 bench 工具來(lái)測(cè)試和反饋,該工具能夠提供關(guān)于大文件和小文件的讀寫性能指標(biāo)。
以阿里云上一個(gè) 88 核 16 GB 的機(jī)器為例,使用阿里云的 Redis 和自建的 MinIO 進(jìn)行性能測(cè)試。在默認(rèn)命令行參數(shù)下,我們發(fā)現(xiàn)小文件的寫入性能接近 1.2 版本,而小文件的讀取性能則有了顯著提升:從 1.2 版本 的每秒 200 個(gè)小文件提升至 1.3 版本 的每秒接近 1000 個(gè)小文件。
此外,文件屬性的讀取性能也得到了優(yōu)化。過去每秒大約只能獲取 200 個(gè)文件屬性,而現(xiàn)在可以達(dá)到 4500 次每秒。當(dāng)然,這一結(jié)果受緩存的影響,實(shí)際性能可能會(huì)有所波動(dòng),但總體上優(yōu)化效果非常顯著。

另一項(xiàng)重要的優(yōu)化涉及路徑深度的影響。在 1.2 版本 中,當(dāng)文件路徑深度增加時(shí),性能急劇下降。例如,在三層目錄的情況下,讀取小文件的性能大幅下降,可能每秒只能讀取幾十個(gè)小文件。而在 1.3 版本 中,即使路徑深度達(dá)到三層,性能幾乎沒有顯著變化,保持了穩(wěn)定的表現(xiàn)。這一改進(jìn)確保了用戶在使用過程中,不會(huì)因?yàn)閯?chuàng)建更多目錄而導(dǎo)致性能下降。

其他優(yōu)化與修復(fù)
子目錄掛載和文件重命名操作在之前的版本中可能無(wú)法正常進(jìn)行,尤其是在重命名時(shí),常常會(huì)遇到一些難以解釋的錯(cuò)誤,導(dǎo)致操作無(wú)法完成。現(xiàn)在,這些問題已經(jīng)得到了優(yōu)化和修復(fù)。此外,可能還有一些其他因素未在此列出,仍在持續(xù)改進(jìn)中。
2. FSD 相關(guān)問題修復(fù)與定位
POSIX 文件權(quán)限映射
在之前的版本中,我們遇到一個(gè)與文件權(quán)限映射相關(guān)的問題,尤其是 0666 權(quán)限設(shè)置。根據(jù) POSIX 標(biāo)準(zhǔn),0666 權(quán)限意味著文件對(duì)于所有用戶都是可讀可寫的。然而,在 Windows 上,即使我們?yōu)槟硞€(gè)文件設(shè)置了 0666 權(quán)限,Everyone 組(即所有用戶)仍然無(wú)法進(jìn)行覆蓋寫操作。
這個(gè)問題的根本原因在于 WinFsp 目前沒有完全處理這些權(quán)限映射。即使在 Windows 上設(shè)置了類似的權(quán)限,實(shí)際上它并不會(huì)如 POSIX 系統(tǒng)那樣讓所有用戶都能夠讀取和寫入文件。
目前,WinFsp 的版本仍然存在這個(gè)問題,我們已經(jīng)向上游提交 PR 來(lái)修復(fù)這個(gè)問題,期望能夠使 Windows 上的行為與 POSIX 系統(tǒng)一致,確保在 Windows 平臺(tái)上也能正確地處理文件權(quán)限。
close to open 一致性
默認(rèn)情況下,JuiceFS 遵循 close-to-open 一致性模型,這意味著在文件關(guān)閉之后,下次打開該文件時(shí),用戶能夠看到之前寫入的數(shù)據(jù),即使是在不同的機(jī)器上也是如此。
然而,在 WinFsp 及 Windows 系統(tǒng)中,文件關(guān)閉的處理方式與此不同。WinFsp 的默認(rèn)行為并不會(huì)在文件關(guān)閉時(shí),異步等待 FUSE 應(yīng)用程序處理完數(shù)據(jù)。具體來(lái)說,當(dāng)應(yīng)用程序調(diào)用 CloseHandle 關(guān)閉文件句柄時(shí),經(jīng)由 WinFsp 的 Windows 應(yīng)用程序并不會(huì)阻塞在 CloseHandle 的調(diào)用處,而是直接返回,哪怕本地還有未上傳至云端的數(shù)據(jù)。這種方式導(dǎo)致了 close-to-open 一致性無(wú)法得到保證,甚至本機(jī)用戶,在下一次打開此文件時(shí),依舊可能讀取到的是錯(cuò)誤的文件長(zhǎng)度信息。
為了解決這個(gè)問題,我們已經(jīng)向 WinFsp 的源代碼做出相應(yīng)調(diào)整,以確保在 Windows 平臺(tái)上也能夠維持 close-to-open 一致性,確保數(shù)據(jù)的同步和一致性不受影響。
內(nèi)核 cache manager 使用
在 WinFsp 的處理過程中,默認(rèn)情況下它并未利用內(nèi)核的 Cache Manager,這直接導(dǎo)致了文件讀取性能較差。Cache Manager 通常會(huì)負(fù)責(zé)緩存和預(yù)讀操作,這有助于提升文件系統(tǒng)的讀取效率。然而,在 WinFsp 的默認(rèn)配置下,Cache Manager 并未得到有效利用,從而影響了系統(tǒng)的性能表現(xiàn)。
為了解決這一問題,我們?cè)?FSD 層面進(jìn)行了問題定位和修復(fù),并研究了如何在 WinFsp 中正確啟用 Cache Manager。我們的目標(biāo)是通過正確啟用和配置緩存管理,顯著提升文件讀取性能,并優(yōu)化系統(tǒng)的整體表現(xiàn)。

03 未來(lái)計(jì)劃
我們將持續(xù)聚焦 Windows 客戶端的可用性,包括 bug 修復(fù)、功能擴(kuò)展以及對(duì)軟鏈接(symlink)的支持;性能提升也是我們不斷努力的方向。隨著使用場(chǎng)景日益復(fù)雜,數(shù)據(jù)規(guī)模不斷擴(kuò)大,且涉及的技術(shù)點(diǎn)較為廣泛,Windows 客戶端 的優(yōu)化將是一個(gè)長(zhǎng)期過程。
此外,許多用戶反饋希望能夠與 AD 域賬號(hào)進(jìn)行集成。在 Windows 環(huán)境下,與 AD 域賬號(hào)的綁定將是一個(gè)非常實(shí)用的特性,我們正在研究這一需求。如果大家有相關(guān)的建議或希望實(shí)現(xiàn)的功能,歡迎與我們討論。
最后,感謝大家對(duì) Windows 版本的支持,歡迎大家體驗(yàn)和反饋,希望我們能為大家提供更好的使用體驗(yàn)。

浙公網(wǎng)安備 33010602011771號(hào)