現在の制限の目的は、同時アクセス/リクエストの速度を制限するか、タイムウィンドウ内でリクエストの速度を制限することにより、システムを保護することです。制限レートに達すると、サービスを拒否できます。
数日前、私はグアワを使用して単一アプリケーションのストリームの制限を実現する計画を読みました。 「Redis in Action」を参照して、JEDISバージョンを実装します。これらはすべてビジネスレベルの制限です。実際のシナリオでの一般的な制限戦略:
nginxアクセスレイヤー電流制限
アカウント番号、IP、システムコールロジックなどの特定のルールに従って、NGINXレベルで電流を制限する
ビジネスアプリケーションシステムの電流制限
ビジネスコードを介したトラフィックの制御このトラフィックは、セマフォと呼ばれます。これはロックとして理解できます。これは、リソースに同時にアクセスできるプロセスの数を制限できます。
コード実装
Redis.clients.jedis.jedisをインポート; Import Redis.clients.jedis.transaction; Import Redis.clients.jedis.zparams; Import java.util.list;/** * @email [email protected] * @data 2017-08 */public class edisic 「バケツ」; private static final string bucket_count = "bucket_count"; private static final string bucket_monitor = "bucket_monitor";静的文字列AcquireTokenFrombucket(Jedis Jedis、int lime、long timeout){string識別子= uuid.randomuuid()。toString(); long now = system.currenttimemillis();トランザクショントランザクション= jedis.multi(); // Semaphore Transaction.zremrangeByscore(backet_monitor.getBytes()、 "-inf" .getBytes()、string.valueof(now -timeout).getBytes()); zParams params = new Zparams(); params.weightsbydouble(1.0,0.0); Transaction.Zinterstore(Bucket、Params、Bucket、Bucket_Monitor); // counter selfincrement transaction.incr(bucket_count); list <Object> results = transaction.exec(); long counter =(long)results.get(results.size() - 1); transaction = jedis.multi(); transaction.zadd(bucket_monitor、now、識別子); transaction.zadd(バケット、カウンター、識別子); transaction.zrank(バケット、識別子); results = transaction.exec(); //ランキングを取得して、リクエストがセマフォの長いランクを取得したかどうかを判断します。 if(rank <lime){return識別子; } else {//セマフォは取得されませんでした。トランザクション= jedis.multi(); transaction.zrem(bucket_monitor、識別子); transaction.zrem(bucket、識別子); transaction.exec(); } nullを返します。 }}
電話
インターフェイスコールをテストします
@getMapping( "/")public void index(httpservletResponse応答)IoException {jedis jedis = jedispool.getResource(); string token = redisratelimiter.acquiretokenfrombucket(jedis、lime、timeout); if(token == null){respons.senderror(500); } else {//あなたのビジネスロジック} jedispool.returnresource(jedis);}最適化
インターセプター +注釈を使用してコードを最適化します
インターセプター
@configurationstatic class webmvcconfigurer extends webmvcconfigureradapter {private logger logger = loggerfactory.getlogger(webmvcconfigurer.class); @Autowired Private Jedispool Jedispool; public void addInterceptors(interceptorregistry registry){registry.addinterceptor(new Handlerinterceptoradapter(){public boolean prehandle(httpservletrequest request、httpservletresponse応答、オブジェクトハンドラー)スロー例外ratelimiter ratelimiter.getannotation(ratelimiter!= null){ratelimiter.limit() (token == null){senderror(500); }}定義注釈
/** * @email [email protected] * @data 2017-08 *現在の制限annotation */@target(elementtype.method)@retention(retentionpolicy.runtime)@documentedpublic @interface ratelimiter {int limit()default 5; int timeout()default1000;}
使用
@RatelImiter(Limit = 2、TimeOut = 5000)@getMapping( "/test")public void test(){}同時テスト
ツール:Apache-Jmeter-3.2
注:Semaphore Returns 500を取得していないインターフェイスは500、ステータスは赤で、Semaphore Returns 200を取得したインターフェイス、ステータスは緑です。
制限要求セマフォが2の場合、5つのスレッドが送信されます。
制限要求セマフォが5の場合、10個のスレッドが送信されます。
材料
Reids + Luaに基づく実装
要約します
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。