クラウドネイティブ時代の画像配信ツール-Dragonflyの紹介

WeChatパブリックアカウント「CloudNativeNotes」をフォローすることを歓迎します

バックグラウンド

本日お伝えするのは、アリババの画像配信用オープンソースツールであるDragonflyです。このツールについて最初に知ったのは、大規模なコンテナ画像配信ソリューションの研究によるものかもしれません。当初は、ツールは確かに使用されました画像配布の問題を解決するために、もちろん、それはまだ画像配布に使用されますが、将来的にはこのツールはエンタープライズレベルのファイルツールとして位置付けられます。

トンボが大規模なコンテナ画像配信の問題を解決するための鍵は、p2pテクノロジーの使用です。これは、perr topeerおよびエンドツーエンドに変換されます。コンテナイメージの配布の背景について少し紹介します。ミラーウェアハウスは一般にレジストリを使用して簡単に構築できることを誰もが知っています。もちろん、エンタープライズレベルのミラーウェアハウスもあります。通常の使用では、これら2つのツールは問題ありませんが、大規模なミラープル要求がある場合(たとえば、1000ノードがミラーをプルしている場合)、ハーバーが失敗してハングアップするか、ファイルの取得に時間がかかりすぎる可能性があります。多くのアプリケーションが待っています。港を水平に拡張することは可能だと言う人もいますが、これは恒久的な解決策ではありません。さらに、港のストレージ(s3ストレージなど)をサポートできるかどうかは2つの質問です。これに基づいて、アリはトンボを発売し、ユーバーはクラーケンを発売しました。この記事の焦点は、Krakenが共有する機会があるトンボです。

トンボの原理

トンボの大規模なコンテナ画像配信の鍵は、p2pテクノロジーの使用ですが、どのように解決されますか?大規模なコンテナイメージの配布の問題をもう少し深く分析しますが、解決する必要のあるいくつかの問題があります。

  • 1000ノードがミラーウェアハウスからミラーイメージをプルする必要があります。ウェアハウスサービスがクラッシュしていないと仮定すると、ミラーイメージを取得するのに非常に長い時間がかかるため、これは次のパフォーマンスグラフに反映されます。
  • 1000ノードはミラーウェアハウスからイメージをプルする必要があり、それらの多くは同じイメージをプルするか、またはそれらの多くは同じレイヤーファイルをプルします。したがって、ここでの小さな問題は、同じ画像/レイヤーファイルを繰り返しプルする問題をどのように解決するかです。プログラミングでは、同じコードが2〜3回出現する場合、関数として抽出する必要があります。
  • ミラーが高い同時実行性でプルされると、ミラーウェアハウスのストレージが崩壊する可能性があります。これはストレージシステムによって決定されます。ストレージシステム自体にボトルネックがあります。港を水平方向に拡張しても、保管への圧力は軽減されません。

上記の2つの問題について、トンボのソリューション戦略は次のとおりです。

  • 港の不必要な同時実行圧力を減らすために、同じイメージ/レイヤーファイルを繰り返しプルしないでください。
  • プルされたクライアントノードをストレージとして使用して、外部ファイルサービスを提供し、港へのストレージの圧力を軽減します。
  • ミラーウェアハウスに移動してファイルを取得する代わりに、他のクライアントノードに移動してレイヤーファイルを取得することにより、ファイルの取得速度が向上します。

では、トンボは大規模な画像分布を解決するのにどれほど効果的ですか?
Dragonflyの場合、ファイルのダウンロードを開始するクライアントの数に関係なく、平均ダウンロード時間はほとんど増加しません(実験では、12秒です。つまり、すべてのクライアントがファイル/イメージのダウンロードを完了するのに必要な時間は合計で12秒です)。
wgetの場合、クライアントが増えると、ダウンロード時間は増え続けます。wgetクライアントの数が1200に達すると(次の実験で)、ファイルソースがクラッシュするため、どのクライアントにもサービスを提供できなくなります。
統計結果から、トンボの使用は間違いなく画像取得時間をスピードアップします。これはトンボの公式統計結果です。サンプル数は100ノードからカウントされます。最適化効果は確かに明らかです。100ノード以上でミラーを同時にプルすることが効率的であることを示すのに十分です。

テスト環境 統計結果
トンボサーバー 2 *(24コア64GB 2000Mb / s)
ファイルオリジンサーバー 2 *(24コア64GB 2000Mb / s)
クライアント 4コア8GB200Mb / s
ターゲットファイルサイズ 200MB

ここに画像の説明を挿入

トンボの概念

