web-dev-qa-db-ja.com

TCP接続を維持して、どのクライアントがオンラインであるかを追跡する

サーバーが単純なIoTデバイスのlotsと連絡を取り合う必要があるアプリケーションを開発しています。サーバーと各デバイス間で情報を交換する必要はほとんどありませんが、デバイスはオンラインのままで、サーバーから24時間アクセス可能である必要があります。ある時点で(非常にまれにしか発生しません)、サーバーはデバイスの1つと連絡を取り、いくつかのメッセージを交換できる必要があります。ただし、これらのデバイスに非常に短い時間で到達できることが重要です。

これは、これらのクライアントデバイスを何らかの方法で継続的に接続する必要があることを意味します。さて、私は疑問に思います:TCPを介してそれらのデバイスを接続し、メッセージを交換する準備ができているようにそれらの接続を維持することは可能ですか?

私は周りを読み込もうとしましたが、常に同じ答えを読みました:メッセージの交換と処理がそれらを維持するのではなくボトルネックになる可能性が非常に高いため、実装によって異なりますTCP接続は生きています。これは実際には私の場合ではありません。非常に限られた量の情報を毎回たくさん交換する必要があるからです。

では、これらのクライアントを接続したままにしておくのは合理的ですか?それとも、もっと効率的な方法を考案する必要がありますか?たとえば、データ交換なしでTCP接続を維持するために必要な帯域幅はどれくらいですか?これには大量のメモリまたはCPUが必要ですか?

数秒ごとにUDPキープアライブをサーバーに送信する単純なC++プログラムを実装しました。ベンチマークによると、これは、適度に制限されたサーバーでも、問題なく数百万のオンラインデバイスにスケールアップできます。 TCPはそれよりもパフォーマンスが悪いですか?

1
Matteo Monti

私のTCPの理解に関しては、「Keeping TCP connections alive」と主張することは、があるので、誤解を招く恐れがあります。 no参照されたときにタイムアウトを処理するTCPプロトコル固有のメカニズム[〜#〜]確立された[〜#〜]接続。つまり、一度確立されると、RESET、FIN、またはACKの受信のタイムアウト(...この最後の場合は、いくつかの送信に続いてACKnowledged)が発生するまで、それらは永久に続く可能性があります。

私の経験では、「アイドルタイムアウト」のような問題の100%は、2つの通信ホスト間のルーティングパスに沿った中間ルーター/ファイアウォールに依存しています。つまり、ファイアウォールは通常「ステートフル」ファイアウォールであるため、ファイアウォール/管理している接続を追跡します。そのため、追跡する必要のあるすべての接続は、(ファイアウォールの)ある程度のシステムリソースが消費されることを意味します。また、ファイアウォール自体の性質上、ファイアウォールは、管理対象接続のどれが「機能」していて、どの接続が「アイドル」であるかを完全に認識しています(ステートフル )ファイアウォール!)。そのため、多くの(すべて?)ファイアウォール実装にはタイムアウトが定義されており、マネージド接続がそのようなタイムアウト値に対してアイドル状態の場合、ファイアウォールは両端にリセットを送信します(... of TCP接続)、独自のリソースを解放します。

あなたの質問に基づいて、私はTCP接続があなたのIoTデバイス(クライアントとして機能する)対あなたの制御サーバー(TCPしたがって...[〜#〜] lots [〜#〜]、そうでない場合[〜#〜] all [〜#〜 ]、NAT IoTデバイストラフィック)になるADSLホームルーターの、確実に説明されているように動作します。

これは、少なくとも、私自身の経験に基づいています。

しかし、私はそうではないので Jon Postel 、私が間違っていても私を責めないでください:-)

補足として:あなたは「...たくさんの単純なIoTデバイス...」と書いています。単一の大きなサーバーで処理できる同時TCP接続の数には、非常に厳しい制限があることに注意してください。..TCP "port"は16ビット値です。したがって、各IPアドレスについて、(TCP組み込み設計による)64K接続を超えることはできません。この問題をどのように解決できるかはわかりません。この質問の文脈でのスコープ。

最後に、IoTデバイスと管理サーバー/アプリケーションの間に一種のハートビートプロトコルを実装する際にnoの問題が実際に発生することを付け加えておきます。帯域幅の点で影響がなく、管理性/制御の点で多くの利点がある、非常に「ネットワークフレンドリー」になるように実装できます。

3

あなたの考えは大丈夫です。実際、最新のモバイルデバイスは通知にまったく同じアプローチを使用し、OS開発者のサーバーへの永続的な接続を維持し、そのサーバーは通知をその接続にプッシュします(サードパーティのアプリ開発者はOSの開発者に通知を送信し、OSの開発者はそれらを中継します適切なモバイルデバイスに)。

デバイスがパブリックにルーティング可能なIPを持ち、ソケットでリッスンできることが保証されている場合は、別の方法を使用できます。その場合、デバイスはIPが変更されるたびにサーバーに通知しますが、サーバーがデバイスにデータを配信する必要があるときはいつでも、サーバーはデバイスのソケットに接続してデータを送信します。そうすれば、サーバーは、データベース内のすべてのデバイスのIPアドレスを更新し、場合によってはデバイスに接続してデータを送信する以外に、負荷を処理する必要がありません。

TCP vs UDPについては、TCPは、デバイスの到達可能性を保証するのに適していると思います-TCP接続が開いていると、デバイスがまだそこにあることが保証されます(そうでない場合、接続がタイムアウトします)。UDPを使用すると、宛先に到達したかどうかさえ知らずに、パケットを空中に投げるだけです(実装しない限り)独自のキープアライブ、接続管理、および再送信システムですが、TCPと呼ばれるすでに堅実で人気のある実装があるのに、なぜ車輪を再発明するのですか?)また、TCP接続が確立されると、送信したものがすべて宛先に到達することを確信できますが、UDPを使用すると、確信が持てず、さまざまな成功の度合いで穴を開ける必要があります。

2
André Borie