自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

NFS-Ganesha源代碼分析

云計算
NFS這個協(xié)議(NFSv2)最初由Sun Microsystems在1984年設(shè)計提出,由于存在一些不足,因此在隨后由幾家公司聯(lián)合推出了NFSv3。

NFS-Ganesha源代碼分析

1. NFSv4簡要概述

NFS這個協(xié)議(NFSv2)最初由Sun Microsystems在1984年設(shè)計提出,由于存在一些不足,因此在隨后由幾家公司聯(lián)合推出了NFSv3。到了NFSv4時,開發(fā)完全由IETF主導,設(shè)計目標是:

  • – 提高互聯(lián)下的NFS訪問和性能
  • – 提供安全性
  • – 更強的跨平臺操作
  • – 方便后期擴展

我們可以看到NFSv4在緩存能力、擴展性、高可用性方面取得了很大的突破,放棄了之前版本的無狀態(tài)性,采用了強狀態(tài)機制,客戶端和服務(wù)端采用了復雜的方式交互,由此保證了服務(wù)器端的負載均衡,減少了客戶端或服務(wù)端的RTO。

在安全性方面,NFSv4采用了面向連接的協(xié)議,強制使用RPCSEC_GSS并且提供基于RPC的安全機制。放棄了之前版本中采用的UDP,采用了TCP。NFSv4支持通過次要版本進行擴展,我們可以看到在NFSv4.1支持了RDMA、pNFS范式以及目錄委派等功能。

2. NFS-Ganesha的四大優(yōu)勢

2007年左右,CEA的大型計算機中心每天都會產(chǎn)生10TB左右的新數(shù)據(jù),CEA將這些數(shù)據(jù)放在由HSM組成的HPSS中,而這些HSM本身提供了NFS接口。但是開發(fā)者在生產(chǎn)環(huán)境中發(fā)現(xiàn)HSM和NFS的橋接仍舊有不少問題,因此開發(fā)者決心寫一個新的NFS Daemon來讓NFS接口更好的配合HPSS。

這個項目需要解決以上的問題之外,開發(fā)團隊還指定了其他目標:

  • – 可以管理百萬級別的數(shù)據(jù)緩存,從而來避免底層文件系統(tǒng)阻塞
  • – 除了可以對接HPSS以外,還可以對接其他文件系統(tǒng)
  • – 支持NFSv4,實現(xiàn)易適配(adaptability),易擴展,安全等特性
  • – 從根本上解決軟件所帶來的性能瓶頸
  • – 開源
  • – 支持Unix系統(tǒng)

由此NFS-Ganesha應(yīng)運而生,它并不是用來替代內(nèi)核版本的NFSv4,相反,NFS Ganesha是一個全新的程序,可能對比kernel版本的NFSv4,Ganesha的性能有所欠缺,但是基于user-space的方法會帶來更多有意思的功能。

靈活的內(nèi)存分配

首先,user-space的程序可以分配大量的內(nèi)存讓程序使用,這些內(nèi)存可以用來建立軟件內(nèi)部緩存,經(jīng)過測試,我們只需要4GB就可以實現(xiàn)百萬級別的數(shù)據(jù)緩存。在一些x86_64平臺的機器上,我們甚至可以分配更大的內(nèi)存(16 32GB),來實現(xiàn)千萬級別的數(shù)據(jù)緩存。

更強的可移植性

如果NFS Ganesha是kernel-space的話,那樣NFS Ganesha的內(nèi)部結(jié)構(gòu)只能適應(yīng)一款特定的OS,而很難移植到別的OS上。另外考慮的是代碼本身:在不同的平臺上編譯和運行的產(chǎn)品比在一個單一平臺上開發(fā)的產(chǎn)品更安全。 我們開發(fā)人員的經(jīng)驗表明,只在單一平臺上開發(fā)會讓開發(fā)后期困難重重; 它通常會顯示在Linux上不會輕易檢測到的錯誤,因為資源不一樣。

