TCPオプションSO_LINGER



Tcp Option So_linger



http://blog.chinaunix.net/uid-29075379-id-3904022.html
SO_LINGERオプションを使用すると、チームにhaproxyを再構築させるときに、リセット(RST)クライアント接続のバグが発生しました。

SO_LINGER効果
TCP接続を閉じるための関数close()の動作を設定します。デフォルトのclose()の動作では、データがソケット送信バッファーに残っている場合、システムはデータを相手に送信し続け、確認応答を待ってから戻ります。



このオプションを使用すると、このデフォルトの動作を次の2つに設定できます。
a。通常のFIN | ACK | FIN | ACK 4パケットを使用する代わりに、RSTパケットを送信して、接続をすぐに閉じ、接続を閉じます。送信バッファに未送信のデータがある場合、そのデータは破棄されます。パーティのTCP状態をアクティブにシャットダウンすると、TIMEWAITがスキップされ、直接CLOSEDになります。インターネット上の多くの人々は、これを使用して、サーバー上に多数のTIMEWAIT状態があるソケットの問題を解決したいと考えています。ただし、これは良い考えではありません。このシャットダウン方法の目的はここにはありません。実際の使用法は、アプリケーション層のサーバーの要件にあります。
b。接続のシャットダウンのタイムアウトを設定します。データがソケット送信バッファに残っている場合、プロセスはスリープ状態になり、カーネルはデータの送信を試みるタイミング状態に入ります。
タイムアウトの前に、すべてのデータが送信され、相手によって確認された場合、カーネルは通常のFIN | ACK | FIN | ACK 4パケットで接続を閉じ、close()は正常に戻ります。
それでもデータの送信に失敗し、タイムアウトしても正常に確認できない場合は、上記のを使用して接続を閉じます。 Close()はEWOULDBLOCKを返します。

SO_LINGERオプションは、次の構造を使用します。



struct linger { int l_onoff int l_linger }

l_onoffが0の場合、オプションはオフになり、l_lingerの値は無視され、close()は上記のデフォルトメソッドによって接続を閉じます。

L_onoffはゼロ以外、l_lingerは0、close()は上記のモードで接続を閉じます。

L_onoffはゼロ以外、l_lingerはゼロ以外、close()は上記のbとの接続を閉じます。



SO_LINGERをどのように使用しても、サーバープログラムが実際に希望どおりに実行されていることを確認するには、多くの忍耐が必要です。このオプションは、小さな要求を処理するサーバーの動作にほとんど影響を与えないためです。単純な機能テストでは、その動作を検証することは困難です。オンライン回線の後で量が多い場合は、問題が発生している可能性があります。そのため、サーバーはすぐにオフラインになり、シミュレートされた実際のシーンの圧力測定を大量に行うことで、その正確性を確認できます:)

https://www.cnblogs.com/javawebsoa/p/3201324.html

SO_LINGERオプションは、遅延オフ時間を設定し、ソケット送信バッファー内のデータが送信されるのを待つために使用されます。このオプションが設定されていない場合、close()が呼び出された後、いくつかのクリーンアップ作業が実行され、FINが送信された直後に返されます。 SO_LINGERオプションが設定されていて、待機時間が正の場合、クリーニングする前にしばらく待機します。
例として、close()アクティブシャットダウンを取り上げます。 FINパケットが送信された後、FIN_WAIT_1状態になります。クローズする遅延がない場合(つまり、SO_LINGERオプションを設定する場合)、tcp_send_fin()の呼び出しの直後にsock_orphan()が呼び出され、FINを送信してsock構造をプロセスコンテキストから分離します。分離後、ユーザー層プロセスはソケットの読み取りおよび書き込みイベントを受信しなくなり、ソケット送信バッファー内のデータがピアによって受信されたかどうかも認識しなくなります。 SO_LINGERオプションが設定されていて、待機時間が0より大きい場合、ソケットの状態がFIN_WAIT_1からFIN_WAIT_2状態に移行するのを待機します。送信されたFINパケットが確認された後、ソケットがFIN_WAIT_2状態になり、FINパケットが送信バッファーの最後のバイトであることはわかっているため、FINパケットの確認は、送信バッファー内のデータがすべて受信されたことを示します。 。もちろん、SO_LINGERオプションで設定された時間より長く待機しても、FIN確認を受け取っていない場合は、通常のクリーンアップ作業を続行し、Linuxではエラーは返されません。この観点から、SO_LINGERオプションの役割は、送信バッファー内のデータが送信されるのを待つことですが、送信バッファー内のデータがピア(ピアダウンまたはピアダウン)によって受信される必要があるという保証はありません。回線の問題)、しばらく待つと言っているだけです。時間はこのプロセスを完了させます。待機期間中にデータを含むパケットを受信すると、RSTパケットがピアに送信され、受信チャネルが閉じられたためにソケットがリセットされます。
このオプションを使用して接続の終了を遅らせる場合は、次の2つの点に注意してください。

  1. プロセスは、状態がFIN_WAIT_1、CLOSING、LAST_ACKでなくなるまで(つまり、FINへのACKパケットを受信するまで)スリープするか、タイムアウトを待ちます。
  2. データを含むパケットを受信した場合でも、待機プロセス中にRSTパケットを送信します。
  3. より多くの追加リソースを消費する

TCPプロトコルは、汎用のトランスポート層プロトコルです。上位層固有のサービスは気にしません。接続を遅らせたい場合は、独自のビジネスとシナリオを組み合わせて管理するのが最善です。このオプションに依存しないでください。 Nginxの遅延シャットダウンはそれ自体で管理され、SO_LINGERオプションを直接使用するよりも快適であり、プロセスのブロックを引き起こしません。エラーメッセージを送信した後、ngxinはしばらく待機し、ユーザーにすべてのデータを送信させます。待機時間を超えると、接続は直接閉じられます。 lingering_closeを使用すると、nginxはクライアントの互換性を維持し、クライアントがリセットされるのを防ぐことができます。
SO_LINGERのもう1つの役割は、TIME_WAITソケットの数を減らすことです。 SO_LINGERオプションを設定するときは、待機時間を0に指定します。このとき、アクティブクローズが呼び出されても、接続を終了するためのFINは送信されません。代わりに、接続は直接CLOSE状態に設定され、ソケット内の送信バッファーと受信バッファーがクリアされます。ピアはRSTパケットを送信します。