NFS-Ganesha ソースコード分析

NFS-Ganesha ソースコード分析

1. NFSv4の概要

NFS プロトコル (NFSv2) は、もともと 1984 年に Sun Microsystems によって設計および提案されました。いくつかの欠点があったため、その後、複数の企業が共同で NFSv3 を立ち上げました。 NFSv4 の時点では、開発は完全に IETF によって主導されており、設計目標は次のとおりでした。

  • – インターネット経由のNFSアクセスとパフォーマンスの向上
  • – セキュリティを提供する
  • – より強力なクロスプラットフォーム操作
  • – 将来の拡張に便利

NFSv4 はキャッシュ機能、スケーラビリティ、高可用性において大きな進歩を遂げたことがわかります。以前のバージョンのステートレス性を放棄し、強力なステートメカニズムを採用しています。クライアントとサーバーは複雑に相互作用し、サーバー側での負荷分散が保証され、クライアントまたはサーバーの RTO が削減されます。

セキュリティの面では、NFSv4 は接続指向プロトコルを使用し、RPCSEC_GSS の使用を強制し、RPC ベースのセキュリティ メカニズムを提供します。以前のバージョンで使用されていた UDP は廃止され、TCP が採用されました。 NFSv4 はマイナー バージョンを通じて拡張をサポートします。 NFSv4.1 は、RDMA、pNFS パラダイム、ディレクトリ委任などの機能をサポートしていることがわかります。

2. NFS-Ganeshaの4つの利点

2007 年頃、CEA の大規模なコンピュータ センターでは、毎日約 10 TB の新しいデータが生成されました。 CEA はこのデータを HSM で構成された HPSS に配置し、これらの HSM 自体が NFS インターフェイスを提供しました。しかし、開発者は、実稼働環境での HSM と NFS のブリッジにまだ多くの問題があることに気づいたため、NFS インターフェースが HPSS とより適切に連携するように新しい NFS デーモンを作成することにしました。

上記の問題を解決することに加えて、開発チームは他の目標も設定しました。

  • – 基盤となるファイルシステムのブロックを回避するために、数百万のデータキャッシュを管理できます。
  • – HPSSに加えて、他のファイルシステムにも接続できます
  • – NFSv4をサポートし、適応性、拡張性、セキュリティなどの機能を実現
  • – ソフトウェアによるパフォーマンスのボトルネックを根本的に解決
  • – オープンソース
  • – Unixシステムをサポート

こうして、NFS-Ganesha が誕生しました。 NFSv4 のカーネル バージョンを置き換えるために使用されるものではありません。それどころか、NFS Ganesha はまったく新しいプログラムです。 NFSv4 のカーネル バージョンと比較すると、Ganesha のパフォーマンスは劣るかもしれませんが、ユーザー空間ベースのアプローチにより、より興味深い機能がもたらされます。

柔軟なメモリ割り当て

まず、ユーザー空間プログラムは、プログラムが使用するために大量のメモリを割り当てることができます。このメモリは、ソフトウェアの内部キャッシュを構築するために使用できます。テストの結果、100 万レベルのデータ キャッシュを実現するには 4 GB しか必要ありません。一部の x86_64 プラットフォーム マシンでは、さらに大きなメモリ (16 ~ 32 GB) を割り当てて、数千万のデータ キャッシュを実現することもできます。

携帯性の向上

NFS Ganesha がカーネル空間である場合、NFS Ganesha の内部構造は特定の OS にのみ適応でき、他の OS に移植することは困難です。もう 1 つの考慮事項はコード自体です。異なるプラットフォームでコンパイルされ実行される製品は、単一のプラットフォームで開発された製品よりも安全です。開発者としての私たちの経験から、単一のプラットフォームのみで開発すると、開発の後半で困難が生じることがわかりました。リソースが同じではないため、Linux では簡単に検出できないバグが頻繁に発生します。

もちろん、移植性とは、NFS Ganesha が異なる OS 上で実行できるだけでなく、異なるファイル システムに適応できることも意味します。 NFSv2 および NFSv3 では、セマンティック設計が Unix タイプのファイルシステムに偏っているため、非 Unix タイプのファイルシステムに適応することは基本的に不可能です。この状況は NFSv4 では大きく変わりました。 NFSv4 のセマンティック設計の出発点は、NFS が可能な限り多くの異なるファイル システムに適応できるようにすることであり、これによりファイル/ディレクトリ属性パラメータの抽象化が強化されます。 Ganesha はもともと、NFSv4 のすべての機能を実装できる汎用 NFSv4 サーバーとして設計されたため、さまざまなファイルシステムに適応する必要もあります。この機能をカーネルに実装するのは簡単ではありません (内部およびプログラミング上の制限が多い) が、ユーザー空間で実装する方が便利です。