當然可移植性不單單指讓NFS Ganesha可以運行在不同的OS上,能夠適配不同的文件系統(tǒng)也是考量之一。在NFSv2和NFSv3中,由于語義設(shè)計上偏向Unix類的文件系統(tǒng),因此基本不可能適配非Unix類的文件系統(tǒng)。這一情況在NFSv4中大有改觀,NFSv4的語義設(shè)計出發(fā)點是讓NFS能盡可能多地適配不同的文件系統(tǒng),因此加強了文件/目錄屬性參數(shù)的抽象。Ganesha設(shè)計初衷是成為一個NFSv4通用服務(wù)器,可以實現(xiàn)NFSv4的所有功能,因此也需要適配各種文件系統(tǒng)。在內(nèi)核中實現(xiàn)這一功能是不容易的(內(nèi)和編程會有很多限制),然而在user-space中實現(xiàn)這一點會便捷一些。

更便捷的訪問機制

內(nèi)核中的NFSv4訪問用戶空間中的服務(wù)不是那么方便,因此其引入了rpc_pipefs機制, 用于解決用戶空間服務(wù)的橋梁,并且 使用kerberos5管理安全性或idmapd守護程序來進行用戶名轉(zhuǎn)換。然而Ganesha不需要這些,它使用常規(guī)API來對外提供服務(wù)。

對接FUSE

由于NFS Ganesha是一個運行在用戶空間的程序,因此它還提供了對一些用戶空間文件系統(tǒng)(FUSE)的支持,可以讓我們直接把FUSE掛載在NFS上而不需要內(nèi)核的幫助。

3. NFS-Ganesha框架淺析

NFS Ganehsha是完全使用開源自由軟件開發(fā)的,由于Linux上的系統(tǒng)編程開發(fā)資源巨大,因此開發(fā)起來比在其他Unix系統(tǒng)上更為便捷。

 

NFS-Ganesha源代碼分析
Figure 1 – NFS Ganesha分層架構(gòu)圖

由上圖我們可以看到,Ganesha是一個基于模塊的程序,每個模塊都負責各自的任務(wù)和目標。開發(fā)團隊在寫代碼之前就對每個模塊進行了精心的設(shè)計,保證了后期擴展的便捷性。比如緩存管理模塊只負責管理緩存,任何在緩存管理模塊上做出的更改不能影響其他模塊。這么做大大減少了每個模塊間的耦合,雖然開發(fā)初期顯得困難重重,但在中后期就方便了很多,每個模塊可以獨立交給不同開發(fā)人員來進行開發(fā)、驗證和測試。

Ganesha的核心模塊

  • – Memory Manager: 負責Ganesha的內(nèi)存管理。
  • – RPCSEC_GSS:負責使用RPCSEC_GSS的數(shù)據(jù)傳輸,通常使用krb5, SPKM3或LIPKEY來管理安全。
  • – NFS協(xié)議模塊:負責NFS消息結(jié)構(gòu)的管理
  • – Metadata(Inode) Cache: 負責元數(shù)據(jù)緩存管理
  • – File Content Cache:負責數(shù)據(jù)緩存管理
  • – File System Abstraction Layer(FSAL): 非常重要的模塊,通過一個接口來完成對命名空間的訪問。所訪問的對象隨后會放置在inode cache和file content cache中。
  • – Hash Tables:提供了基于紅黑樹的哈希表,這個模塊在Ganesha里用到很多。

內(nèi)存管理

內(nèi)存管理是開發(fā)Ganesha時比較大的問題,因為大多數(shù)Ganesha架構(gòu)中的所有模塊都必須執(zhí)行動態(tài)內(nèi)存分配。 例如,管理NFS請求的線程可能需要分配用于存儲所請求結(jié)果的緩沖器。 如果使用常規(guī)的LibC malloc / free調(diào)用,則存在內(nèi)存碎片的風險,因為某些模塊將分配大的緩沖區(qū),而其他模塊將使用較小的緩沖區(qū)。 這可能導致程序使用的部分內(nèi)存被交換到磁盤,性能會迅速下降的情況。

