
ポートで接続をリッスンするアプリケーションがありますが、更新などのために時々停止します。プログラムが実行中の場合はそのポートの要求がアプリケーションに送信され、実行されていない場合は要求が他のアプリケーション (「一時的に利用できません」というメッセージを返すことができる) に送信されるようシステムを構成する方法が必要です。これを実現する最も簡単な方法は何ですか?
私はターゲットマシンのルートアクセス権を持っていないので、のようなことは避けたいと思っていますiptables
。他の2つのアプリケーションへの接続をルーティングするだけのヘルパーアプリケーションを検討しましたが、もっと簡単な方法があることを願っています。
答え1
あなたの質問は、両方のプログラムが同じマシン上で交互に実行され、同じポートにバインドされることを意味します。これは悪い考えです。TIME_WAIT
これを試すと、(別名 2MSL) 問題に遭遇することになります。この記事問題について説明します。(Windows 中心ですが、説明されている内容のほとんどはどの TCP/IP スタックにも当てはまります。)
BSD ソケット API ではこの保護を無効にする方法が提供されています ( setsockopt(SO_REUSEADDR)
) が、これはそうすることが正当化されるケースの 1 つではありません。
代わりに、高可用性の専門家が行うのと同じ方法で問題を解決します。リバースプロキシ世界と「実際の」バックエンド サーバー間の通信です。
HTTPの世界では、この問題に対する一般的な解決策の1つはnginxバックエンド サーバーがダウンしている間、静的コンテンツをクライアントに提供するように構成できます。プロトコルが HTTP、IMAP、または POP のような場合は、nginx をそのまま使用できます。そうでない場合は、カスタム プロキシ サーバーを構築できます。
これを機能させるには、おそらく 2 つの TCP ポートが必要です。プロキシは、パブリック IP 上の公開ポート番号にバインドします。バックエンド サーバーは、ローカルホスト インターフェイス上のセカンダリ ポートにのみバインドします。したがって、トラフィックは、プロキシを介してのみパブリック ネットワークからバックエンド サーバーに到達できます。
両方のプログラムがそれを許可するように記述されている場合、両方を同じポートにバインドしても問題ありません。たとえば、パブリック IP が で1.2.3.4
、パブリック サービス ポートが の場合、リバース プロキシが IP にのみバインドし、「実際の」サーバーが にのみバインドすると、2345
両方のプログラムがポートにバインドできます。どちらかが(0.0.0.0) にバインドする場合は、異なるポートが必要です。2345
1.2.3.4
127.0.0.1
INADDR_ANY
これにより、クライアントが常に同じプログラム (プロキシ サーバー) と通信するため、2MSL の問題が解決されます。ネットワーク スタックは、2MSL 時間に巻き込まれた迷子のパケットをどう処理するかについて混乱することはありません。
リバースプロキシのバリエーションとしては、ロードバランサー、ここでも機能する可能性があります。ロード バランサは、トラフィックをさまざまなマシンにインテリジェントにルーティングするように設計されています。この種のプロキシは、将来的にアプリを水平方向に拡張する必要がある可能性がある場合に適しています。通常のアプリケーション サーバーがすべてダウンしているときに、特別な「サービス ダウン」ホストにトラフィックを送信する方法を知っているロード バランサを選択します。
ロード バランサ ソリューション バリアントの主な問題は、汎用ロード バランサが、プロキシするすべてのバックエンド サービスが同じポート番号を使用し、IP のみが異なると盲目的に想定する可能性があることです。ただし、より柔軟なロード バランサを入手したり、共有サーバーに複数の IP を取得したりできる可能性があります。