より便利なアクセスメカニズム

カーネル内の NFSv4 がユーザー空間のサービスにアクセスするのはあまり便利ではないため、ユーザー空間サービスのブリッジを解決するために rpc_pipefs メカニズムを導入し、セキュリティを管理するために kerberos5 を使用するか、ユーザー名の変換を実行するために idmapd デーモンを使用します。ただし、Ganesha ではこれらは必要なく、通常の API を使用して外部にサービスを提供します。

FUSEとのインターフェース

NFS Ganesha はユーザー空間で実行されるプログラムであるため、一部のユーザー空間ファイルシステム (FUSE) もサポートしており、カーネルの助けを借りずに FUSE を NFS に直接マウントできます。

3. NFS-Ganeshaフレームワークの簡単な分析

NFS Ganehsha は、完全にオープン ソースのフリー ソフトウェアを使用して開発されています。 Linux には膨大なシステム プログラミング開発リソースがあるため、他の Unix システムよりも開発が容易です。


図 1 – NFS Ganesha 階層化アーキテクチャ

上の図から、Ganesha はモジュール ベースのプログラムであり、各モジュールが独自のタスクと目標を担当していることがわかります。開発チームは、その後の拡張の利便性を確保するために、コードを書く前に各モジュールを慎重に設計しました。たとえば、キャッシュ管理モジュールはキャッシュの管理のみを担当し、キャッシュ管理モジュールに加えられた変更は他のモジュールに影響を与えることはできません。そうすることで、各モジュール間の結合が大幅に減少します。開発の初期段階では難しいように思えますが、中期および後期段階でははるかに便利になります。各モジュールは、開発、検証、テストのために、異なる開発者に個別に引き渡すことができます。

ガネーシャのコアモジュール

  • – メモリ マネージャー: Ganesha のメモリ管理を担当します。
  • – RPCSEC_GSS: RPCSEC_GSS を使用したデータ転送を担当し、通常は krb5、SPKM3、または LIPKEY を使用してセキュリティを管理します。
  • – NFSプロトコルモジュール: NFSメッセージ構造の管理を担当
  • – メタデータ(Inode)キャッシュ:メタデータのキャッシュ管理を担当します
  • – ファイルコンテンツキャッシュ:データキャッシュ管理を担当
  • – ファイル システム抽象化レイヤー (FSAL):インターフェイスを介して名前空間へのアクセスを提供する非常に重要なモジュール。アクセスされたオブジェクトは、inode キャッシュとファイル コンテンツ キャッシュに配置されます。
  • – ハッシュ テーブル:赤黒木に基づくハッシュ テーブルを提供します。このモジュールはGaneshaでよく使われます。

メモリ管理

Ganesha アーキテクチャのほとんどのモジュールは動的なメモリ割り当てを実行する必要があるため、Ganesha を開発する場合、メモリ管理は大きな問題となります。たとえば、NFS 要求を管理するスレッドでは、要求された結果を格納するためのバッファを割り当てる必要がある場合があります。通常の LibC malloc/free 呼び出しを使用すると、一部のモジュールが大きなバッファを割り当て、他のモジュールが小さなバッファを使用するため、メモリが断片化されるリスクがあります。これにより、プログラムが使用するメモリの一部がディスクにスワップされ、パフォーマンスが急速に低下する可能性があります。

したがって、Ganesha には、各スレッドに必要なメモリを割り当てるための独自のメモリ マネージャーがあります。メモリ マネージャーは、カーネルで使用されるものと同じメモリ割り当てアルゴリズムである Buddy Malloc アルゴリズムを使用します。 Madvise はメモリ アロケータ内で呼び出され、関連するページを移動しないように Linux メモリ マネージャを制御します。高いパフォーマンスを維持するために、Linux に大きなメモリ ブロックを要求します。

スレッド管理

CPU の管理はメモリの管理よりも簡単です。 Ganesha は多数のスレッドを使用するため、同時に数十のスレッドが並行して動作している場合があります。開発チームはここでスレッドを管理するために多くの POSIX 呼び出しを使用し、Linux スケジューリング プロセスが各スレッドを個別に処理できるようにして、負荷がすべての CPU をカバーできるようにしました。