因此Ganesha有一個自己的內(nèi)存管理器,來給各個線程分配需要的內(nèi)存。內(nèi)存管理器使用了Buddy Malloc algorithm,和內(nèi)核使用的內(nèi)存分配是一樣的。內(nèi)存分配器中調(diào)用了madvise來管束Linux內(nèi)存管理器不要移動相關(guān)頁。其會向Linux申請一大塊內(nèi)存來保持高性能表現(xiàn)。

線程管理

管理CPU相比較內(nèi)存會簡單一些。Ganesha使用了大量的線程,可能在同一時間會有幾十個線程在并行工作。開發(fā)團隊在這里用到了很多POSIX調(diào)用來管理線程,讓Linux調(diào)度進程單獨處理每一個線程,使得負載可以覆蓋到所有的CPU。

開發(fā)團隊也考慮了死鎖情況,雖然引入互斥鎖可以用來防止資源訪問沖突,但是如果大量線程因此陷入死鎖狀態(tài),會大大降低性能。因此開發(fā)團隊采用了讀寫鎖,但是由于讀寫鎖可能因系統(tǒng)而異,因此又開發(fā)了一個庫來完成讀寫鎖的轉(zhuǎn)換。

當一個線程池中同時存在太多線程時,這個線程池會成為性能瓶頸。為了解決這個問題,Ganesha給每一個線程分配了單獨的資源,這樣也要求每個線程自己處理垃圾回收,并且定期重新組合它的資源。同時”dispatcher thread”提供了一些機制來防止太多線程在同一時間執(zhí)行垃圾回收;在緩存層中垃圾回收被分成好幾個步驟,每個步驟由單獨代理處理。經(jīng)過生產(chǎn)環(huán)境實測,這種設(shè)計時得當?shù)摹?/p>

哈希表

關(guān)聯(lián)尋找功能在Ganesha被大量使用,比如我們想通過對象的父節(jié)點和名稱來尋找對象元數(shù)據(jù)等類似行為是很經(jīng)常的,因此為了保證Ganesha整體的高性能,關(guān)聯(lián)尋找功能必須非常高效。

為了達到這個目的,開發(fā)團隊采用了紅黑樹,它會在add/update操作后自動沖平衡。由于單棵紅黑樹會引發(fā)進程調(diào)用沖突(多個進程同時add/update,引發(fā)同時重平衡),如果加讀寫鎖在紅黑樹上,又會引發(fā)性能瓶頸。因此開發(fā)團隊設(shè)計了紅黑樹數(shù)組來解決了這個問題,降低了兩個線程同時訪問一個紅黑樹的概率,從而避免了訪問沖突。

大型多線程守護程序

運行Ganesha需要很多線程同時工作,因此設(shè)計一個大型的線程守護程序在設(shè)計之初尤為重要,線程分為以下不同類型:

  • – dispatcher thread: 用于監(jiān)聽和分發(fā)傳入的NFS、MOUNT請求。它會選擇處于最空閑的worker線程然后將請求添加到這個worker線程的待處理列表中。這個線程會保留最近10分鐘內(nèi)的請求答復,如果在10分鐘內(nèi)收到相同指令(存在哈希表并用RPC Xid4值尋址),則會返回以前的請求回復。
  • – worker thread: Ganesha中的核心線程,也是使用最多的線程。worker線程等待dispatcher的調(diào)度,收到請求后先對其進行解碼,然后通過調(diào)用inode cache API和file content API來完成請求操作。
  • – statistics thread: 收集每個module中的線程統(tǒng)計信息,并定期用CSV格式記錄數(shù)據(jù),以便于進一步處理。
  • – admin gateway: 用于遠程管理操作,包括清楚緩存,同步數(shù)據(jù)到FSAL存儲端,關(guān)閉進程等。ganeshaadmin這個程序?qū)iT用于與admin gateway線程交互。

緩存處理

在上文中提到,Ganesha使用了大片內(nèi)存用于建立元數(shù)據(jù)和數(shù)據(jù)緩存。我們先從元數(shù)據(jù)緩存開始講起。metadata cache存放在Cache Inode Layer(MDCache Layer)層 。每個實例對應(yīng)一個命名空間中的實例(文件,符號鏈接,目錄)。這些Cache Inode Layer中的實例對應(yīng)一個FSAL中的對象,把從FSAL中讀取到的對象結(jié)構(gòu)映射在內(nèi)存中。