トンボを詳しく紹介する前に、トンボにいくつかの概念を紹介する必要があります。

  • SuperNode(スーパーノード):これは、主に次の2つの機能を提供する長時間実行プロセスです。
    • ピアノードごとにダウンロードピースのネットワークパスをスケジュールします(シードファイルとして理解できます。シードファイルは、クライアントにどのデータを取得するかを指示します)。ピアノードはスーパーノードに通知するため、superNodeはスケジューラーおよびトラッカーです。ノードピースファイルつまり、スーパーノードはその下にあるすべてのピアノードのピースファイル情報を所有します。
    • CDNサーバーは、ソースから重複データをダウンロードしないように、ソースからデータをキャッシュします。ファイルをダウンロードする前に、degetはスーパーノードに登録し、ダウンロードする情報をスーパーノードdfgetに通知します。スーパーノードはすぐにソースに移動して、これらのターゲットファイルをダウンロードします。
  • Dfget:トンボでファイルを取得するためのツールで、ファイルデータのダウンロードを担当します。wgetと同様に、同時に、彼はピアの役割も果たします(dfget serverコマンドはピアサービスです)。peerロールのノードは、dfgetコマンドを使用するp2pネットワーク内の他のクライアントにデータを送信できます。
  • Dfdaemon:エージェントです。Dfdaemonは、コンテナーエンジン(dockerデーモン)とレジストリ(レジストリまたはハーバー)の間のエージェントとして機能します。これは、ローカルの長時間実行プロセスでもあります。イメージをプルするとき、彼はdockerデーモンによって送信されたリクエストをインターセプトし、非レイヤーファイルのリクエストを直接転送し、レイヤーファイル取得リクエストの場合、インターセプト後にDfgetを使用してこれらのレイヤーファイルをダウンロードします。Dockerは、プロキシパラメータを設定し、dfdaemonに接続して、dfdaemonを有効にする必要があります。
  • P2P:ピアツーピア、分散アプリケーションアーキテクチャ。
  • タスク:タスクはtaskFileに関するメタ情報を格納し、タスクはtaskFile、ピース、およびその他のコンテンツに関するメタ情報を格納します。タスクとタスクIDで識別されるディスク上のファイルの間には、1対1の対応があります。スーパーノードからファイルをダウンロードする場合は、タスクを登録する必要があります。つまり、事前にダウンロードするファイル情報をサーバーに通知する必要があります。実際に操作を実行します。
  • DfgetTask:DfgetTaskは、Dfgetまたは他のクライアントによって開始されたダウンロードプロセスを表します。Dfgetがp2pネットワークからファイルをダウンロードしようとすると、Supernodeはダウンロードプロセスのライフサイクルを管理するためにDfgetTaskオブジェクトを作成します。
  • ピア:P2Pネットワークでは、両方のピアノードがリソースプロバイダーとコンシューマーの両方です。したがって、Dfgetがスーパーノードからタスクのダウンロードを開始する前に、Dfgetは他のピアがP2Pネットワークにダウンロードするためのダウンロードファイルサービスを提供するWebサーバーを起動し、ピア/登録要求をスーパーノードに送信してP2Pネットワークに参加します。この方法でのみ、DfgetはP2Pネットワークからファイルをダウンロードできます。
  • ピース:ピースはダウンロードされるファイルの一部であり、ファイルの一部として解釈できます。トンボでは、ダウンロードしたファイルは完全には送信されませんが、セグメントで送信されます。

トンボのしくみ

トンボには、スーパーノード、dfdaemon、dfgetの3つのコンポーネントがあります。これらのコンポーネントについて以下に説明します。

dfdaemon

dfdaemonは正確に何をしましたか?それはどのような役割を果たしましたか?

dragonflyを使用するノードでは、dockerのプロキシパラメーターは次のように構成されます。

vi /usr/lib/systemd/system/docker.service
[Service]
Environment="HTTP_PROXY=http://10.154.12.120:65001"

http://10.154.12.120:65001アドレスは、dfdaemonサービスのアドレスです。通常、各ノードはdfdaemonサービスを開始し、ノードのdockerプロキシパラメーターはdfdaemonサービスを指します。dockerのプロキシパラメータ設定の役割は、dockerデーモンによって送信されたすべてのリクエストがdfdaemonサービスであるhttp://10.154.12.120:65001に送信され、dfdaemonによって処理されることです。

dfdaemonの傍受

ここに画像の説明を挿入

dfdaemonは、dockerデーモンによって送信されたすべてのリクエストをインターセプトするわけではなく、blob / sha256。*を含むリクエストのみをインターセプトし、他のリクエストのみを転送します。つまり、ミラーをプルすると、dfdaemonはミラーリングされたblobファイルを取得する要求を作成して転送します。