開発チームはデッドロック状況も考慮しました。ミューテックス ロックの導入によりリソース アクセスの競合を防ぐことはできますが、その結果、多数のスレッドがデッドロックに陥ると、パフォーマンスが大幅に低下します。そのため、開発チームは読み取り/書き込みロックを採用しましたが、読み取り/書き込みロックはシステムごとに異なる可能性があるため、読み取り/書き込みロックの変換を完了するためのライブラリが開発されました。

スレッド プール内に同時にスレッドが多すぎると、スレッド プールはパフォーマンスのボトルネックになります。この問題を解決するために、Ganesha は各スレッドに個別のリソースを割り当てます。これにより、各スレッドがガベージ コレクション自体を処理し、定期的にリソースを再構築する必要もあります。同時に、「ディスパッチャ スレッド」は、同時にガベージ コレクションを実行するスレッドが多すぎるのを防ぐためのメカニズムも提供します。キャッシュ層では、ガベージコレクションは複数のステップに分割され、各ステップは個別のエージェントによって処理されます。実稼働環境でテストした結果、この設計は適切であることがわかりました。

ハッシュテーブル

関連付け検索機能は Ganesha で広く使用されています。たとえば、オブジェクトの親ノードと名前を通じてオブジェクトのメタデータを検索したい場合がよくあります。したがって、Ganesha の全体的な高いパフォーマンスを確保するには、関連付け検索機能が非常に効率的である必要があります。

この目標を達成するために、開発チームは、追加/更新操作後に自動的に再バランスをとる赤黒木を使用しました。単一の赤黒ツリーではプロセス呼び出しの競合 (複数のプロセスが同時に追加/更新し、同時再バランスが発生) が発生するため、赤黒ツリーに読み取り/書き込みロックが追加されると、パフォーマンスのボトルネックが発生します。そのため、開発チームはこの問題を解決するために赤黒木配列を設計し、2 つのスレッドが同時に赤黒木にアクセスする可能性を減らして、アクセスの競合を回避しました。

大規模なマルチスレッドデーモン

Ganesha を実行するには、多くのスレッドを同時に動作させる必要があるため、設計の最初に大規模なスレッド デーモンを設計することが特に重要です。スレッドは次の異なるタイプに分類されます。

  • – ディスパッチャ スレッド: 着信 NFS および MOUNT 要求をリッスンして配布するために使用されます。最もアイドル状態のワーカー スレッドを選択し、そのワーカー スレッドの保留リストに要求を追加します。このスレッドは、過去 10 分以内の要求に対する応答を保持し、同じ命令 (ハッシュ テーブルに格納され、RPC Xid4 値でアドレス指定されている) が 10 分以内に受信された場合、以前の要求応答が返されます。
  • – ワーカー スレッド: Ganesha のコア スレッドであり、最もよく使用されるスレッドです。ワーカー スレッドはディスパッチャのスケジュールを待機し、要求を受信した後デコードし、inode キャッシュ API とファイル コンテンツ API を呼び出して要求操作を完了します。
  • – 統計スレッド: 各モジュールのスレッド統計を収集し、さらなる処理のために定期的に CSV 形式でデータを記録します。
  • – 管理ゲートウェイ: キャッシュのクリア、FSAL ストレージへのデータの同期、プロセスのシャットダウンなどのリモート管理操作に使用されます。Ganeshaadmin は、管理ゲートウェイ スレッドと対話するように特別に設計されたプログラムです。

キャッシュ処理

前述のように、Ganesha はメタデータとデータ キャッシュを構築するために大量のメモリを使用します。メタデータ キャッシュから始めましょう。メタデータ キャッシュは、キャッシュ Inode レイヤー (MDCache レイヤー) に保存されます。各インスタンスは、名前空間内のインスタンス (ファイル、シンボリック リンク、ディレクトリ) に対応します。キャッシュ Inode レイヤー内のこれらのインスタンスは FSAL 内のオブジェクトに対応し、FSAL から読み取られたオブジェクト構造をメモリにマッピングします。

キャッシュ Inode レイヤーは、メタデータと対応する FSAL オブジェクト ハンドルをハッシュ テーブルに格納して、エントリを関連付けます。 Ganesha の初期バージョンでは、メタデータのキャッシュに「ライトスルー」キャッシュ戦略を使用します。インスタンスの属性は、一定期間(定義可能)が経過すると期限切れになり、その後インスタンスはメモリから削除されます。各スレッドには LRU (Least Recently Used) リストがあります。各キャッシュ インスタンスは、1 つのスレッドの LRU 内にのみ存在できます。スレッドがインスタンスを取得した場合、元のスレッドは LRU リスト内の対応するエントリを解放する必要があります。

