雑多に技術メモと他色々

主に自分用な技術メモが多くなる気がする。他色々が書かれるかどうかは不明。

サーバ間HTTP(S)通信のチューニング基礎の覚え書き

コネクションプールとかTIME_WAITとか…

やりたいこと

  • どこかのサーバから外部サーバへ何度もHTTP通信したい
  • 継続して上記を実施したい
  • 1つ1つの通信は短時間で終わるようにそれなりの性能を確保したい
  • 通信元のサーバはCentOSとする(業務都合)

タイムアウト

サーバ間通信ならタイムアウト値は必ず設定するものと考える。(特にデフォルトで無限待ちになるようなケースだと最悪)

タイムアウトの種類

種類 概要 ざっくり設定時間
コネクションタイムアウト コネクションの確立までにこれ以上かかる場合は打ち切る。 100ミリ秒~数秒程度
リードタイムアウト コネクション確立後、レスポンスを受け取りきるまでにこれ以上かかる場合は打ち切る。 数秒~数時間

コネクションタイムアウトは通信確立までの時間なので、ルーティング~TCP接続確立が長時間化しなければいい。平常時に数秒レベルが必要になるケースは稀だと思ってる。

リードタイムアウトは、通信先の処理に時間がかかる場合や大量のデータを受け取る場合は長時間でないと処理が打ち切られる。ユーザ待ちになるようなオンライン処理なら長くても数秒で済ませたいところか。

タイムアウト設定値の長短

あまりに短いと、少しの処理遅延で正常な通信を打ち切ることになる。
長くしすぎると通信先の遅延や無応答が発生した時に待ち続けるので、通信元の自サーバが受ける影響が大きくなる。
結局は長すぎても短すぎてもだめなのでいい感じにチューニングしろってことになる。

コネクションプール

接続済のコネクションをプールして使い回す。
使い回せば通信確立までのコストをスキップできるので、1通信の時間が短くなる。
また、短時間で本当に何度も通信が行われるケースでコネクションオープン->クローズを繰り返すとTIME_WAITでポートが食いつぶされてしまう場合もあり、その回避手段としての価値も高い。

通信先に対して自サーバが複数のソケットを専有し続けるので、通信先が利用を許容している範囲で使うことが望ましい。
また、同一の通信先に何度も通信する場合の解決策であり、通信先自体が大量に存在するケースでは利用する意味が薄い。
1サーバに100万回通信なら利用するべきだが、100万サーバに1回ずつ通信するならプールを利用する意味は無いってこと。

TIME_WAIT

ぜんぶTIME_WAITのせいだとおっしゃる方がいるくらい問題を引くことも多い。
qiita.com
通信成功してコネクションクローズした後、利用したポートは一定時間TIME_WAIT状態で利用不可となる(業務で使った環境は確か60秒)。前述の大量通信が行われるような場合、netstatやらssやらで見るとTIME_WAITでポートが埋め尽くされてしまうこともある。
コネクションプールは解決のためのひとつのアプローチだが、他の策もあり。

カーネルパラメータでTIME_WAIT関連の値をチューニング

種類 概要 デフォルト値 チューニング値
net.ipv4.tcp_tw_recycle ググるとまだ出てくることも多いが廃止済みなので使わないこと。 - -
net.ipv4.tcp_tw_reuse TIME_WAIT状態のポートを開放前に再利用できるようにする。 0(無効) 1(有効)
net.ipv4.tcp_fin_timeout FIN-WAIT2からTIME_WAITへの遷移を待機する時間 60(秒) 30(秒) ※ 場合によりけりだが何も考えないならこんな感じか

実業務でチューニングした時に効果があったのはnet.ipv4.tcp_tw_reuseだった。
net.ipv4.tcp_fin_timeoutはFIN-WAIT2からTIME_WAITへの遷移時間は調整できるが、TIME_WAITから開放までの60秒は調整できない。(最初ここで勘違いした)
FIN-WAIT2 -> TIME_WAIT が滞るようなケースならnet.ipv4.tcp_fin_timeoutも効果的なのかもしれない。

とりあえずnet.ipv4.tcp_tw_reuseをコマンドで設定、確認する場合はこう。

# 設定なら
$ sysctl -w net.ipv4.tcp_tw_reuse=1

# 値確認なら
$ sysctl -n net.ipv4.tcp_tw_reuse
1

※ 有効にしても効かないケースがあったり、再利用が正常にハンドリングできずに不正な通信になったりということはあり得るはずなので、利用しても大丈夫かどうかは検証してください。

TIME_WAITの待機時間を減らす

TIME_WAIT状態で利用不可から開放されるまでの時間はカーネルパラメータでチューニングできない。
どうしても変更したい場合はカーネルを自分でいじってリビルドってことになるようだ。さすがにめんどい。
qiita.com

まとめ

いろいろいじって快適な大量通信ライフを。