ひよっこ。

I want to…

エフェメラルポートのバッティング

Posted by hikaruworld : 2008 11月 13

RHEL4上で起動しているTomcatをデフォルトの8080ポートで起動しようとしたら、唐突に以下のエラーで落ちた。

致命的: エンドポイントを初期化中のエラーです
java.net.BindException: Address already in use: JVM_Bind:8080

エラー自体は別段珍しいものではない。Tomcatのプロセスがつかみっぱなしになっているんだろう。
ただ昨日まで起動していたものが、突然起動しなくなるとはどういうことだと思いつつ、
とりあえずnetstatしてみる。

netstat -n –tcp | grep IPアドレス

必要な箇所だけ抜粋。
確かに使っているようだ。でも5432というと。。。

tcp 0 0 10.131.229.25:5432 10.131.229.25:8080 ESTABLISHED

続いて、lsof

lsof -i:8080

またまた、該当箇所のみ

COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
java 19463 root 18u IPv6 3159971 TCP hostname:8080->hostname:postgres (ESTABLISHED)

…変なものが見える。
PostgreSQLとのコネクションを張るのに8080を使っているようだ。

Tomcat上のアプリとDB間はパフォーマンスを考慮して、コネクションプーリングを持ちいているので、
Tomcat起動時にアプリ⇔DB間で、複数コネクションを複数のTCP接続で確立させ、
その際にコネクション分のポートがPostgreSQLによって確保されるわけだ。
おそらくこの際のポートの確保は、OSで設定されているエフェメラルポートから適当に割り振られるようだ。

PostgreSQLのエフェメラルポートの割り当てがどのように行われるかわからないが(挙動的にインクリメントっぽい)、
このコネクション確立時のポート確保とアプリケーションの起動ポートがバッティングする可能性があるようだ。

# この理解であっているのかな?あとで図でも書いてみるか。。

色々検索してみたが、サーバ構築時にエフェメラルポートの設定を考慮する必要があるのは周知の事実らしい。
すみません、存在すら全く知りませんでした。

RHEL4の場合は、以下のように設定すれば任意にエフェメラルポートを設定可能なようなので、
/etc/sysctl.confnet.ipv4.ip_local_port_rangeを以下のように追記した(要再起動)。

net.ipv4.ip_local_port_range = 20000 61000

上限値はメモリに依存するらしい。
なお、RHEL4のデフォルト設定は1024-65000(最大値は忘れた、確かこのあたりだった気がする)らしいが
この件に関するRHELのドキュメントが見つけられなかった。

探し方が悪い???
とりあえず検証してみて期待通りの動作をしているところまでは確認したが、気になるところである。

P.S
次のエントリーで書くが、このバグはコネクションプーリングのdestory漏れという、
あほなミスと重複して発生頻度が上がっていたようだ。(汗

参考リンク:

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

 
%d人のブロガーが「いいね」をつけました。