各スレッドは独自のガベージ コレクションを担当し、ガベージ コレクションが開始されると、スレッドは LRU リストの最も古いエントリから実行を開始します。次に、特定のガベージ ポリシーを使用して、エントリを保持するか削除するかを決定します。メタデータ キャッシュは非常に大きい (最大数百万エントリ) ことが想定されているため、割り当てられたメモリの 90% を超えるまでガベージ コレクションは発生しません。 Ganesha は、ノードがディレクトリを表し、リーフがファイルとシンボリック リンクを表すキャッシュされた「ツリー トポロジ」に、可能な限り多くの FSAL オブジェクトを配置します。リーフのガベージコレクションはノードよりも早く行われ、ノードにリーフがない場合にのみガベージコレクションが実行されます。

ファイル コンテンツ キャッシュ データ キャッシュは、Inode キャッシュから独立していません。オブジェクトのメタデータ キャッシュとデータ キャッシュは 1 対 1 で対応します (データ キャッシュはメタデータ キャッシュの「サブキャッシュ」です)。これにより、キャッシュの不整合が発生する状況を回避できます。ファイルの内容は、ローカル ファイル システムの専用ディレクトリにキャッシュされます。データ キャッシュ インスタンスは、インデックス ファイルとデータ ファイルの 2 つのファイルに対応します。データ ファイルはキャッシュされたファイルと同等です。インデックス ファイルには、重要な FSAL ハンドルを含むメタデータ情報が含まれています。インデックス ファイルは主にデータ キャッシュを再構築するために使用されます。サーバーがクラッシュし、キャッシュが完全にクリアされない場合、FSAL ハンドルはインデックス ファイル内の情報を読み取ってメタデータ キャッシュを再構築し、データ ファイルにポイントしてデータ キャッシュ インスタンスを再構築します。

キャッシュが不足している場合、ワーカー スレッドは LRU リスト内の長時間開かれていないインスタンスをチェックし、メタデータ キャッシュのリサイクルを開始します。メタデータ キャッシュのリサイクルが開始されると、データ キャッシュのガベージ コレクションも同時に実行されます。ファイル キャッシュ インスタンスをリサイクルする場合、メタデータ キャッシュはデータ キャッシュがファイル インスタンスを認識するかどうかを問い合わせます。認識されない場合は、データ キャッシュが無効であることを意味し、メタデータのリサイクルは正常に続行され、インスタンス キャッシュのリサイクルが完了します。認識された場合、対応するファイル キャッシュとデータ キャッシュがリサイクルされ、対応するメタデータ キャッシュもリサイクルされます。これにより、データ キャッシュの有効なインスタンスがリサイクルされなくなります。

このアプローチは Ganesha のアーキテクチャ設計と一致しており、ワーカー スレッドはメタデータ キャッシュとデータ キャッシュの両方を管理でき、両者は常に一貫性が保たれます。 Ganesha は、小さなファイルのデータ キャッシュに「ライトバック」戦略を使用します。ファイルが大きい場合は、キャッシュを経由せずに直接読み取られます。改善できる点は、大きなファイルを分割してキャッシュに格納し、読み取りと書き込みの効率を向上できることです。

FSAL (ファイル システム抽象化レイヤー)

FSAL は非常に重要なモジュールです。 FSAL 自体は、Inode キャッシュとファイル コンテンツ キャッシュの共通インターフェイスを提供し、要求を受信すると特定の FSAL (FSAL_SNMP、FSAL_RGW など) を呼び出します。 FSAL 内のオブジェクトは FSAL ハンドルに対応します。 FSAL のセマンティック設計は NFSv4 と非常に似ているため、Ganesha に適応する新しい FSAL API を開発して記述することが可能です。 Ganehsa パッケージは、FSAL ソース コード テンプレートも提供します。

4. 例

NFS Ganesha の内部構造を多数紹介しました。ここでは、NFS Ganesha を Ceph RGW に接続する例を使用して、コード IO を説明します。


図 2 – NFS Ganesha ワークフロー

上図に示すように、open() を例に挙げます。まず、ユーザーまたはアプリケーションがファイル操作の呼び出しを開始します。これはシステム コール sys_open() を経由して仮想ファイル システム層 vfs_open() に到達し、その後、処理のために NFS ファイル システム nfs_open() に渡されます。 NFS ファイル システムはストレージ メディアを操作できません。 NFS クライアント関数 nfs3_proc_open() を呼び出して通信し、ファイル操作を NFS Ganesha サーバーに転送します。

