最近、数人のネチズンからインタビューのフィードバックを受け取りましたが、インタビュー中に全員が 現在の制限 関連の質問をされました。今日は、私たちのプロジェクトにおけるさまざまな電流制限ソリューションについて話しましょう。
一般的な電流制限シナリオの場合、 2 つの次元 情報:
上 2 つの側面を組み合わせると、電流制限とは、1 秒あたり最大 100 アクセス リクエストを設定するなど、特定の時間枠内のリソース アクセスを制限することを意味します。しかし、実際のシナリオでは、1 つの電流制限ルールを設定するだけでなく、複数の電流制限ルールを設定して連携して動作させることもできます。主な電流制限ルールは次のとおりです:
(接続数およびQPS)の電流制限については、IPディメンションで電流制限を設定することも、単一サーバーに基づいて電流制限を設定することもできます。
実際の環境では、通常、同じ IP のアクセス頻度を 10 未満に設定するなど、複数の次元での電流制限ルールが設定されます。接続数が 5 未満の場合は、各マシンの QPS を最大 1000 に設定し、接続数を最大 200 に保ちます。さらに、サーバグループや計算機室全体のサーバをまとめて、より上位の電流制限ルールを設定することもでき、これらの電流制限ルールが連携してトラフィック制御を行います。
リソースのダウンロード速度など、「通信速度」については誰もがよく知っています。一部の Web サイトでは、この領域でより詳細な電流制限ロジックが用意されています。たとえば、一般の登録ユーザーのダウンロード速度は 100k/s、メンバーシップ購入後は 10M/s になります。この背後には、ユーザー グループに基づいた電流制限ロジックがあります。またはユーザータグ。
ブラック リストとホワイト リストは、大規模なエンタープライズ アプリケーションでデータを制限および解放する非常に一般的な手段であり、多くの場合、ブラック リストとホワイト リストは動的に変更されます。たとえば、ある IP が一定期間にあまりにも頻繁にアクセスされ、ロボット ユーザーまたはトラフィック攻撃としてシステムによって識別された場合、その IP はブラックリストに追加され、それによってシステム リソースへのアクセスが制限されます。一般に「IP ブロッキング」として知られているもの。
私たちがよく目にするクローラー プログラム、たとえば、Zhihu で美しい女性の写真をクロールしたり、証券システムの株式のタイムシェアリング情報をクロールしたりする場合、これらのクローラー プログラムは、追加されないように IP を変更する機能を実装する必要があります。 。
会社のネットワークが 12306 などの大規模な公開 Web サイトにアクセスできない場合もあります。これは、一部の会社の送信 IP アドレスが同じアドレスであるためでもあります。そのため、アクセス数が多すぎると、この IP アドレスは相手のシステムによって認識され、ブラックリストに追加されます。家庭用ブロードバンドを使用する学生は、ほとんどのネットワーク オペレータがユーザーを異なる送信 IP セグメントに割り当てたり、ユーザーの IP アドレスを随時動的に変更したりしていることを知っておく必要があります。
ホワイトリストの方が分かりやすく、王室から授与される金メダルに相当し、様々な電流制限ルールを何の障害もなく自由に行き来することができます。たとえば、一部の電子商取引企業は、非常に大規模な販売者のアカウントをホワイトリストに追加します。そのような販売者は独自の運用および保守システムを持っていることが多く、大量の製品のリリースや補充を行うために企業の IT システムと接続する必要があるためです。 、など。さらに、パブリック アカウントのバックエンド Programming Technology Circle を検索し、「Java」と返信すると、サプライズ ギフト パッケージがプレゼントされます。
分散は、単一マシンの電流制限シナリオとは異なり、分散環境全体のすべてのサーバーを全体として考慮します。たとえば、IP 電流制限の場合、1 つの IP を 1 秒あたり最大 10 アクセスに制限します。この IP からのリクエストがどのマシンに送信されるかに関係なく、クラスタ内のサービス ノードにアクセスする限り、この制限の対象となります。電流制限 ルールによる制約。
クラスター内のすべてのマシンのアクセス ステータスを取得できるように、電流制限情報を「集中型」コンポーネントに保存することをお勧めします。現在、主流の電流制限ソリューションは 2 つあります。
トークン バケット トークン バケット アルゴリズムは、現在最も広く使用されている電流制限アルゴリズムです。名前が示すように、次の 2 つの重要な役割があります。
このプロセスには、トークン ジェネレーターとトークン バケットが含まれます。トークン バケットはトークンの場所であると前述しました。バケットであるため、容量が必要です。つまり、トークン バケットが多数のトークンを保持できることを意味します. カードの枚数は固定値です。
トークン ジェネレーターの場合、所定のレートに従ってバケットにトークンを追加します。たとえば、1 秒あたり 100 リクエスト、または 1 分あたり 50 リクエストのレートでトークンを発行するように構成できます。 。ここでの発行速度は均一であることに注意してください。これは、これらの 50 個のトークンが各時間ウィンドウの開始時に一度に発行されるのではなく、この時間ウィンドウ内で均一の速度で発行されることを意味します。
トークンディスペンサーは蛇口になっており、下の水を入れたバケツが満水になると自然に水(トークン)が外に流れ出ます。トークン発行時も同様で、トークンバケットの容量には限りがあり、定格容量のトークンがいっぱいになった場合、新しいトークンは破棄されます。
両方のアルゴリズムが持つそれぞれの特性に基づいて理解するのは難しくありません。 「一定」レートと「不定」レート。トークンバケットは一定のレートでトークンを生成しますが、アクセスリクエストがトークンを取得するレートは「不定」で、とにかくトークンがあればあるだけ発行され、トークンがなくなったらただ待つだけです。リーキー バケットはリクエストを「一定」のレートで処理しますが、これらのリクエストがバケットに流入するレートは「可変」です。
これら 2 つの特性から、リーキー バケットの自然な特性により、バースト トラフィックが発生しないことがわかります。たとえ 1 秒あたり 1,000 リクエストが到着したとしても、バックグラウンド サービス出力へのアクセス レートは常に一定です。トークンバケットは異なります。一定量のトークンを「事前に保存」できる機能があるため、突発的なトラフィックに対処する際に、短時間ですべてのトークンを消費できます。バーストトラフィックの処理効率はリーキーよりも高くなります。バックエンド システムへの負荷もそれに応じて増加します。
たとえば、1 秒ごとに 5 人のユーザーがアクセスし、5 秒以内に 10 人のユーザーがアクセスする場合、0 ~ 5 秒の時間ウィンドウ内にアクセスすることになります。金額は15です。インターフェイスが時間ウィンドウ内のアクセスの上限を 20 に設定すると、時間が 6 秒目に達すると、1 秒のグリッドが時間ウィンドウから出たため、この時間ウィンドウ内の合計カウントは 10 になります。 6 秒以内に受信できる訪問数は 20-10=10 です。
スライディング ウィンドウは実際には計算アルゴリズムであり、時間ウィンドウのスパンが長いほど電流制限効果がより滑らかになるという特徴があります。たとえば、現在のタイム ウィンドウが 2 秒しかなく、すべてのアクセス要求が最初の 1 秒に集中している場合、時間が 1 秒戻ると、現在のウィンドウのカウントが大幅に変化します。この出来事の状況
検証コード、IP ブラックリスト、など、これらの手段は悪意のある攻撃やクローラーの収集を効果的に防ぐことができます;
電流制限の分野では、Guava はマルチスレッド モジュールの下に次の # 機能を提供します。 ##RateLimiter で始まる電流制限サポート クラスですが、そのスコープは「現在の」サーバーに限定されています。言い換えれば、Guawa の電流制限は単一マシンの電流制限であり、複数のマシンまたは JVM プロセスにわたって何も行うことはできません。たとえば、現在 2 台のサーバー [
サーバー 1,
サーバー 2] があり、どちらのサーバーもログイン サービスをデプロイしています。これら 2 台のマシンでトラフィック制御を実行したい場合、 , たとえば、2 台のマシンの合計訪問数を 1 秒あたり 20 回以内に制御する場合、Guava を使用して行う場合、各マシンの訪問数を個別に制御できるのは 10 以下のみです。
Guava は分散システム用のソリューションではありませんが、シンプルで軽量のクライアント電流制限コンポーネントとして、電流制限アルゴリズムを説明するのに非常に適しています
サービス ゲートウェイは、分散リンク全体の最初のレベルとして、すべてのユーザー要求を受け入れるため、ゲートウェイ レベルで電流を制限することが適切なエントリ ポイントです。上から下へのパスは次のとおりです:
Nginx の現在の制限
システム アーキテクチャにおいて、Nginx のプロキシとルーティング転送はゲートウェイ層の非常に重要な機能であり、Nginx 本来の軽量かつ優れた設計により、多くの企業の最初の選択肢となっています。ゲートウェイ レベルから。ほとんどのネットワーク トラフィックに耐えられるフロントエンド ゲートウェイとして使用できるため、電流制限に Nginx を使用することも良い選択です。Nginx では、電流制限に基づいた一般的に使用されるポリシー構成も提供されます。
Nginx は 2 つの電流制限方法を提供します。1 つはレートを制御する方法、もう 1 つは同時接続数を制御する方法です。レートの制御
limit_req_zone
を使用して単位時間あたりのリクエスト数、つまりレート制限を制限する必要があります Nginx の現在の制限統計はミリ秒に基づいているため、設定した速度は 2r/s です。この変換は、単一の IP では 500 ミリ秒以内に 1 つのリクエストのみが通過でき、2 番目のリクエストは開始直後のみ通過できることを意味します。 501ミリ秒から。
burst=4
各 IP で最大 4 つのバースト リクエストが許可されることを意味します
同時実行数の制御
Uselimit_conn_zone
と limit_conn
2 つの命令で同時実行数を制御できます
limit_conn perip 10
は、単一の IP が同時に最大 10 個の接続を保持できるように制限することを意味します。 limit_conn perserver 100
は、サーバーが同時に処理できる同時接続の合計数が 100 であることを意味します。
注: この接続は、リクエスト ヘッダーがバックエンドによって処理された後にのみカウントされます。
ミドルウェアの電流制限
分散環境の場合、ミドルウェアは電流制限データを保存する中央ノードのような場所にすぎません。たとえば、制御インターフェイスのアクセス レートを 1 秒あたり 100 リクエストにしたい場合、現在の 1 秒以内に受信したリクエストの数をどこかに保存し、クラスター環境内のすべてのノードがアクセスできるようにする必要があります。では、この一時データを保存するにはどのようなテクノロジーを使用できるのでしょうか?
それなら Redis に違いないと誰もが思ったはずです。Redis の有効期限機能を使用すると、現在の制限の期間 (1 秒あたり 10 リクエスト、または 10 秒ごとに 10 リクエストなど) を簡単に設定できます。 )。同時に、Redis にはスクリプト プログラミングという特別なスキルもあります。電流制限ロジックをスクリプトに記述し、それを Redis に埋め込むことができます。これにより、電流制限の責任がサービス層から完全に分離されます。強力な同時実行特性と高い利用可能なクラスター アーキテクチャは、大規模クラスターへの現在制限されたアクセスも十分にサポートできます (reids lua)。
電流制限コンポーネント
上で紹介した方法に加えて、現在、Sentinel など、同様の機能を提供するオープン ソース コンポーネントがいくつかあります。これは良い選択です。 。 Sentinel は、Alibaba によって作成されたオープン ソース コンポーネントであり、Spring Cloud Alibaba コンポーネント ライブラリに含まれています。Sentinel は、電流制限の豊富な API セットと視覚的な管理コンソールを提供しており、電流制限の管理に簡単に役立ちます。
実際のプロジェクトでは、電流制限方法は 1 つだけ使用されます。電流制限戦略に効果を与えるために、複数の方法が組み合わせて使用されることがよくあります。階層の感覚。リソース使用量が最大に達しました。このプロセスでは、電流制限戦略の設計は、上で広く、底部でタイトである前述のファネル モデルを参照することもできます。ファネルのさまざまな部分の電流制限スキームの設計では、次の点に注意する必要があります。現在のコンポーネントの高可用性。
実際に私が参加したプロジェクトを例に挙げると、商品詳細ページのインターフェースを開発したのですが、モバイルタオバオの転用により、アプリ側のアクセスリクエストはまずアリババのmtopゲートウェイを経由します。ゲートウェイ層では、電流制限は比較的緩くなります。リクエストがゲートウェイを介してバックエンドの製品詳細ページ サービスに到達した後、一連のミドルウェア電流制限コンポーネントを使用して、サービス上でより詳細な電流制限制御が実行されます
1) Tomcat は maxThreads を使用して電流制限を実装します。
2) Nginx の limit_req_zone
とバーストは、レート制限を実装するために使用されます。
3) Nginx の limit_conn_zone
と limit_conn
の 2 つの命令は、同時接続の総数を制御します。
4) タイム ウィンドウ アルゴリズムは、Redis の順序付きコレクションを利用して実装できます。
5) リーキー バケット アルゴリズムは、Redis-Cell を使用して実装できます。
6) トークン アルゴリズムは、Google の guava パッケージを解決することで実装できます。
Redis で実装された電流制限ソリューションは分散システムで使用できますが、guava で実装された電流制限ソリューションはスタンドアロン環境にのみ適用できることに注意してください。サーバー側の電流制限が面倒だと感じる場合は、プロジェクトのビジネス ニーズを満たすことができる場合に限り、コードを変更せずにコンテナーの電流制限 (Nginx または Tomcat) を直接使用できます。
Tomcat 8.5 バージョンの最大スレッド数は、conf/server.xml
設定にあります。maxThreads は最大スレッド数です。 Tomcat のリクエスト時 同時実行数がこの値 (maxThreads) より大きい場合、リクエストは実行のためにキューに入れられ、電流制限の目的が完了します。 ######知らせ:###
maxThreads の値は適切に増やすことができます。Tomcat のデフォルトは 150 (Tomcat バージョン 8.5) ですが、この値は大きいほど良いわけではありません。特定のサーバー構成によって異なります。毎回注意する必要があります。スレッドが開始されると、スレッド スタック用に 1MB の JVM メモリ領域が必要になり、スレッドが増えるほど GC の負担が重くなります。
最後に、オペレーティング システムにはプロセス内のスレッド数に一定の制限があることに注意してください。Windows の各プロセスのスレッド数は 2000 を超えることはできません。 Linux の各プロセスのスレッド数は 1,000 を超えることはできません。
以上が電流制限と一般的な解決策を 10 分で理解します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。