まず、設計に関する2つの注意事項:
多くの場合、誰かが新しいIPアドレスを取得するのは非常に簡単です。iPhoneをLTEから3Gに切り替えて元に戻し、DSLモデルのプラグを抜き差しし、新しいオープンプロキシを選択するなどです。したがって、意図的な悪用を防ぐためにこれを期待している場合人々が自分たちがやりすぎていることに気づかないだけでなく、それはあまり役に立ちません。
IPアドレスは、多くの場合、NATによって、または順次に共有されます。1人の人を意味する場合はIPあたり1時間あたり200リクエストが妥当と思われるかもしれませんが、BigCorpの地域オフィスの7500人の従業員全員を意味する場合はどうでしょうか。
とにかく、あなたの解決策はうまくいくでしょう、そしてあなたのトラフィックパターンに応じて、それは合理的かもしれません、しかしいくつかの選択肢があります。
たとえば、すべての接続をチェックする代わりに、共有ブラックリストを保持したい場合があります。接続が確立されたら、そのブラックリストに基づいてすぐに承認または拒否し、「データベースの更新」ジョブを開始します。N秒ごとに1回以上更新するのではなく、更新を統合するためのさらなるトリックを実行できます。もちろん、これは、すべての接続で読み取り可能で、バックグラウンドジョブで書き込み可能な共有データがあることを意味します。つまり、競合状態やデッドロックへの扉、そしてGuidoがGAEに直面することはめったにないことを確認するために懸命に努力したすべての楽しいこと。
dataStoreの代わりにmemcacheを使用できます。ただし、キーを慎重に作り直して、単純なKey-Valueストアに適したものにし、有効期限が必要な処理を実行できるようにする必要があります。たとえば、IPからキーオフされた値に加えて、タイムスタンプや乱数など、接続ごとにキーを設定した値に加えて、他の値を見つけることができるIPからキーオフされた接続リストの値を保持できます。キャッシュからドロップされた値はカウントされなくなり、接続リストの値がドロップされた場合、ユーザーは0まで下がる必要があります。ただし、これにより多くの複雑さが増します。
少数のユーザーがそれぞれ大量のリクエストを行っている場合は、タイマーを使用して、IPごとにデクリメント、リセット、または再カウントすることができます。ただし、1時間あたり数百を超える個別のIPが予想される場合は、これらすべてのタイマーを手動で合体する必要があり、おそらくジョブも合体する必要があります(たとえば、「17:55:39に、この17のIPのリストをデクリメントする」)。 、そしてタイマーはおそらく非常に頻繁に起動するので、おそらくそれだけの価値はありません。
個人的には、最初に最も単純な実装を行い、次にストレステストとパフォーマンステストを行います。それで十分であれば、心配する必要はありません。
And if it's not good enough, I might look into whether I could simplify the design before looking at optimizing the implementation. For example, if it's N connections per IP per calendar-hour, that makes everything a whole lot easier—just store a counter per IP (in dataStore or memcache), and wipe all the counters at every XX:00. Is that acceptable?