Hintergrund Wie wir alle wissen, ist Nginx ein Hochleistungs-Webserver, der häufig zum Lastenausgleich und als Reverse-Proxy verwendet wird. Der sogenannte Reverse-Proxy entspricht dem Forward-Proxy. Der Forward-Proxy ist das, was wir im herkömmlichen Sinne als „Proxy“ verstehen: Unter normalen Umständen kann beispielsweise in China nicht auf Google zugegriffen werden. Wenn wir darauf zugreifen müssen, müssen wir es über eine Proxy-Schicht weiterleiten. Dieser Forward-Proxy stellt den Server (also Google) dar, während der Reverse-Proxy den Client (also den Benutzer) darstellt. Nachdem die Benutzeranforderung nginx erreicht hat, leitet nginx die Benutzeranforderung an den tatsächlichen Backend-Dienst weiter und gibt das Ergebnis an den Benutzer zurück. (Bild aus Wikipedia) Forward-Proxy und Reverse-Proxy werden eigentlich aus der Perspektive des Benutzers definiert. Forward bedeutet, den Dienst, den der Benutzer anfordern möchte, per Proxy zu übermitteln, während Reverse bedeutet, den Benutzer per Proxy zu übermitteln, um eine Anforderung an den Dienst zu initiieren. Es gibt einen sehr wichtigen Unterschied zwischen den beiden: Der Forward-Proxy-Server kennt den Anforderer nicht und der Reverse-Proxy-Anforderer kennt den Server nicht. Das häufigste Szenario, in dem nginx als Reverse-Proxy verwendet wird, ist das bekannte http-Protokoll. Durch Konfigurieren der Datei nginx.conf können Sie ganz einfach eine Reverse-Proxy-Regel definieren: Arbeiterprozesse 1; Ereignisse { Arbeiterverbindungen 1024; } http { mime.types einschließen; Standardtyp Anwendung/Oktett-Stream; Server { hören Sie 80; Servername localhost; Standort / { Proxy-Passwort http://Domäne; } } } Nginx unterstützt den Reverse-Proxy des gRPC-Protokolls seit 1.13.10 und die Konfiguration ist ähnlich: Arbeiterprozesse 1; Ereignisse { Arbeiterverbindungen 1024; } http { mime.types einschließen; Standardtyp Anwendung/Oktett-Stream; Server { hören Sie 81 http2; Servername localhost; Standort / { grpc_pass http://ip; } } } Bei komplexeren Anforderungen stellt sich jedoch heraus, dass das gRPC-Modul von nginx tatsächlich viele Fallstricke aufweist und die Implementierungsfunktion nicht so vollständig ist wie die von http. Bei der Anwendung der http-Lösung treten Probleme auf. Szenario Zu Beginn war unser Szenario sehr einfach. Wir haben eine einfache C/S-Architektur über das gRPC-Protokoll implementiert: Diese einfache Direktverbindung ist jedoch in einigen Szenarien nicht möglich. Beispielsweise befinden sich Client und Server in zwei Netzwerkumgebungen und sind nicht miteinander verbunden. In diesem Fall ist es unmöglich, über eine einfache gRPC-Verbindung auf den Dienst zuzugreifen. Eine Lösung besteht darin, die Weiterleitung über einen zwischengeschalteten Proxyserver unter Verwendung der oben erwähnten nginx Reverse Proxy-gRPC-Methode durchzuführen: Der Nginx-Proxy wird auf einem Cluster bereitgestellt, auf den beide Umgebungen zugreifen können, wodurch der gRPC-Zugriff über Netzwerkumgebungen hinweg ermöglicht wird. Die folgende Frage lautet: Wie konfiguriert man diese Routing-Regel? Beachten Sie, dass unsere anfänglichen gRPC-Zielknoten klar sind, d. h. die IP-Adressen von Server1 und Server2. Wenn in der Mitte eine Schicht von Nginx-Proxys hinzugefügt wird, sind die Objekte der vom Client initiierten gRPC-Anforderungen alle IP-Adressen des Nginx-Proxys. Nachdem der Client eine Verbindung mit nginx hergestellt hat, woher weiß nginx, ob die Anforderung an Server1 oder Server2 weitergeleitet werden soll? (Hierbei handelt es sich bei Server1 und Server2 nicht einfach um redundante Bereitstellungen desselben Dienstes. Es kann erforderlich sein, anhand der Attribute der Anfrage, wie etwa der Benutzer-ID, zu entscheiden, wer antwortet. Daher kann Lastenausgleich nicht verwendet werden, um eine Antwortanfrage zufällig auszuwählen.) LösungWenn es sich um ein HTTP-Protokoll handelt, gibt es viele Möglichkeiten, es zu implementieren: Differenzieren nach PfadDie Anfrage fügt dem Pfad die Serverinformationen hinzu, zum Beispiel: /server1/service/method, und dann stellt nginx beim Weiterleiten der Anfrage die ursprüngliche Anfrage wieder her: Arbeiterprozesse 1; Ereignisse { Arbeiterverbindungen 1024; } http { mime.types einschließen; Standardtyp Anwendung/Oktett-Stream; Server { hören Sie 80; Servername localhost; Standort ~ ^/server1/ { Proxy-Passwort http://Domäne1/; } Standort ~ ^/server2/ { Proxy-Passwort http://Domäne2/; } } } Beachten Sie den Schrägstrich am Ende von http://domain/. Ohne diesen Schrägstrich wäre der angeforderte Pfad /server1/service/method, und der Server kann nur auf Anforderungen für /service/method antworten, was zu einem 404-Fehler führt. Differenzieren nach AnfrageparameternSie können die Informationen von Server1 auch in die Anforderungsparameter einfügen: Arbeiterprozesse 1; Ereignisse { Arbeiterverbindungen 1024; } http { mime.types einschließen; Standardtyp Anwendung/Oktett-Stream; Server { hören Sie 80; Servername localhost; Standort /Dienst/Methode { wenn ($query_string ~ x_server=(.*)) { Proxy-Passwort http://$1; } } } } Bei gRPC ist es jedoch nicht so einfach. Erstens unterstützt gRPC das Schreiben von URIs nicht. Die von nginx weitergeleitete Anfrage behält den ursprünglichen Pfad bei und kann den Pfad beim Weiterleiten nicht ändern. Dies bedeutet, dass die oben genannte erste Methode nicht durchführbar ist. Zweitens basiert gRPC auf dem HTTP 2.0-Protokoll. HTTP2 kennt das Konzept von queryString nicht. Im Anforderungsheader gibt es ein Element: path stellt den Anforderungspfad dar, z. B. /service/method, und dieser Pfad kann keine Anforderungsparameter enthalten, d. h. der Pfad kann nicht als /service/method?server=server1 geschrieben werden. Dies bedeutet, dass auch die zweite oben genannte Methode nicht durchführbar ist. Beachten Sie, dass der Anforderungsheader in HTTP2:Pfad den Pfad der Anforderung angibt. Warum ändern wir also nicht einfach:Pfad direkt? Arbeiterprozesse 1; Ereignisse { Arbeiterverbindungen 1024; } http { mime.types einschließen; Standardtyp Anwendung/Oktett-Stream; Server { hören Sie 80 http2; Servername localhost; Standort ~ ^/(.*)/Dienst/.* { grpc_set_header :Pfad /service/$2; grpc_pass http://$1; } } } Eine tatsächliche Überprüfung zeigt jedoch, dass diese Methode nicht durchführbar ist. Wenn Sie den Anforderungsheader von :path direkt ändern, meldet der Server einen Fehler. Ein möglicher Fehler ist wie folgt:
Nach dem Erfassen des Pakets wurde festgestellt, dass grpc_set_header das Ergebnis von :path nicht überschrieben, sondern einen neuen Anforderungsheader hinzugefügt hat, was dem Vorhandensein von zwei :path im Anforderungsheader entspricht. Dies kann der Grund sein, warum der Server einen 502-Fehler gemeldet hat. Wenn wir mit unserem Latein am Ende sind, denken wir an die Metadatenfunktion von gRPC. Wir können die Serverinformationen in den Metadaten auf der Clientseite speichern und sie dann während des Nginx-Routings gemäß den Serverinformationen in den Metadaten an den entsprechenden Back-End-Dienst weiterleiten, um unsere Anforderungen zu erfüllen. Für die Sprache Go erfordert das Festlegen von Metadaten die Implementierung der Schnittstelle PerRPCCredentials und die anschließende Übergabe einer Instanz dieser Implementierungsklasse beim Initiieren einer Verbindung: Typ extraMetadata-Struktur { IP-Zeichenfolge } Funktion (c extraMetadata) GetRequestMetadata(ctx Kontext.Kontext, URI ...Zeichenfolge) (Map[Zeichenfolge]Zeichenfolge, Fehler) { Karte zurückgeben[Zeichenfolge]Zeichenfolge{ "x-ip": c.Ip, }, Null } func (c extraMetadata) RequireTransportSecurity() bool { return false } Funktion main(){ ... // nginxProxy ist die IP- oder Domänenadresse des Nginx-Proxys var nginxProxy string // serverIp ist die IP-Adresse des Backend-Dienstes, berechnet basierend auf den Anforderungsattributen var Server-IP-Zeichenfolge con, err := grpc.Dial(nginxProxy, grpc.WithInsecure(), grpc.WithPerRPCCredentials(extraMetadata{Ip: serverIp})) } Leiten Sie es dann gemäß diesen Metadaten in der Nginx-Konfiguration an den entsprechenden Server weiter: Arbeiterprozesse 1; Ereignisse { Arbeiterverbindungen 1024; } http { mime.types einschließen; Standardtyp Anwendung/Oktett-Stream; Server { hören Sie 80 http2; Servername localhost; Standort ~ ^/Dienst/.* { grpc_pass grpc://$http_x_ip:8200; } } } Beachten Sie, dass hier die Syntax $http_x_ip verwendet wird, um auf die von uns übergebenen x-ip-Metadateninformationen zu verweisen. Diese Methode hat sich als effektiv erwiesen und der Client kann über den Nginx-Proxy erfolgreich auf den gRPC-Dienst des Servers zugreifen. ZusammenfassenEs gibt zu wenig Dokumentation für das gRPC-Modul von nginx. Die offizielle Dokumentation gibt nur den Zweck einiger Anweisungen an und erklärt nicht die Metadatenmethode. Es gibt auch wenig Online-Dokumentation, die dieses Thema berührt, was zu zwei oder drei Tagen Fehlerbehebung führte. Ich fasse den gesamten Vorgang hier zusammen und hoffe, dass er Leuten helfen kann, die auf dasselbe Problem stoßen. Dies ist das Ende dieses Artikels über die Fallstricke bei der Verwendung von nginx als Reverse-Proxy für grpc. Weitere relevante Inhalte zum Reverse-Proxy von nginx grpc finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen! Das könnte Sie auch interessieren:
|
>>: MySql-Freigabe der Nullfunktionsnutzung
1. Es wird empfohlen, den Root-Benutzer für die A...
Das Format des Textbereichs kann beim Speichern in...
In diesem Artikel wird der spezifische Code von V...
Im Docker-Design führt ein Container nur eine Anw...
Inhaltsverzeichnis DOM Knoten Elementknoten: Text...
erinnern: IDE-Festplatte: Die erste Festplatte is...
In diesem Artikel wird der spezifische Code von V...
Erstellen Sie eine Simulationsumgebung: Betriebss...
Gestern habe ich CentOS7 unter VMware installiert...
Es gibt eine Frage, die Webdesigner schon lange b...
So verwenden Sie CSS-Variablen in JS Verwenden Si...
1. Installation von Windows Server 2019 Installie...
Dieser Artikel verwendet das Centos7.6-System und...
Inhaltsverzeichnis Versteckte Probleme Lösung zur...
Heureka: 1. Erstellen Sie ein JDK-Image Starten S...