Ganesha でクライアント要求をリッスンするプロセスは Dispatcher プロセスです。nfs_rpc_get_funcdesc() 関数は、svc_getargs() を呼び出して xprt (rpc 通信ハンドル) 内のデータを読み取り、ユーザーの特定の要求を取得し、この情報を reqdata 変数に挿入します。次に、ディスパッチャ スレッドはユーザー要求 -reqdata を要求キューに挿入し、処理を待機します。

Ganesha は、要求を処理するために最もアイドル状態のワーカー スレッドを選択します。つまり、nfs_rpc_dequeue_req() を呼び出して待機キューから要求を取り出し、次に nfs_rpc_execute() 関数を呼び出して要求を処理します。 Ganesha は内部にリクエスト/応答キャッシュを構築しました。 nfs_dupreq_start() 関数は、ハッシュ テーブルで同じ要求を検索します。見つかった場合は、対応する応答を見つけ、svc_sendreply() を呼び出してクライアントに応答を送信し、要求の処理を完了します。

Ganesha がハッシュ テーブルで同じ要求を見つけられない場合、nfs_dupreq_start() 関数はキャッシュに新しい要求を作成し、service_function() (nfs_open()) を呼び出します。 nfs_open() 呼び出し要求を受信すると、FSAL (ファイルシステム抽象レイヤー) は fsal_open2() 関数を呼び出します。初期化フェーズで ganesha.conf に FSAL を RGW として指定し、FSAL/FSAL_RGW/handle.c ファイルで FSAL の操作関数をリダイレクトしているため、fsal_open2() は実際には rgw_fsal_open2() を呼び出して、librgw を使用して特定の操作を実行します。要求が完了すると、応答は対応するハッシュ テーブルに挿入され、要求にマップされ、その後、応答は svc_sendreply() を介してクライアントに送信されます。これにより、sys_open() 関数の呼び出しが完了します。

<<:  SSDクラウドハードディスクが利用可能になりました。超高性能を割引価格でお楽しみください

>>:  マルチメディア シングス プレーヤーが、より適切なオーディオおよびビデオ プレーヤーの選び方について語ります

推薦する

キーワードを最適に一致させる方法

多くのウェブマスターは、キーワードの組み合わせはほんの少しあれば十分だと考えています。実際、キーワー...

evlgaming-512m メモリ KVM/10g ハードディスク/月額 3.5 米ドル

バジェット バージョンでは、Xeon E3-1230v2 U とハード ディスク RAID 1 が使...

Microsoft Azure Kubernetes コンテナ サービスが中国で開始、プレビュー開始

2018 年 11 月 13 日、上海 - Linux Foundation が主催する毎年恒例のオ...

経験談共有: 80年代以降の負け犬のウェブマスターが1日8,000ドル稼ぐ方法

数日前、ウェブマスターのウェブサイトを閲覧していたところ、1日に6000元を稼いだと堂々と自慢してい...

「分散キャッシュの詳細」 - 「独自のキャッシュを作成する」

【51CTO.comオリジナル記事】 [51CTO オリジナル記事、パートナーサイトに転載する場合は...

推奨: Egihosting 超大型ハードドライブ VPS

Egihosting はストレージベースの VPS を開始しました。必要な場合はぜひご覧ください。デ...

inceptionhosting-5.35 ユーロ/2g メモリ/XEN/50g ハードディスク/1t トラフィック

Inceptionhosting のマイアミ データ センターの XEN VPS が、大容量メモリと...

主流のオンラインマーケティングプロモーションチャネル17の機能をまとめました。

主流のオンラインマーケティングプロモーションチャネルを17個整理しました。オンラインプロモーションチ...

fliphost-新しいウェブサイトデザイン-VPSプロモーション/512MメモリKVM/月額6.5ドルの支払い

設立から2年以上経ったVPSビジネスを展開するFliphostが、ついにウェブサイトをリニューアルし...

Kubernetes のマルチコンテナ Pod 設計パターン

[[436040]] 【51CTO.com クイック翻訳】ポッドKubernetes では、Pod ...

Dogyun:「香港-CMI」データセンターの「CMI」ラインVPSの簡単なレビュー

Dogyun の「Hong Kong-CMI」シリーズの VPS は 50Mbps の帯域幅を提供し...

SEOの観点からH1タグの配置を分析する

HTML コードについて少しでも知識のある最適化担当者であれば、サイトの最適化における H1 タグの...

PaaS はクラウド コンピューティングの具体的な表現でしょうか?

PaaS は Platform as a Service の略で、サービスとしてのプラットフォームを...

世界のモバイル市場予測

最近、App Annie は「2020 年の世界モバイル市場予測」レポートを発表しました。このレポー...