gRPC-Client-Lastausgleich

9

Ich benutze gRPC mit Python als Client / Server in kubernetes-Pods ... Ich möchte in der Lage sein, mehrere Pods desselben Typs (gRPC-Server) zu starten und den Client eine Verbindung zu ihnen herstellen zu lassen (zufällig).

Ich habe 10 Pods des Servers verschickt und einen "Service" eingerichtet, um sie zu targetieren. Dann habe ich mich im Client mit dem DNS-Namen des Dienstes verbunden - das bedeutet, dass kubernetes den Lastenausgleich durchführen und mich zu einem zufälligen Server-Pod leiten sollte. In Wirklichkeit ruft der Client die gRPC-Funktionen auf (was gut funktioniert), aber wenn ich mir die Protokolle anschaue, sehe ich, dass alle Anrufe zum selben Server-Pod gehen.

Ich gehe davon aus, dass der Client eine Art DNS-Caching durchführt, was dazu führt, dass alle Anrufe an denselben Server gesendet werden. Ist das der Fall? Gibt es sowieso, um es zu deaktivieren und den gleichen Stub-Client zu einem "neuen" Anruf und holen Sie eine neue IP durch DNS mit jedem Anruf?

Ich bin mir des Aufwands bewusst, den ich verursachen könnte, wenn ich den DNS-Server jedes Mal abfrage, aber die Verteilung der Last ist für mich im Moment viel wichtiger.

BEARBEITEN

wahrscheinlich kein Caching-Problem ... Könnte nur sein, wie gRPC funktioniert. HTTP / 2 und dauerhafte wiederverwendbare Verbindung. Kann ich nach jedem Anruf die Verbindung trennen?

    
Idan 22.09.2016, 16:03
quelle

2 Antworten

10

Lassen Sie mich die Gelegenheit nutzen, um zu antworten, indem Sie beschreiben, wie die Dinge funktionieren sollen.

Die Funktionsweise von clientseitigem LB im gRPC C-Kern (die Grundlage für alle außer den Java- und Go-Varianten oder gRPC) ist wie folgt (das autorisierende Dokument finden Sie hier ):

Clientseitige LB wird absichtlich einfach und "dumm" gehalten. Die Art und Weise, wie wir komplexe LB-Richtlinien implementieren, erfolgt über einen externen LB-Server (wie im oben genannten Dokument beschrieben). Sie sind nicht mit diesem Szenario beschäftigt. Stattdessen erstellen Sie einfach einen Kanal, der die (standardmäßige) pick-first LB-Richtlinie verwendet.

Die Eingabe für eine LB-Richtlinie ist eine Liste der aufgelösten Adressen. Wenn foo.com bei Verwendung von DNS in [10.0.0.1, 10.0.0.2, 10.0.0.3, 10.0.0.4] aufgelöst wird, versucht die Richtlinie, eine Verbindung zu allen herzustellen. Der erste, der erfolgreich verbunden wird, wird zum ausgewählten , bis er die Verbindung trennt . Also der Name "Pick-first". Ein längerer Name hätte sein können: "Wählen Sie zuerst und bleiben Sie so lange wie möglich dabei", aber das hat zu einem sehr langen Dateinamen geführt :). Wenn / wenn die ausgewählte Verbindung getrennt wird, wird die Richtlinie für die erste Auswahl zur Rückgabe der nächsten erfolgreich verbundenen Adresse (intern als "verbundener Unterkanal" bezeichnet), falls vorhanden, übergehen. Erneut wählt er diesen verbundenen Unterkanal solange, wie er verbunden bleibt. Wenn alle Fehler auftreten, wird der Aufruf fehlschlagen.

Das Problem hierbei ist, dass die DNS-Auflösung, die intrinsisch Pull-basiert ist, nur 1) bei der Kanalerzeugung und 2) bei der Trennung des gewählten verbundenen Subkanals ausgelöst wird.

Eine Hacky-Lösung wäre im Moment, einen neuen Kanal für jede Anfrage zu erstellen (sehr ineffizient, aber bei der Einrichtung wäre das der Trick).

Angesichts der im ersten Quartal 2017 anstehenden Änderungen (siehe Ссылка ) können Kunden eine andere LB-Policy wählen, nämlich Round Robin. Außerdem könnten wir versuchen, ein "randomize" -Bit für diese Client-Konfiguration einzuführen, das die Adressen vor dem Ausführen von Round-Robin über sie mischen würde, um effektiv zu erreichen, was Sie beabsichtigen.

    
David García Quintas 28.09.2016, 19:37
quelle
1

Wenn Sie einen Vanilla-Kubernetes-Dienst erstellt haben, sollte der Dienst eine eigene virtuelle Last mit Lastenausgleich haben (prüfen Sie, ob kubectl get svc your-service für Ihren Dienst eine CLUSTER-IP anzeigt). Wenn dies der Fall ist, sollte das DNS-Caching kein Problem darstellen, da diese einzelne virtuelle IP den Verkehr unter den tatsächlichen Backends aufteilen sollte.

Probieren Sie kubectl get endpoints your-service aus, um zu bestätigen, dass Ihr Dienst über alle Ihre Backends informiert ist.

Wenn Sie einen Headless-Dienst haben, wird bei einer DNS-Suche ein A-Eintrag mit zurückgegeben 10 IPs (eins für jeden deiner Pods). Wenn Ihr Client immer die erste IP in einem A-Datensatz auswählt, würde dies auch das Verhalten erklären, das Sie sehen.

    
CJ Cullen 22.09.2016 17:06
quelle

Tags und Links