dfdaemonが傍受した後に何が起こるか

DfaemonはDockerデーモン要求をインターセプトしますが、追加の処理のためにインターセプトされるblobファイル要求を除いて、他の要求は転送されるだけです。たとえば、dockerがイメージをプルするとき、このリクエストのようにマニフェストファイル情報を取得する必要があります。dfdaemonは直接転送され、転送結果に従ってdockerデーモンに返されます。マニフェストファイルを取得した後、dockerデーモンはblobファイルの取得を要求します。このような要求は、他の処理のためにdfdaemonによってインターセプトされます。元々、dockerデーモンはレジストリまたはハーバーからblobファイルを取得するために使用されていましたが、現在はdfdaemonによってインターセプトされ、dfdaemonはblobファイルを取得します。では、dfdaemonはどのようにしてBlobファイルを取得するのでしょうか。実際、dfdaemonはblobファイルを直接取得しませんが、dfgetコマンドを使用してblobファイルを取得します。実行されるdfgetコマンドは次のとおりです。

"/opt/dragonfly/df-client/dfget" "-u" "http://10.154.12.121:7999/v2/library/rabbitmq/blobs/sha256:04f8f8815c88ec1ed64a013b039aef36b2ebc09c66101a35a916a2f73bab6ae3" "-o" "/root/.small-dragonfly/dfdaemon/data/5e096c2a-a93c-42c1-a2b6-9f88585a3d92" "--node" "10.142.113.43" "--expiretime" "30m0s" "--alivetime" "5m0s" "-f" "Expires&Signature" "--dfdaemon" "-s" "20MB" "--totallimit" "20MB" "--node" "10.154.12.127,10.154.12.127" "--header" "User-Agent:docker/18.09.9 go/go1.11.13 git-commit/039a7df kernel/4.14.78-300.el7.bclinux.x86_64 os/linux arch/amd64 UpstreamClient(Docker-Client/18.09.2 \\(linux\\))" "--header" "X-Forwarded-For:10.154.12.127"

dfdaemonは、blobファイルをプルするタスクをdfgetに転送します。dfgetコマンドが実行された後、dfdaemonはダウンロードされたblobファイルのコンテンツをローカルで読み取り(dfgetはファイルを取得した後、ファイルをローカルに保存します)、ファイルの内容をに返します。 dockerデーモン、次にdockerデーモンはBlobファイルを取得します。

dfget

上記のように、dfdaemonはdfgetを使用してblobファイルを取得しますが、dfgetはどのように取得しますか?ファイルを直接取得するdockerデーモンとの違いは何ですか?

dfget getblobプロセス

実際、現在のバージョンのdragonflyは主に画像の配布に使用されます。デフォルトでは、blobファイルのリクエストのみをインターセプトして処理します。Dragobflyのdfgetはblobファイルの取得を担当します。次の図は、dfgetがblobファイルを取得するプロセス全体を示しています。
ここに画像の説明を挿入

  • dfgetコマンドの開始後、最初にスーパーノードに登録し、ローカルで必要なblobファイルを通知し、ピアサービスがローカルで開始されたこと、アドレスの数、およびサービスポートの数をスーパーノードに通知します。スーパーノードはtaskIdをdfgetに返します。ここで1つの詳細に注意する必要があります。dfclientにはローカルに複数のピアサービスが存在する可能性があり、ピアサービスはポートを占有するため、で使用する場合は注意が必要です。 k8s?
  • dfgetは、taskIdに従ってスーパーノードを再度要求し、ダウンロードしたblobファイルのシードファイルを取得します。シードファイルは、どのピアノードがどのピースを取得し、これらすべてのピースをダウンロードするかを示し、完成したblobファイルをまとめることができます。次に、blobファイルを一時ディレクトリに保存すると、外部プログラムが一時ディレクトリ内のblobファイルを正しいターゲットディレクトリに転送します(dfdaemonはターゲットディレクトリに移動してファイルを読み取り、dockerデーモンに返します)。

注:ここに質問はありますか?スーパーノードがハングした場合、dfgetはBlobファイルの取得に失敗しますか?この問題は考慮され、ソースコードで解決されました。dfgetがdragonflyを介して完全なデータを取得できない場合、dfgetはソースウェアハウスに直接移動してblobファイルを取得し、一時ディレクトリに保存します。

スーパーノード

