4件のコメント

フロントエンド/バックエンドシステムでTCPポートが涸渇する問題への対処方法

先日実際にお客さんのところで「TCPポートが涸渇する」という問題が起きたのでそのことについて書いてみようと思います。

実際のシステムはMicrosoft Dynamics CRMだったのですが、これは通常のフロントエンド/バックエンドシステムであればどのシステムでも起こりうる問題です。

フロントエンド/バックエンドシステム

「フロントエンド」、「バックエンド」という言葉が耳慣れない方もいると思うので簡単に説明しておきます。「フロントエンド」というのは実際にクライアントからの接続を受け、結果を返す役割のサーバーを指します。基本的にクライアントから見えるのはこのサーバーだけです。1台だけでは性能的にさばききれない、1台だけでは単一障害点になってしまう、というような理由から複数台配置されることが多いです。性能が足りなくなってきたらフロントエンドのサーバーの台数を単純に足してスケールアウトさせることができるというのもメリットです。

「バックエンド」というのはフロントエンドサーバーからデータの要求を受けつけ、それを返すサーバーです。フロントエンドは複数台で構成されることが多いのですが、その1台1台に実際にクライアントに応答を返すためのデータを全て保持していては、コストもかかりますし、それらをどのように更新、同期させるのかなど、色々と難しい問題が出てきてしまいます。そこで、データ自体は「バックエンド」のサーバーに持たせておき、必要なものをつど「バックエンド」から取得して、クライアントに応答する、ということにします。「バックエンド」にはデータベースサーバーが配置されることがほとんどです。また、「バックエンド」のサーバー自体も冗長化されることが多いですが、データベースサーバーを複数同時に稼動させるとデータの同期が難しいため、実際に稼動しているのは1台だけのActive-Passive構成を取る事が多いです。

image

フロントエンド/バックエンド構成の場合には、上記の図のようにTCP/IPのコネクションが張られます。フロントエンドの上の矢印はクライアントからの接続を意味しています。フロントエンドが複数台ある場合には、複数台に接続が分散されるように別途構成する必要があります。

Windows系のシステムでは

  • フロントエンドサーバーではIISが稼動
  • クライアントからのHTTPの要求を受け付ける
  • バックエンドで稼動しているMS SQLサーバーから必要なデータを取得
  • 結果のHTMLページを生成
  • クライアントに返す

・・・というような処理が行われているのが一般的です。この際、フロントエンドの冗長化および負荷分散にはWindows標準のNLB(ネットワーク負荷分散)が使われ、バックエンドのMS SQLの冗長化には、Microsoft Cluster Service(フェールオーバークラスタ)が使われることが多いです。

何がおきていたのか

今回のトラブルは、フロントエンドサーバーにアクセスすると、特定のページでエラーが表示されてしまう、というトラブルでした。色々と可能性が考えられますが、結局はフロントエンドサーバーとバックエンドサーバー間のTCPコネクションに問題が発生していました。フロントエンドとバックエンド間では、SQLサーバーからのデータを取得するために、多数のコネクションが発生しています。そして今回のケースではフロントエンド側に大量にTIME_WAITのセッションが残ってしまっていて、それが原因でTCPのポートが涸渇し、バックエンドからデータを取得できない状態になってしまっていました。

TIME_WAITというのはTCPの状態を表すものです。通信の始まりから終わりまでどのようにTCPの状態が遷移するのか、ということはRFC793で定義されていて、その中のひとつです。以下の@ITの記事がこのあたりについてわかりやすく書いてあります。

今回は、「フロントエンド側に大量のTIME_WAIT」「バックエンド側には特におかしな点は無い」ということでした。これはつまりフロントエンド側がアクティブクローズを行っているわけです。ですが、その量が半端な数ではありませんでした。netstat -anで確認したところ、負荷が対してかかっていない状況でも100コネクション程度はTIME_WAITが確認でき、負荷が高い時間帯では数千コネクション程度確認されました。

TCPのコネクションはいくつまで使えるのか?

数千オーダーになってくると、そもそもきちんと動くのか?と心配になるかもしれませんが、実際に今回のシステムではこのTCPのポートが涸渇してしまい、正常に接続できない状態になってしまいました。そもそもTCPのポート番号(=コネクション)はいくつまで使えるのでしょうか?

