Wir haben diese JavaEE-Webanwendung (JSP+Struts+Hibernate+MySQL), die derzeit auf einem einzelnen Server läuft. Aufgrund des Wachstums der Website und Leistungsproblemen haben wir uns entschieden, das Projekt auf mehreren Maschinen zu clustern. Die Website sollte etwa 5000 Anfragen pro Sekunde tolerieren. Nach einigem Googeln und Lesen bin ich auf einige Strategien gestoßen, um dies zu erreichen:
- Verwendung von Apache als Front-End-Load Balancer und Reverse-Proxy, einige Tomcat-Instanzen, jede auf einer separaten Maschine, und schließlich ein DB-Server, auf dem MySQL läuft. Tomcat-Instanzen können bei Bedarf skaliert werden.
- Verwenden vonNginxals Front-End-Load Balancer und Reverse-Proxy. Der Rest wäre derselbe wie oben.
- Verwenden vonHAProxyals Front-End-Load Balancer und Reverse-Proxy. Der Rest wäre derselbe wie oben.
Ich nehme an, dass bei den oben genannten Ansätzen der gesamte Datenverkehr über den Front-End-Load Balancer (Apache, Nginx oder HAProxy Server) laufen sollte. Dadurch wird der Front-End-Server zu einem Engpass und auch zu einem SPOF. Ist das richtig? Kann ein einzelner Front-End-Server den gesamten Datenverkehr einer großen Webanwendung tolerieren?
Um dieses Problem zu umgehen, habe ich mir eine Art handgemachte Strategie ausgedacht:
- Platzieren der Anmeldeseite und Authentifizierungsaktionen auf einem Front-End-Server (z. B. wird dieser von myapp.com aus zugänglich sein). Wenn sich ein Benutzer erfolgreich anmeldet, wird er zu einem der Back-End-Server (z. B. srv1.myapp.com) umgeleitet und kann seine Aktivität dort fortsetzen.
Bin ich also auf dem richtigen Weg?
Teilen Sie mir Ihre Meinung zu diesen Ansätzen mit und wenn Ihnen ein besserer Ansatz einfällt, erwähnen Sie ihn bitte hier.
Antwort1
Es ist keine gute Idee, die Anmeldeseite auf einem Frontend-Server zu platzieren und auf Backends umzuleiten. Benutzer setzen möglicherweise Lesezeichen für Ihre Backend-Server, es kann zu einer ungleichmäßigen Verteilung kommen und wenn ein Server ausfällt, versuchen Benutzer trotzdem, ihn aufzurufen, wenn sie sich in derselben Sitzung befinden.
Was Sie brauchen, ist ein aktives/passives (Herzschlag/Schrittmacher/IP-Ausfallsicherung/DNS-Failover) oder aktiv/aktiv (DNS-Round-Robin/Netzwerklastenausgleich) Frontend-Server.
Bei der Aktiv/Passiv-Variante wird Ihr gesamter Datenverkehr auf einen Frontend-Server umgeleitet, während ein zweiter in Bereitschaft steht (Hot-Standby). Wenn der erste ausfiel, führten Sie irgendwie ein Failover durch (entweder durch Neuzuweisung der IP-Adresse oder durch Ändern des DNS*), um auf den zweiten Server zu verweisen.
Mit Active/Active wären zwei (oder mehr) Server ständig aktiv, mit EtherDNS-Round-RobinoderIP-/Netzwerklastenausgleichum die Last (ungefähr) gleichmäßig zwischen beiden zu verteilen. Dann würden die beiden Server die Last wiederum auf Ihre Backend-Server verteilen.
„Aktiv/Aktiv“ ist die Methode, die von den meisten großen Webanwendungen verwendet wird. (Sehen Sie sich die DNS-Einträge von YouTube/Google/Twitter/Wordpress.com/Tumblr an, dort finden Sie mehrere IPs für die Server für DNS-Round-Robin.)
Sobald Sie diese Entscheidung getroffen und umgesetzt haben, haben Sie nur noch die Wahl zwischen Lösungen. Persönlich würde ich vorschlagenNGINXaber jeder hat seine Vorlieben (HAProxy,Tintenfisch,Cherokee,Lichtgeschwindigkeit,F5(Hardware),Cisco(Hardware) und unzählige andere).
Leider können wir bei solchen Fragen nicht einfach sagen „mach das“, denn es hängt wirklich von deinen Anforderungen ab. Recherchiere einige der oben genannten Schlüsselwörter und wenn du spezielle Fragen hast, kannst du sie gerne stellen.
*DNS-basiertes Failover sollte nach Möglichkeit vermieden werden, da einige Clients DNS über seine TTL hinaus zwischenspeichern, was nicht ideal ist.
Antwort2
Ich weiß nichts über Nginx, aber Sie können einige Haproxy-Load Balancer in einer Aktiv/Passiv-Konfiguration koppeln, um zu verhindern, dass Haproxy zu diesem einzigen Ausfallpunkt wird.
Es gibt auch kommerzielle Lösungen, aber aus irgendeinem Grund scheinen diese bei Serverfehlern nicht so viel „Tinte“ zu bekommen.