サーバーとして機能し、潜在的に数千のデバイスを管理するアプリケーションをx86_64 CentOS7で作成しています。私のアプリケーションは、接続プロセス(さまざまなアプリケーション層のハンドシェイク、DB操作など)を実行するとうまく機能せず、何千ものデバイスがオンラインになる可能性があるためです同時に、レート制限接続の受け入れを試したい(スケール問題への可能な「ソースでの硬化」アプローチとして)。
簡単に言うと、nデバイスのアプリケーションハンドシェイクプロセスがすでに実行されている間、着信接続は何らかの方法で「拒否」されます(これはn[〜#〜] t [〜#〜]制限時間、またはn同時ハンドシェイク制限) 。
悲しいことに:
accept()
で接続をドロップするだけでは、デバイスの再接続バックオフメカニズムは呼び出されないため、再試行は騒々しいでしょうlisten
バックログサイズを変更することもできませんaccept()
が人為的に遅延するまで、着信接続をバックログに残したくありません。これは、epollがレベルトリガーされ、結果として生じる「タイトな」を回避するためのアーキテクチャ上の悪夢が少し発生するためです。ループ"connect()
/accept()
のオーバーヘッドは高くない (特に実際のI/Oと比較した場合)と聞いたので、単にシャットダウンする傾向がありますすでに100回の再接続を処理しているときにリッスンソケットをダウンし、海岸が晴れたら再オープン/再listen()
します。
しかし、これはどういうわけか問題を解決するための間違った方法のように感じます。
上記の制約がある場合、この問題にどのように取り組みますか?
人為的に遅延したaccept()を保留して、着信接続をバックログに残します
Epollのセットから記述子を一時的に削除することにより、実際の検出を人為的に遅らせる方が理にかなっています。
andy mangoコメントでこれを示唆 、そしてそれは私が最終的にやったことです(これは予想よりも構造的に単純でした)。
それは、ソケットを連続して閉じて再度開くことが「恐ろしいアイデア」であるかどうかという質問には実際には答えませんが、私はもはや疑問に思う必要がないことを意味します。