Cache Inode Layer將元數(shù)據(jù)與對應(yīng)FSAL對象handle放入哈希表中,用來關(guān)聯(lián)條目。初版的Ganesha采用’write through’緩存策略來做元數(shù)據(jù)緩存。實例的屬性會在一定的時間(可定義)后過期,過期后該實例將會在內(nèi)存中刪除。每個線程有一個LRU(Least Recently Used) 列表,每個緩存實例只能存在于1個線程的LRU中,如果某個線程獲得了某個實例,將會要求原線程在LRU列表中釋放對應(yīng)條目。

每個線程需要自己負責垃圾回收,當垃圾回收開始時,線程將從LRU列表上最舊的條目開始執(zhí)行。 然后使用特定的垃圾策略來決定是否保存或清除條目。由于元數(shù)據(jù)緩存應(yīng)該非常大(高達數(shù)百萬條目),因此占滿分配內(nèi)存的90%(高位)之前不會發(fā)生垃圾回收。Ganesha盡可能多得將FSAL對象放入緩存的‘樹型拓撲’中,其中節(jié)點代表目錄,葉子可代表文件和符號鏈接;葉子的垃圾回收要早于節(jié)點,當節(jié)點中沒有葉子時才會做垃圾回收。

File Content Cache數(shù)據(jù)緩存并不是獨立于與Inode Cache,一個對象的元數(shù)據(jù)緩存和數(shù)據(jù)緩存會一一對應(yīng)(數(shù)據(jù)緩存是元數(shù)據(jù)緩存的‘子緩存’),從而避免了緩存不統(tǒng)一的情況。文件內(nèi)容會被緩存至本地文件系統(tǒng)的專用目錄中,一個數(shù)據(jù)緩存實例會對應(yīng)2個文件:索引文件和數(shù)據(jù)文件。數(shù)據(jù)文件等同于被緩存的文件。索引文件中包含了元數(shù)據(jù)信息,其中包含了對重要的FSAL handle。索引文件主要用于重建數(shù)據(jù)緩存,當服務(wù)器端崩潰后沒有干凈地清掉緩存時,F(xiàn)SAL handle會讀取索引文件中的信息來重建元數(shù)據(jù)緩存,并將其指向數(shù)據(jù)文件,用以重建數(shù)據(jù)緩存實例。

當緩存不足時,worker thread會查看LRU列表中很久未被打開的實例,然后開始做元數(shù)據(jù)緩存回收。當元數(shù)據(jù)緩存回收開始時,數(shù)據(jù)緩存的垃圾回收也會同時進行:在回收文件緩存實例時,元數(shù)據(jù)緩存會問詢數(shù)據(jù)緩存是否認識該文件實例,如果不認識則代表該數(shù)據(jù)緩存已經(jīng)無效,則元數(shù)據(jù)回收正常進行,并完成實例緩存回收;如果認識,對應(yīng)的文件緩存以及數(shù)據(jù)緩存均會被回收,隨后對應(yīng)的元數(shù)據(jù)緩存也會被回收。這樣保證了一個數(shù)據(jù)緩存有效的實例不會被回收。

這種方式很符合Ganesha的架構(gòu)設(shè)計:worker線程可以同時管理元數(shù)據(jù)緩存和數(shù)據(jù)緩存,兩者一直保持一致。Ganesha在小文件的數(shù)據(jù)緩存上采用’write back’策略,如果文件很大的話則會直接讀取,而不經(jīng)過緩存;可以改進的地方是可以把大文件分割成部分放入緩存中,提高讀寫效率。

FSAL(File System Abstraction Layer)

FSAL是相當重要的模塊。FSAL本身給Inode Cache和File Content Cache提供了通用接口,收到請求后會調(diào)用具體的FSAL(FSAL_SNMP, FSAL_RGW等)。FSAL中的對象對應(yīng)一個FSAL handle。由于FSAL的語義設(shè)計與NFSv4很相似,因此開發(fā)和可以自己編寫新的FSAL API來適配Ganesha。Ganehsa軟件包還提供了FSAL源代碼模板。

