まず、シーン記述
サーバプロセスの開発・インタフェースでは、クライアント・インターフェースの乱用を防ぐために、サーバリソースの保護は、一般に、我々は、サーバー上のさまざまなインターフェイスのための呼び出しの数が制限されます。例えば、1分として、例えば、サーバインターフェイスが上限値(上限)を超えることはできません呼び出し時間の期間(インターバル)で、回数ユーザについて、100倍。ユーザの数が呼び出しインターフェイスの上限を超えた場合、それはユーザの要求を指示することを拒否し、エラーメッセージを返します。
フロー制御戦略インターフェースサービス:転換、降格、電流制限。この記事では、サービス・インターフェースへの同時アクセスの頻度と量を減少させるが、下限トラフィックポリシーについて説明したが、高可用性サービス・インターフェースとビジネスアプリケーションシステムの交換です。
第二に、一般的な制限アルゴリズム
1、トークンバケットアルゴリズム
水が直接アセンブリを通ってオーバフローリーキーバケット(漏出バケット)アルゴリズムは、(非常にシンプルなアイデア、最初のバケットに排出する水(リクエスト)、一定速度(インターフェースに応答速度)でバケット水、流入速度でありますインターフェースアクセス頻度が応答速度を超える)、及び、要求を拒否し、伝送速度がリーキーバケットアルゴリズムは、以下の概略のデータに制限を課すことができることがわかります。
2つの変数が見ることができますがありますが、それは、トラフィックのサポートが急激に増加し、他のバケットの脆弱性(率)の大きさであるとき、水(バースト)を保存することができますどのくらい、バレルの大きさです。
リーキーバケットパラメータの漏洩速度は固定されているので、その結果、ネットワークリソースの競合が存在しない場合であっても(輻輳が発生していない)、トークンバケットアルゴリズムは、ポート速度にストリームバースト(バースト)しません。このように、投影用のトークンバケットアルゴリズムの存在を髪の流れ特性は非効率的です。
2、トークンバケットアルゴリズム
トークンバケットアルゴリズム(トークンバケット)と同様の効果リーキーバケットアルゴリズムが、反対方向に、より容易に理解される。以上の時間、システムは、定数1 / QPS間隔(QPS = 100なら、となりますインターバルバケットでは10ms)がトークン(バケツがいっぱいになった場合は、水道水で一定の増加が)、そこにある、リークを想像し、逆抜け穴追加され、新しい要求に結合されていない来て、私たちは、それぞれのトークンを取り、もしません。トークンは、彼らがブロックされたり、サービス拒否撮像することができます。
別の利点は、容易に速度を変更することができるトークンバケットである。率、バケットにトークンの速度を増加させる要求を増やす必要が一旦一般タイミング(例えば100ミリ秒)トークンの特定の数にタブを増加、リアルタイムの計算アルゴリズムのいくつかの亜種の数は、トークンを増やす必要があります。
Redisのを実装PHP +トークンバケットアルゴリズムに基づいて第三に、
<?php
namespace Api\Lib; /** * 限流控制 */ class RateLimit { private $minNum = 60; //单个用户每分访问数 private $dayNum = 10000; //单个用户每天总的访问量 public function minLimit($uid) { $minNumKey = $uid . '_minNum'; $dayNumKey = $uid . '_dayNum'; $resMin = $this->getRedis($minNumKey, $this->minNum, 60); $resDay = $this->getRedis($minNumKey, $this->minNum, 86400); if (!$resMin['status'] || !$resDay['status']) { exit($resMin['msg'] . $resDay['msg']); } } public function getRedis($key, $initNum, $expire) { $nowtime = time(); $result = ['status' => true, 'msg' => '']; $redisObj = $this->di->get('redis'); $redis->watch($key); $limitVal = $redis->get($key); if ($limitVal) { $limitVal = json_decode($limitVal, true); $newNum = min($initNum, ($limitVal['num'] - 1) + (($initNum / $expire) * ($nowtime - $limitVal['time']))); if ($newNum > 0) { $redisVal = json_encode(['num' => $newNum, 'time' => time()]); } else { return ['status' =