規定の状態では、Windows XPとWindows 2003では一時的なポートの範囲は1024~5000です。つまり4024個を同時に使ってしまうとそれ以上接続にいけなくなってしまいます。Windows VistaとWindows2008では49152~65535と大幅に数が増えました。

対処方法

このようにTCPのポート番号が涸渇してしまうようなケースにはどうやって対処すればいいのでしょうか?大きく3つの方法があります。

1.アプリケーションでネットワークの扱いを変更する

これが本来はいちばんいい対応方法です。TCPのコネクションを張るだけもパケットが3回も飛び交って時間がかかる(3ウェイハンドシェイク)わけですから、そんなに大量にコネクションを張らなくてはいけないくらい頻繁にデータを要求するなら、少数のTCPコネクションを張ったままにして、それをつど再利用すればいいわけです。これならポート涸渇の問題も発生しませんし、パフォーマンスすらよくなるでしょう。

ただし、もちろんこれは自分が作成しているアプリケーションならまだしも、製品であってはなかなか手がでる話ではありません。一応メーカーに文句はいいつつも、別の方法で問題を回避するより仕方が無いでしょう。

2. 一時的なポートの数を増やす

一時的なポートの数を増やすことでも対応できます。以下のレジストリの値を変更し、5000~65534までのポート番号までを使用できるようにできます。

  • HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters
    • MaxUserPort(DWORD)
    • 5000~65534

3.タイムアウトの時間を短くする

規定の状態ではTIME_WAITの状態で4分待ちます。さすがに4分というのは長すぎる気もしますので、これを短くすることで対応することもできます。

  • HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters
    • TcpTimedWaitDelay(DWORD)
    • 30~240

Windows VistaやWindows Server 2008ではTCPの一時的なポートの数は大幅に増えているのですから、ポートの数を増やしてしまうのがいいかもしれません。ですが、一応念のために書いておくと、やはりポート番号を管理するためにもOSのカーネルが仕事をしなければいけないわけですから、最悪の場合OSが不安定になったりする危険性があります。・・・とはいえ、ほとんどの環境で問題になることは無いと思いますけれども。

今回のポイント

今回のポイントは以下のあたりだと思います。

  • フロントエンド、バックエンドのシステムでどのように接続がなされ、どのようにデータが流れているのかの理解
  • TCPのコネクションとポート番号との関係性の理解

この手の問題は、しばらくほおっておくと勝手に問題が解決してしまって「たまにおかしくなる」「とりあえず再起動しておけば直る」というようなあいまいな認識になってしまうことが良くあります。想像力を働かせて、一つ一つ可能性を消していけば原因に到達できるはずですので、がんばっていきましょう。

子供3人。家族優先。都内SIer勤務。Windows系中心のインフラよりの何でも屋。脱原発。 Microsoft MVP for Cloud and Datacenter Management.

4件のコメント

    1. hisaさんコメントありがとうございます。
      システムによってはそういう方法が対処になることもあり得ますね。

      きちんと因果関係など含めて理解していないとJAVAの削除はリスキーだとは思いますが…。

  1. fjtさんコメントありがとうございます!

    ポート枯渇は結構よく遭遇しますよね。私が過去遭遇したものでは他にはADに対する更新、登録系のスクリプトで、処理を行うたびにDCにTCPコネクションを張りまくっていて、処理件数が多くなるとエラーが出てしまう・・・と言うようなことがありました。

    結局ポート枯渇はプログラムの書き方が悪いことが多いので、それに気がつけるかどうかですよね・・・。

    netstatでプロセスIDが出せるのは便利ですよね~。

  2. 自分も半年くらい前にポート枯渇に出くわしたよ

    通信が不安定な時には、
    ・netstat -ano  (-oでPIDを表示)
    ・tasklist
    が打てると切り分けが早くていいね(2003以上で対応)

コメントを残す

メールアドレスが公開されることはありません。

x
11月15日にHuaweiさん、IIJさん、Microsoftさん、JBSでAzure Stackのセミナーを行います。私も登壇させてもらいます。懇親会もあります。 是非ご参加下さい! セミナー申し込みページ:https://www.jbs.co.jp/event/list/2018/1115