4. 一個栗子

介紹了許多NFS Ganesha的內(nèi)部構(gòu)造,這邊通過一個NFS Ganesha對接Ceph RGW的例子來闡述一下代碼IO:

NFS-Ganesha源代碼分析
Figure 2 – NFS Ganesha workflow

以open()為例來,如上圖所示。首先用戶或者應(yīng)用程序開始調(diào)用文件操作,經(jīng)過系統(tǒng)調(diào)用 sys_open(),到達虛擬文件系統(tǒng)層 vfs_open(),然后交給 NFS 文件系統(tǒng)nfs_open()來處理。NFS 文件系統(tǒng)無法操作存儲介質(zhì),它調(diào)用 NFS 客戶端函數(shù)nfs3_proc_open() 進行通信,把文件操作轉(zhuǎn)發(fā)到NFS Ganesha服務(wù)器。

Ganesha中監(jiān)聽客戶端請求的是Dispatcher這個進程:其中的nfs_rpc_get_funcdesc()函數(shù)通過調(diào)用svc_getargs()來讀取xprt(rpc通信句柄)中的數(shù)據(jù),從而得到用戶的具體請求,然后將這些信息注入到reqdata這個變量中。隨后Dispatcher這個線程會把用戶請求-reqdata插入到請求隊列中,等待處理。

Ganesha會選擇一個最空閑的worker thread來處理請求:通過調(diào)用nfs_rpc_dequeue_req()將一個請求從等待隊列中取出,隨后調(diào)用nfs_rpc_execute()函數(shù)處理請求。Ganesha內(nèi)部自建了一個請求/回復緩存,nfs_dupreq_start()函數(shù)會在哈希表中尋找是否有一樣的請求,如果找到,則尋找到對應(yīng)回復,然后調(diào)用svc_sendreply()將回復發(fā)送給客戶端,從而完成一個請求的處理。

如果Ganesha沒有在哈希表中找到一樣的請求,nfs_dupreq_start()這個函數(shù)會在緩存中新建一個請求,隨后調(diào)用service_function(),也就是nfs_open()。FSAL(filesystem abstract layer)收到nfs_open()調(diào)用請求后,會調(diào)用fsal_open2()函數(shù)。由于我們已經(jīng)在初始化階段,在ganesha.conf指定了FSAL為RGW,并且在FSAL/FSAL_RGW/handle.c文件下我們已經(jīng)重定向了FSAL的操作函數(shù),因此fsal_open2()實際會調(diào)用rgw_fsal_open2(),通過使用librgw來進行具體操作。請求完成后,回復會插入到對應(yīng)哈希表中,與請求建立映射,隨后回復通過svc_sendreply()發(fā)送給客戶端。由此完成了sys_open()這個函數(shù)的調(diào)用。

責任編輯:未麗燕 來源: 51CTO.com
相關(guān)推薦

2011-08-01 16:42:24

ibmdwNFS文件系統(tǒng)

2011-02-23 14:54:58

FileZilla

2011-02-23 14:46:21

FileZilla

2011-02-23 14:39:27

FileZilla

2011-02-23 14:16:43

FileZilla

2011-02-23 14:26:28

FileZilla

2011-02-23 15:11:27

FileZilla

2011-02-23 15:26:01

FileZilla

2011-02-23 13:47:33

FileZilla

2011-02-23 15:33:42

FileZilla

2011-02-23 15:21:06

FileZilla

2015-08-28 09:38:51

Linux源代碼分析工具

2015-08-26 17:38:47

Linux源代碼

2009-07-02 13:59:35

JSP后臺

2011-08-24 15:42:38

LUA源代碼

2020-02-24 09:25:33

代碼開發(fā)工具

2021-10-01 12:17:30

Facebook開源工具Mariana Tre

2011-08-24 16:24:54

Lua源代碼

2009-04-20 20:09:15

2012-02-20 14:47:08

JavaPlay
點贊
收藏

51CTO技術(shù)棧公眾號