PIDの再考1.パート2

目次






ソケットサービスの並列化



ブート時のこのタイプの同期は、ブートプロセスのかなりの部分のシーケンス(サービスの順次開始)につながります。 同期と一貫性の代価を取り除くことができたらクールではないでしょうか? まあ、実際にそれを取り除くことができます。 これを行うには、サービス(デーモン)が実際に相互に必要とするものと、サービスの起動が遅れる理由を理解する必要があります。 従来のUnixデーモン(サービス)の場合、この質問に対する答えは1つだけです。サービスを提供するデーモンが接続を受け入れる準備ができるまで待機します。 これは通常、ファイルシステム上のAF_UNIXソケットですが、 AF_INETソケットにすることもできます。 例:D-Busクライアントは/ var / run / dbus / system_bus_socketに接続し、syslogクライアントは/ dev / log待機CUPSクライアントは/var/run/cups/cups.sockを待機NFSマウントポイントはwait / varを待機します /run/rpcbind.sockおよびポートマッパーのポートportなど 考えてみてください。実際、他の人が待っていることは1つだけです。



これが後続の基礎であるため、もう一度言いますが、言い換えると、 syslogとさまざまなsyslogクライアントを同時に実行すると、上の図で何が起こるかは、クライアントからのメッセージがbuffer / dev / log 。 バッファがオーバーフローするまで、クライアントはsyslogのロードが完了するまで待つべきではなく、すべてのメッセージをキューからプルして処理します。 別の例: D-Busと複数のクライアントを同時に起動します。 したがって、同期要求がバスに送信される場合、応答も同期的に期待され、クライアントはブロックされますが、この1つのクライアント(同期要求を送信する)のみが、 D-Busが要求をキャッチするまでそしてそれを処理しません。



一般に、カーネルソケットバッファーは並列化の向上に役立ち、ユーザー空間の介入なしに、カーネルによって順序付けと同期が行われます! ただし、デーモンがロードされるまですべてのソケットが使用可能な場合、依存関係管理も冗長になります(少なくとも2次)。デーモンが別のデーモンを必要とする場合は、接続します。 別のデーモンがすでに実行されている場合、すぐに成功します。 しかし、別のデーモンがまだ実行されていないが、起動中の場合、最初のデーモンは同期過成長を​​起こすまで待機するべきではありません。 別のデーモンがまったく実行されていない場合でも、自動的に起動できます。 最初のデーモンの観点からは違いはないため、依存関係管理はほとんど不要またはセカンダリになり、それらはすべて最適に並列化され、オプションでオンデマンドでロードされます。 一番上では、ソケットは使用可能なままであるため、まだ冷えていますが、実際には、デーモンは一時的に使用できなくなる場合があります(「崩壊」が原因である可能性があります)。 実際、顧客に通知したり、顧客からの要求を失ったりすることなく、開始、停止(または転倒)、再開、再開(など)することができます。



休憩して別のコーヒーを注いで、さらに興味深い素材が待っていることを確認してください。



しかし、最初はいくつかのことを明確にしましょう。これは新しいロジックのようなものですか? いいえ、もちろんありません。 このように動作する最も有望なシステムは、Appleのlaunchdです。MacOSでは、ソケットをリッスンし、すべてのデーモンを起動するとlaunchdになります。 したがって、すべてのサービス(デーモン)は、依存関係を構成しなくても、並行して開始できます。 そして、これは実際に独創的なソリューションであり、MacOSが素晴らしい起動時間を提供する主な理由です。 launchdのメンバーが何をどのように行うかを説明するこのビデオを強くお勧めします。 残念ながら、このアイデアはAppleキャンパス以外では認識されませんでした。



アイデアは実際にlaunchdよりも古いです。 launchd以前は、尊敬されているinetdは同様のスタイルで機能していました。ソケットは主に、実際のサービス(いわばメイン機能)を開始するデーモンで作成され、ソケットファイル記述子をexec()関数に渡します。 ただし、 inetdの焦点は、主にローカルサービスとデーモンではなく、インターネットサービスに焦点を合わせていました(後の実装ではAF_UNIXソケットもサポートしています)。 inetdは 、システムブートプロセスの並列化や依存関係の解決のためのツールではありませんでした。



TCPソケットの場合、inetdは主に次のように使用されました。着信接続ごとに新しいデーモンインスタンスが作成されました。 これは、接続ごとに新しいプロセスが初期化および作成されたことを意味します。これは、高性能サーバーのレシピとは言えません。 ただし、最初からinetdは別の操作モードもサポートしており、最初の接続で単一のデーモンが作成され、このインスタンスのみが後続の接続を受け入れました(これはinetd.confの wait / nowaitオプションの 目的であり、このドキュメントは非常に不十分に文書化されていましたオプション、残念ながら)。 各接続でデーモンを実行すると、inetdの評判に悪影響を与え、ブランディングが遅すぎました。 しかし、これは完全に真実ではありません。



バスサービスの並列化



最近のLinuxサービスは、フラットAF_UNIXソケットではなくD-Busを介してサービスを提供する傾向があります。 さて、問題は、従来のソケットサービスと同じ論理並列化ロジックを適用できますか? はい、できます。D-Busにはこれに必要なすべてのメカニズムが既に備わっています。アクティベーションバスを使用すると、サービスに最初にアクセスしたときにサービスを開始できます。 アクティベーションバスは、 D-Busサービスのプロバイダーとコンシューマーを同時に起動するために必要な各リクエストの最小同期機能も提供します:AvahiをCUPSと同時に実行したい場合(注意: CUPSAvahiを使用してmDNS / DNS-SDプリンターを検出します)これらを同時に実行できます。バスアクティベーションロジックを介してCUPSが Avahiよりも速い場合、 D-Busバスにサービス名を設定するためにAvahiがビジーである間にリクエストをキューに入れます。



したがって、この方法で:ソケットベースのサービスアクティベーションとバスベースのサービスアクティベーションにより、すべてのデーモンを同期せずに並行して実行できます。 また、アクティベーションにより、サービスの「遅延」ロードを実行できます。サービス(デーモン)がほとんど使用されない場合、システムブート中に開始する代わりに、バス上のソケットまたは名前への最初のアクセスで開始できます。



そして、それが素晴らしくなければ、何が素晴らしかったのかわかりません!



継続するには...



All Articles