Kürzlich erlerntes Strombegrenzungswissen

Vorwort

Nur eine Glatze kann stärker werden.
Der Text wurde in mein GitHub-Repository aufgenommen. Willkommen bei Star: https://github.com/ZhongFuCheng3y/3y Ich
hatte während meines Studiums keinen Zugriff auf Dinge wie hohe Parallelität / großen Datenverkehr, daher habe ich das aktuelle Limit natürlich nicht berührt. Oben. Als ich mir das Projekt des Unternehmens ansah, stellte ich fest, dass es nützlich ist, den Strom (RateLimiter) zu begrenzen.

1. Einführung in die Grundkenntnisse der Strombegrenzung

Warum wollen Sie den Strom begrenzen? Ich glaube, ich muss nicht mehr sagen.

  • Zum Beispiel gehe ich am Wochenende zum Abendessen in ein Restaurant, aber es gibt zu viele Leute. Ich kann nur an der Rezeption eine Nummer holen und warten, bis die Nummer mich erreicht, bevor ich im Restaurant essen kann. Was ist, wenn es im Hotel kein aktuelles Limit gibt? Wenn das Essen eintrifft, kommen die Leute herein und das Restaurant kann den Personenfluss nicht bewältigen, so dass es leicht zu Unfällen kommen kann (das Restaurant ist voller Menschen und es gibt keinen Weg mehr. Das Hotelpersonal ist zusammengebrochen und konnte nicht damit umgehen).
  • Zurück zum Code in der Welt ist derselbe, der Server kann eine begrenzte Anzahl von Anfragen verarbeiten, insbesondere wenn eine große Anzahl von Anfragen, wir müssen den Fluss begrenzen (entweder die Anfrage warten lassen oder die Anfrage werfen)
    Kürzlich erlerntes Strombegrenzungswissen
    , um
    den Code in der Welt zu begrenzen , Es gibt zwei gängige Algorithmen zur Strombegrenzung:

  • Token-Bucket-Algorithmus
  • Leaky-Bucket-Algorithmus

    1.1 Was ist der Leaky-Bucket-Algorithmus?

Zum Beispiel habe ich jetzt einen Eimer, und der grüne ist die Kapazität, die ich Wasser aufnehmen kann. Wenn er die Kapazität überschreitet, die ich halten kann, und dann Wasser in den Eimer gießt, läuft er über (Begrenzungsfluss):

Kürzlich erlerntes Strombegrenzungswissen

Was wir derzeit über den Eimer wissen können, ist:

  • Die Kapazität des Eimers ist festgelegt (es ist die grüne auf dem Bild).
  • Wenn die Kapazität des Eimers überschritten wird, läuft er über (entweder warten oder direkt entsorgen).
    OK, jetzt graben wir ein Loch in den Eimer, damit Wasser aus dem Loch fließen kann:

Kürzlich erlerntes Strombegrenzungswissen
Ein Loch wurde gegraben, und
die Größe der Öffnung des aus dem Loch fließenden Wassereimers wurde festgelegt, so dass auch die aus dem Loch fließende Wasserrate festgelegt wurde.

Zusammenfassend lässt sich sagen, dass der Algorithmus nur zwei Parameter benötigt:

  • Eimerkapazität
  • Leckraten-
    Leaky-Bucket-Algorithmus, implementiert in zwei:
  1. Die Situation eines plötzlichen Fließens ist nicht zulässig: Wenn die Wasserzuflussrate größer als die Wasseraustrittsrate ist, verwerfen Sie das überschüssige Wasser direkt. Zum Beispiel kann mein Eimer 100 l aufnehmen, aber mein Eimer hat eine Wasserausstoßrate von 10 l / s. Zu diesem Zeitpunkt lasse ich nur 10 l Wasser in den Eimer, wenn 100 l / s Wasser eingehen, und der Rest ist eingeschränkt. (Begrenzte die Anforderungsgeschwindigkeit)
  2. Erlaube einen bestimmten Verkehrsschub: Mein Eimer kann 100 l aufnehmen. Wenn mein Eimer jetzt leer ist, können die 100 l Wasser sofort in meinen Eimer gelangen. Ich werde das Wasser mit einer Geschwindigkeit von 10 l / s abfließen lassen. Wenn immer noch 100 l Wasser hereinkommen, kann ich den Durchfluss nur begrenzen.
    Nach der obigen Analyse wissen wir:

Der Leaky-Bucket-Algorithmus kann den Burst-Verkehr im Netzwerk glätten (da die Rate der Wasserleckage festgelegt ist).

1.2 Was ist der Token-Bucket-Algorithmus?

Jetzt habe ich noch einen Eimer. Dieser Eimer wird nicht für Wasser verwendet, sondern für Token:

