LoginSignup
2
0

More than 5 years have passed since last update.

Solaris11にバージョンアップ後、TCP接続が失敗するようになった

Posted at

Solaris11.3にバージョンアップ後、ネットワーク接続数が多くなると、ソケット接続が失敗する現象が稀に発生し、処理をやり直すことになりました。原因は、TIME_WAITとエフェメラルポートのポート番号の設定方式に起因するとわかたっため、備忘録として記載しました。

事象

Solaris10からSolaris11.3へバージョンアップ後、サーバ間(サーバA⇒サーバB)のコネクション接続でconnect()から
ECONREFUSED が復帰し、接続不可となる事象が発生しました。
接続数が多い時に発生しましたが、Solaris10の時と、接続数、通信量は変わっていませんでした。
なお、接続ポートにはエフェメラルポートを使用していました。

原因 

 ネットワークトレースを取るなどして再現調査を行った結果、以下が判りました。

  • コネクションをクローズ後、一定時間(デフォルトは60秒)、そのコネクションをTIME-WAIT状態で保持します。
    これはTCPの仕様です。その際、使用していたポート番号もOSで保持しています。
  • 次の接続で、ポート番号に直前にクローズされたコネクションで使用していたポート番号(エフェメラルポート)が割り振られました。
    そのため、TIME-WAIT状態とみなされ、connectでRSTが復帰されました。
    これは、Solaris11からエフェメラルポートがランダムに選択されるように動作が変わったため、まれに直前で使用していたポート番号と同じ番号が割り振られたためでした。
    (Solaris10以前は+1カウント方式なので同じポート番号が割り振られる可能性は極めて低いものでした)

SolarisではTIME-WAIT状態の保持期間中に同じクライアントのIPアドレス・ポート番号から  
接続要求があった場合はRFC793の規約に準じてRSTを返す実装になっています。
RFC793より新しいRFC1122ではTIME-WAITでも新しい接続要求を受け付けてよいとされており、
WindowsやLinuxはこれに準じているようで、RSTは発生しませんでした。

プレゼンテーション1.png

対処・教訓

TIME-WAIT時間の変更など考えましたが、他に与える影響を考慮し、
最終的には、RSTが返る場合に備えて、リトライを組み込むようにしました。
実際に3回リトライとし、その後問題は発生していません。

Windows、Linuxでは、この問題は発生しませんが、Solaris転用を考慮する必要がある場合、
connectでRSTが復帰した場合、リトライ処理は組み込んでおくべきかと思います。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0