同時三剣客の限流方案の総括
7662 ワード
前言
高同時性のシステムでは、キャッシュ、ダウングレード、ストリーム制限の3つの利器がシステムを保護します.ストリーム制限でよく見られるアプリケーションシーンは、秒殺、注文、コメントなどの突発的な同時問題です.
本文
限流の目的
ストリーム制限の目的は、同時アクセス/要求を制限すること、または時間ウィンドウ内の要求を制限することによってシステムを保護することであり、制限速度に達すると、サービス(エラー・ページに移動したり、リソースがなくなったことを通知したり)、列に並んだり、待機したり(秒殺、コメント、注文)、ダウングレード(商品詳細ページ在庫のデフォルト在庫品などの基板データまたはデフォルトデータに戻る)を拒否することができます.
げんりゅうほうしき
nginx
のlimit_conn
モジュールのような瞬時同時接続数を制限するGuava
のRateLimiter
、nginx
のlimit_req
モジュール、毎秒の平均レートを制限)MQ
の消費率CPU
またはメモリ負荷等に応じる、ストリームげんりゅうアルゴリズム
1.トークンバケツ
2.バケツ漏れ
3.カウンタ
カウンタを使用してストリーム制限を行うこともできます.主に、データベース接続プール、スレッドプール、秒殺の同時数などの総同時数を制限するために使用されます.グローバル総要求数または一定期間の総要求数で設定されたバルブ値によりストリームを制限する.これは平均速度制限流ではなく,単純で乱暴な制限流方式である.
トークンバケツvsドレインバケツ
トークンバケツは、平均流入速度を制限し、バースト要求を許可し、ある程度のバースト流量を許可する.
ドレインバケツは、定量的流出速度を制限し、バースト流入速度を平滑化する.
レベル制限フローの適用
1.ストリーム制限総リソース数
プール化テクノロジーを使用して、接続プール、スレッドプールの合計リソース数を制限できます.例えば、各アプリケーションに割り当てられたデータベース接続が
100
である場合、本アプリケーションは最大100
個のリソースを使用することができ、待機または異常放出を超えることができる.2.ストリーム制限合計同時/接続/要求数
Tomcat
を使用した場合、Connector
のいずれかの構成には次のパラメータがあります.Tomcat
は、要求を処理するための最大スレッド数を開始することができ、要求処理量が最大スレッド数よりはるかに大きい場合、硬直する可能性があります.Tomcat
のスレッドが応答に忙しい場合、新しく来た接続はキューに入り、キューサイズを超えると接続を拒否します.3.ストリーム制限インタフェースの合計同時/要求数
Java
のAtomicLong
を使用して、コードを示します.try{
if(atomic.incrementAndGet() > ) {
//
} else {
//
}
} finally {
atomic.decrementAndGet();
}
4.あるインタフェースのタイムウィンドウ要求数を制限する
Guava
のCache
を使用して、コードを示します.LoadingCache counter = CacheBuilder.newBuilder()
.expireAfterWrite(2, TimeUnit.SECONDS)
.build(newCacheLoader() {
@Override
public AtomicLong load(Long seconds) throws Exception {
return newAtomicLong(0);
}
});
longlimit =1000;
while(true) {
//
long currentSeconds = System.currentTimeMillis() /1000;
if(counter.get(currentSeconds).incrementAndGet() > limit) {
System.out.println(" : " + currentSeconds);
continue;
}
//
}
5.平滑ストリームのあるインタフェースの要求数
従来のストリーム制限方式では、バースト要求にうまく対応できなかった.すなわち、瞬間要求が許可され、いくつかの問題を引き起こす可能性がある.そのため、一部のシーンでは、バーストリクエストを改造し、平均レートリクエスト処理に改造する必要がある.
Guava RateLimiter
はトークンバケツアルゴリズム実装を提供する.SmoothBursty
)SmoothWarmingUp
)スムーズバーストリミット(SmoothBursty)
RateLimiter limiter = RateLimiter.create(5);
System.out.println(limiter.acquire());
System.out.println(limiter.acquire());
System.out.println(limiter.acquire());
System.out.println(limiter.acquire());
System.out.println(limiter.acquire());
System.out.println(limiter.acquire());
次のような出力が得られます.
0.0
0.198239
0.196083
0.200609
0.199599
0.19961
スムースウォームリミット(SmoothWarmingUp)
RateLimiter limiter = RateLimiter.create(5, 1000, TimeUnit.MILLISECONDS);
for(inti = 1; i < 5; i++) {
System.out.println(limiter.acquire());
}
Thread.sleep(1000L);
for(inti = 1; i < 5; i++) {
System.out.println(limiter.acquire());
}
次のような出力が得られます.
0.0
0.51767
0.357814
0.219992
0.199984
0.0
0.360826
0.220166
0.199723
0.199555
SmoothWarmingUp
の作成方法:RateLimiter.create(doublepermitsPerSecond, long warmupPeriod, TimeUnit unit);
速度は台形の上昇速度であり、つまり冷却起動時に比較的大きな速度で平均速度に徐々に到達する.次いで平均速度(台形が平均速度に低下する)に傾く.
warmupPeriod
パラメータを調整することによって、最初から平滑固定速度を実現することができる.ぶんぷしきげんりゅう
分散型ストリーム制限は、ストリーム制限サービスを原子化することが最も重要であり、解決策は
redis + lua
またはnginx + lua
技術を用いて実現することができる.アクセス層限流
アクセス層は、通常、トラフィックを要求する入口を指し、その主な目的は以下のとおりである.
Nginx
アクセス層ストリーム制限について、Nginx
を使用して、2つのモジュールを備えることができる:接続数ストリーム制限モジュールngx_http_limit_conn_module
とドレインバケツアルゴリズムによって実現される要求ストリーム制限モジュールngx_http_limit_req_module
.より複雑なストリーム制限シナリオは、OpenResty
によって提供されるLua
ストリーム制限モジュールlua-resty-limit-traffic
を使用して行うこともできる.KEY
に対応する総ネットワーク接続数を制限するために使用され、例えばIP
、ドメイン名次元に従って制限することができる.KEY
に対応する要求の平均レートを制限するために使用され、平滑モード(delay
)と許可バーストモード(nodelay
)の2つの方法がある.OpenResty
によって提供されるLua
ストリーム制限モジュールlua-resty-limit-traffic
は、より複雑なストリーム制限シナリオを行うことができる.技術公衆番号へようこそ:零壹技術スタック
このアカウントでは、仮想マシンの基礎、マルチスレッドプログラミング、高性能フレームワーク、非同期、キャッシュ、メッセージミドルウェア、分散型およびマイクロサービス、アーキテクチャ学習、階層化などの学習資料と文章を含むバックエンド技術の乾物を共有し続けます.