web-dev-qa-db-ja.com

ドメインソケットを介して送信される単一パケットのサイズの実際的な制限は何ですか?

一般的なサーバークライアントプログラム用に作成されたUnixドメインソケットがあると仮定します。クライアントはソケットを介して10GBのバッファーを送信し、その間サーバーによって消費されます。

OS(Linux/BSD)は10GBバッファを多くのパケットに分割して送信/消費しますか、それとも一度に送信されますか?

ドメインソケットの10GBバッファを一度に送信できない場合、単一のパケットの実際的なサイズ制限は何ですか?

制約:

  • プログラムはLinux 2.6.32+とFreeBSD 9+の両方で実行されます
  • 送信されるバッファのサイズは、3バイトから最大10 GBの範囲です。
19
user972946

Unixソケットで送信できるパケットの最大サイズを決定するいくつかの要因があります。

  1. _wmem_max_ソケット送信バッファー最大サイズカーネル設定。これは、setsockopt (SO_SNDBUF)を使用して設定できる送信バッファーの最大サイズを決定します。現在の設定は_/proc/sys/net/core/wmem_max_から読み取ることができ、_sysctl net.core.wmem_max=VALUE_を使用して設定できます(設定を_/etc/sysctl.conf_に追加して、再起動後も変更を永続化します)。この設定は、Unixソケットだけでなく、すべてのソケットとソケットプロトコルに適用されることに注意してください。

  2. Unixソケットに(SOCK_DATAGRAMを使用して)複数のパケットが送信される場合、ブロックせずに送信できるデータの最大量は、ソケット送信バッファーのサイズ(上記を参照)Unixソケットの未読パケットの最大数(カーネルパラメータ_net.unix.max_dgram_qlen_)。

  3. 最後に、パケット(SOCK_DATAGRAM)には、連続したメモリが必要です( に従って、Linuxで送信できるAF_UNIXデータグラムメッセージの最大サイズは? )。カーネルで利用可能な連続メモリの量は、多くの要因(システムのI/O負荷など)に依存します。

したがって、アプリケーションのパフォーマンスを最大化するには、大きなソケットバッファーサイズ(ソケット書き込みシステムコールによるユーザー/カーネルスペースのコンテキスト切り替えを最小限に抑えるため)と大きなUnixソケットキュー(プロデューサーとコンシューマーを可能な限り切り離すため)が必要です。 )。ただし、ソケット送信バッファーのサイズとキューの長さの積は、カーネルが連続したメモリ領域を使い尽くすほど大きくてはなりません(書き込みエラーの原因)。

実際の数値は、システム構成と使用法によって異なります。テストによって制限を決定する必要があります... 256Kbで_wmem_max_を、32で_max_dgram_qlen_で開始し、問題が発生し始めるまで_wmem_max_を2倍にします。プロデューサとコンシューマのアクティビティのバランスをある程度とるために_max_dgram_qlen_を調整する必要があります(プロデューサがコンシューマよりもはるかに高速または低速の場合、キューサイズはあまり影響しません)。

プロデューサーは、setsockopt (SO_SNDBUF)の呼び出しでソケット送信バッファーサイズを_wmem_max_バイトに具体的に設定する必要があり、データを_wmem_max_バイトチャンクに分割する必要があります(コンシューマーはそれらを再組み立てする必要があります)。

最良の推測:実用的な制限はwmem_max〜8Mbとunix_dgram_qlen〜32前後になります。

27
isedev

ドメインソケットにはそれ自体「パケット」はありません。 tcp "streams"またはudp "datagrams"のセマンティクスは、カーネルを使用してシミュレートされたものであり、ユーザー空間アプリと同様に見えますが、それは、可能な限りです。メカニズムは、ネットワークプロトコルを使用するネットワークソケットほど複雑ではありません。ここで本当に興味があるのは、カーネルがどれだけバッファリングするかです。

プログラムの観点からは、それは本当に重要ではありません。ソケットはパイプまたはFIFOと考えてください。バッファーがいっぱいになると、ブロックします。ソケットが非ブロッキングの場合、短い書き込み(ストリームを想定)またはEAGAINのエラーが発生します。これは、バッファのサイズに関係なく当てはまります。ただし、getsockoptを使用してバッファサイズをクエリし、setsockoptを使用してそのサイズを増やすことができるはずですが、10 GB近くになるとは思いません。

または、sendfileを参照することもできます。

2
Duck

ここには2つのアイデアがあります。 1つはSOCK_DGRAMを使用している場合に送信されるパケットのサイズで、もう1つはドメインソケットのバッファのサイズです。これは、ドメインソケットで設定された変数に依存します。サイズは、それがメモリファイルソケットかどうかによって異なります。

0
user2691041