Kürzlich erlerntes Strombegrenzungswissen
Token im Eimer
werden mit einer bestimmten Geschwindigkeit in den Eimer geworfen. Zum Beispiel werfe ich 10 Token pro Sekunde in den Eimer:

Kürzlich erlerntes Strombegrenzungswissen
Wirf Token mit einer bestimmten Geschwindigkeit in den Eimer
. Es gibt eine Obergrenze für die Anzahl der Token, die geladen werden können. Beispielsweise kann mein Eimer höchstens 1000 Token aufnehmen.

Jede Anfrage geht ein, sie geht in den Eimer, um einen Token zu erhalten

  • Wenn ich zum Beispiel in dieser Sekunde 1001 Anfragen habe, gehe ich zum Bucket und hole 1001 Token. Zu diesem Zeitpunkt kann es zwei Situationen geben:
  • Es befinden sich keine 1001 Token im Bucket, nur 1000 Token, sodass die Anforderung, die den Token nicht erhält, nur blockiert werden kann (Warten).
  • Der Bucket enthält 1001 Token, und alle Anforderungen können ausgeführt werden.
    Kürzlich erlerntes Strombegrenzungswissen

    Der Token-Bucket-Algorithmus unterstützt Burst-Verkehr im Netzwerk

Der Unterschied zwischen einem undichten Bucket und einem Token-Bucket: Aus dem obigen Beispiel kann wahrscheinlich jeder ersehen, dass der undichte Bucket nur Anforderungen mit einer festen Rate verarbeiten kann, während der Token-Bucket Anforderungen mit der maximalen Anzahl von Token im Bucket verarbeiten kann.

Zweitens verwenden Sie Rate Limiter

RateLimiter ist eine strombegrenzende Komponente von Guava. Mein System verwendet diese strombegrenzende Komponente, die sehr bequem zu verwenden ist.

Pom-Abhängigkeit einführen:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>20.0</version>
</dependency>

RateLimiter basiert auf dem Token-Bucket-Algorithmus, die API ist sehr einfach, siehe folgende Demo:

public static void main(String[] args) {
        //线程池
        ExecutorService exec = Executors.newCachedThreadPool();
        //速率是每秒只有3个许可
        final RateLimiter rateLimiter = RateLimiter.create(3.0);

        for (int i = 0; i < 100; i++) {
            final int no = i;
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    try {
                        //获取许可
                        rateLimiter.acquire();
                        System.out.println("Accessing: " + no + ",time:"
                                + new SimpleDateFormat("yy-MM-dd HH:mm:ss").format(new Date()));

                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }
            };
            //执行线程
            exec.execute(runnable);
        }
        //退出线程池
        exec.shutdown();
    }

Wir können den Ergebnissen entnehmen, dass nur drei pro Sekunde ausgeführt werden können:

Kürzlich erlerntes Strombegrenzungswissen
Führen Sie drei pro Sekunde aus

Drei, verteilte Strombegrenzung

RateLimiter ist eine Strombegrenzungskomponente für eine Maschine. Was kann ich tun, wenn es sich um eine verteilte Anwendung handelt?

Dies kann mit Redis + Lua erreicht werden. Der ungefähre Lua-Skriptcode lautet wie folgt:

local key = "rate.limit:" .. KEYS[1] --限流KEY
local limit = tonumber(ARGV[1])        --限流大小
local current = tonumber(redis.call('get', key) or "0")
if current + 1 > limit then --如果超出限流大小
  return 0
else  --请求数+1,并设置1秒过期
  redis.call("INCRBY", key,"1")
   redis.call("expire", key,"1")
   return current + 1
end

Der Java-Code lautet wie folgt:

public static boolean accquire() throws IOException, URISyntaxException {
    Jedis jedis = new Jedis("127.0.0.1");
    File luaFile = new File(RedisLimitRateWithLUA.class.getResource("/").toURI().getPath() + "limit.lua");
    String luaScript = FileUtils.readFileToString(luaFile);

    String key = "ip:" + System.currentTimeMillis()/1000; // 当前秒
    String limit = "5"; // 最大限制
    List<String> keys = new ArrayList<String>();
    keys.add(key);
    List<String> args = new ArrayList<String>();
    args.add(limit);
    Long result = (Long)(jedis.eval(luaScript, keys, args)); // 执行lua脚本,传入参数
    return result == 1;
}

Erläuterung:

Kürzlich erlerntes Strombegrenzungswissen

Mehr als 200 Originalartikel Technische Artikel
Massive Videoressourcen
Exquisite Mind-Map-
Gesichtsfragen
Drücken Sie den Scan-Code. Möglicherweise
ist mir das Anschauen und Teilen sehr wichtig.

Ich denke du magst

Origin blog.51cto.com/15082392/2590346
Empfohlen
Rangfolge