web-dev-qa-db-ja.com

複数のしきい値を使用してHAProxyとの接続をレート制限する方法はありますか

私は、HaProxyを使用してStackExchange それを行う と同様の方法でHaProxyを使用して単純なレート制限を実装しました。レート制限の複数のしきい値が存在するように、それをもう少し高度にしようとしています。

たとえば、要求するクライアントを制限します。

  • 15 /分

  • 60 /時間

  • 360 /日

同じデータを異なるサンプルレートで保存するには、複数のスティックテーブルが必要なようです。ドキュメントは述べています:

プロキシごとに1つのスティックテーブルのみがあります。このドキュメントを書いている現時点では、プロキシごとに複数のテーブルを用意することは役に立たないようです。これが必要な場合は、スティックテーブルを含むダミーバックエンドを作成して参照します。

残念ながら、ダミーのバックエンドテーブルにデータを格納する方法を理解しようとするときの悪魔がいます。

私は他の方法にも心を開いています。HaProxyは単に有望な道のように思えました。環境にはすでにそれがあるので、それは理にかなっています。任意の提案をいただければ幸いです。

4
palehorse

私はこれを自分でやろうとしていて、運が悪く、google-fuに頼ることにしました。複数のレベルのレート制限を探しているときの一番の結果はこれで、本当に興奮しました。それから私はそれが答えがないのを見て、そして絶望の実存の落とし穴に落ちました。自分を掘り下げた後、ハッキングを続けましたが、運がよかったので、少なくとも自分が必要としていることを行う方法を見つけ出したようです。多分それもあなたのために働くでしょう。

Haproxyは本当にとてもクールです。現在の負荷分散ソリューションの代わりにHaproxyを使い始めることにワクワクしますが、スティックテーブルは頭を包む怪物のようです。その前に、私を助けているように見える1つの一般的な原則を見つけました、そしてそれはあなたが明示的に複数のスティックテーブルでセットアップを行おうとしているとき、名前によってeveryスティックテーブルを参照することです。名前が暗黙的である(あなたがいるバックエンドであると想定される)デフォルトの振る舞いは素晴らしいです...複数のスティックテーブルを使いこなそうとしている場合を除きます。だから、以下の私の設定では、その一部が必要以上に冗長になっています。そうすれば、ロジックを理解するのが簡単になります。とにかく、ここに行きます(これはIPではなくMoodleアプリケーションのCookieに基づいてカウントされ、v1.5.11のhaproxyを使用していることに注意してください):

backend dynamic_60
  stick-table type string len 36 size 1m store gpc0_rate(60s)

backend dynamic
  stick-table type string len 36 size 1m store gpc0_rate(10s)
  stick on cookie(MoodleSession) table dynamic
  stick on cookie(MoodleSession) table dynamic_60
  tcp-request content track-sc0 cookie(MoodleSession) table dynamic
  tcp-request content track-sc1 cookie(MoodleSession) table dynamic_60

  acl rate_10s sc0_inc_gpc0(dynamic) gt 0
  acl rate_60s sc1_inc_gpc0(dynamic_60) gt 0
  tcp-request content reject if rate_10s rate_60s FALSE

つまり、これは、1つのカウンターを10秒あたりのレートを記録するように設定し、別のカウンターを60秒あたりのレートを記録するように設定することです。実際にはこれらのカウンターを使用してまだレート制限を行っていないことに注意してください。ただし、次の方法で確認できます。

echo "show table dynamic" | socat /var/run/haproxy/admin.sock stdio
echo "show table dynamic_60" | socat /var/run/haproxy/admin.sock stdio

レートカウンターが個別に維持されていること。

これらのカウンターを実際にインクリメントするために必要な最小限の構成を見つけたかったので、「tcp-request content reject」ステートメントの最後に「FALSE」と表示されます。カウンターでACLを定義するだけでは、インクリメントされません。実際にはACLを使用する必要があります。最後に「FALSE」を指定すると、条件を満たさなくてもACLを使用して、実際にリクエストを拒否できます。これらのACLの実際の数値を決定したら、おそらく「FALSE」を削除します。

複数のスティックテーブルを機能させるための本当の鍵は、「スティックオン」、「track-sc {0 | 1 | 2}」、および「sc {0,1,2} _inc_gpc0実際にリクエストを処理しているバックエンド。それらのいずれかをdynamic_60バックエンドに移動すると、そのカウントが機能しなくなりました。理由は、実際にはリクエストを通過して情報をプルしていないため、リクエストを処理していないバックエンドにACLを追跡または適用しても意味がないためだと思います。そうは言っても、他の人がもっと良い説明をするだろうと確信しています。私はhaproxyにかなり新しいです。

私が尋ねた次の質問は次のとおりでした:(「track-sc」の構成設定は0から2までしか行かないため)3つの項目の追跡のみに制限されていますか?はい、追跡できるのは3つだけだと思います。しかし重要なことに、実際にリクエストを処理するのは3つのことperバックエンドです。したがって、たとえば、私のように静的コンテンツに対して動的コンテンツとは異なるレート制限を行う場合は、フロントエンドの「静的」または「動的」バックエンドのどちらに移動するかを、リクエスト。次に、「静的」バックエンドで、「静的」および「静的_60」バックエンドでtrack-sc0とtrack-sc1を定義します(たまたま、上記の構成と同様の命名規則に従っている場合)。次に、レート制限の決定に使用する4つのスティックテーブルがあります。動的コンテンツと静的コンテンツの両方で10秒と60秒のレート。 3番目のカウンターを使用すると、3つのレベルを取得できると思いますが、それが限界だと思います。

11
David Ackerman