スーパーノードは、dragnflyシステム全体で中心的なスケジューリングの役割を果たします。dfgetはスーパーノードからシードファイルを取得する必要があります。スーパーノードが失われた場合、dfgetは元のメソッドを使用してblobファイルを取得し、元のリクエストに戻ることしかできません。したがって、スーパーノードはどのような操作を行いますか。

  • 自分をピアサービスとして登録すると、スーパーノードはファイルサーバーとしてnginxを使用します。
  • 登録、シードファイルの取得、ノードステータスの報告、そしてもちろん関連する監視インターフェイスなどのサービスを提供します。

登録インターフェース

上記の1つは、dfgetが開始されるたびに、スーパーノードに登録され、ローカルで開始されたピアサービス情報をスーパーノードに通知することを学習しました。スーパーノードはこのインターフェイスで何をしますか?

  • dfget登録情報には、ダウンロードが予想されるファイル情報が含まれ、スーパーノードがそれを解析します。
  • スーパーノードは、ダウンロードするファイル情報に従って一意のtaskIdを構成し、それをクライアントに返します。
  • スーパーノードは、ダウンロードされると予想されるファイルサイズを取得し、ピースサイズを計算します。
  • スーパーノードは、目的のファイルを非同期でダウンロードします。
    • ファイルがすでにローカルに存在するかどうかを確認し、存在する場合は終了します。
    • ファイルがローカルに存在しない場合は、ソースウェアハウスに移動してファイルを取得し、スーパーノードにローカルに保存します。
  • dfgetはtaskIdを取得した後、シードファイルを取得するようにスーパーノードに再度要求します。スーパーノードは、ファイルのブロックサイズと数(各ブロックをダウンロードするピアノード)に従って、最終的にシードファイルを形成します。Blobファイルが196Mの場合、各ピースには4Mがあり、合計49個に分割されます。スーパーノードは、49個をダウンロードする場所をdegetに指示します。
  • dfgetが各ピースをダウンロードした後、ダウンロードステータスをスーパーノードに報告し、スーパーノードはその管轄下のピアノードでどのピースが使用可能かを認識します。

ここに画像の説明を挿入

上の写真は私が描いたdragobflyの相互作用図です。相互作用については以下で説明します。まず、展開環境を紹介します。

  • dockerを使用して、スーパーノードを1つのノードにデプロイします。
  • Dockerは、両方のノードにdfclientをデプロイするために使用されます。dfclientは、dfdaemonとdfgetで構成されます。両方のノードのDockerは、プロキシパラメーターで構成されます。

Blobファイルの説明を取得します。

  • ノードでdockerpullコマンドを実行します。
  • ノードのdockerデーモンは、リクエストをローカルのdfdaemonに転送します
  • dfdaemonは、フィルタリング条件に従って転送処理または傍受処理を選択します。
  • dfdaemonはblobファイル要求をインターセプトします。
  • dfdaemonはdfgetを使用してBlobファイルを取得します。
  • ピアとして登録されたdfget;
  • dfgetは、シードファイルを取得するようにスーパーノードに要求します。
  • dfgetは、シードファイルに従ってBlobファイルを取得し、一時ディレクトリに保存します。
  • dfgetはダウンロードステータスをスーパーノードに報告します。
  • dfgetは一時ファイルを介してターゲットディレクトリに移動され、dfgetが実行されます。
  • dfdaemonは、ターゲットディレクトリからファイルの内容を取得し、それをdockerデーモンに返します。
  • BLOBファイルをダウンロードした後、次のBLOBファイルを開始します。

総括する

トンボの利点:

  • 明らかに、特にクライアントが多い場合は、プル速度を高速化します。最適化の効果は明ら​​かであるため、利点については説明しません。

トンボの危険点:

  • トンボには多くのデータ配置動作があり、ディスクから大量のデータが読み取られるため、ディスクのパフォーマンス要件が高いことがわかります。
  • 頻繁な配置と読み取りの動作は、パフォーマンスのさらなる向上を妨げます。
  • ローカルディスクを使用するため、ディスク容量の管理も非常に重要であり、圧倒的です。もちろん、トンボは定期的かつ定量的にディスクをクリーンアップします。

注:Dragondlyは、大規模な同時実行シナリオに適しています。使用シナリオで100ノードが同時にイメージをプルする必要がない場合は、Dragonflyを使用しないことをお勧めします。水平方向に拡張されたハーバーを使用するだけで十分です。結局のところ、トンボを使用すると、ある程度の複雑さがもたらされます。

上記のリスクポイントについては、dragonfly2.0で解決され、ストリームモードになります。また、トンボ2.0には予熱機能があります。要するに、このコンポーネントの開発は正しい方向に進んだばかりであり、まだ長い道のりがあります。

おすすめ

転載: blog.csdn.net/u013276277/article/details/113102551