2016-09-22 2 views
9

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

Ich habe 10 Pods des Servers verschickt und einen "Service" eingerichtet, um sie zu erreichen. 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 vermute, 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 Overheads bewusst, den ich verursachen könnte, wenn es den DNS-Server jedes Mal abfragt, aber das Verteilen der Last ist viel wichtiger für mich im Moment.

EDIT

wahrscheinlich kein Problem Caching ... könnte nur die Art und Weise sein gRPC funktioniert. HTTP/2 und dauerhafte wiederverwendbare Verbindung. Kann ich nach jedem Anruf die Verbindung trennen?

Antwort

10

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

Die Art und Weise clientseitige LB im gRPC C Kern (die Grundlage für alle, aber die Java and Go Aromen oder gRPC) arbeitet, ist wie folgt (die maßgebliche doc here gefunden werden kann):

Client-seitiges 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 (Standard) 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 der ausgewählte , 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 von ihnen fehlschlagen, würde der Anruf 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 jetzt, einen neuen Kanal für jede Anfrage zu erstellen (sehr ineffizient, aber es würde den Trick bei der Einrichtung tun).

Aufgrund der Änderungen im ersten Quartal 2017 (siehe https://github.com/grpc/grpc/issues/7818) können Kunden eine andere LB-Richtlinie 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.

+0

Vielen Dank für die ausführliche Antwort. Eigentlich habe ich schon was du vorgeschlagen hast und einen neuen Kanal für jede Anfrage erstellt (nicht effizient, ich weiß). Aus Ihrer Antwort verstehe ich, dass nur die erste IP in den DNS Anfragen erhalten wird, bis es stoppt (keine verfügbaren Verbindungen/getötet/abgestürzt) und nur dann werden die Clients zur zweiten IP gelangen und so weiter ... ist das richtig? – Idan

+0

Ja. Bis auf Änderungen kann man Round Robin anstelle von Pick als LB-Policy auswählen, wie erwähnt. –

+0

Gibt es eine typische Lösung für die Skalierung der mehreren gRPC-Server? oder clientseitiger Lastenausgleich? –

1

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

Versuchen Sie kubectl get endpoints your-service, um zu bestätigen, dass Ihr Dienst tatsächlich über alle Ihre Backends weiß.

Wenn Sie eine headless service haben, gibt eine DNS-Suche einen A-Eintrag mit 10 IPs zurück (eine für jeden Ihrer 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.

+0

Es gibt einen CLUSTER_IP für den Server und ich kann sehen, dass ich alle Endpunkte habe, wenn ich Endpunkte bekomme. geht immer noch zum selben Server. Ich denke, es könnte die Art sein, wie gRPC funktioniert und die Wiederverwendung der Verbindung von HTTP/2 ... – Idan