Verständnis von mod_proxy und Apache 2 zum Schreiben eines Comet-Servers

8

Ich versuche derzeit, einen einfachen HTTP-Server für eine Art Kometen -Technik (lange Polling) zu implementieren XHR-Anfragen). Da JavaScript bei Crossdomain-Anfragen sehr streng ist, habe ich ein paar Fragen:

  1. Wie ich verstanden habe, ist jeder Apache Worker blockiert, während er eine Anfrage bearbeitet, also würde das Schreiben des "Skripts" als eine gewöhnliche Webseite den Apache blockieren, wenn alle Arbeiter eine Anfrage haben, zu dienen. - & gt; Funktioniert nicht!
  2. Ich kam auf die Idee, einen eigenen einfachen HTTP-Server zu schreiben, nur um diese langen Abfragen zu bedienen. Dieser Server sollte nicht blockiert werden, sodass jeder Worker viele Anfragen gleichzeitig verarbeiten kann. Da meine Seite auch Inhalte / Bilder usw. enthält und mein Server keinen Server-Inhalt benötigt, habe ich ihn an einem anderen Port als 80 gestartet. Das Problem ist jetzt, dass ich nicht zwischen meinem JavaScript von meinem Apache und meinem Kometen interagieren kann -server läuft aufgrund verschiedener crossdomain-Einschränkungen auf einem anderen Port. - & gt; Funktioniert nicht!
  3. Dann kam ich auf die Idee, mod_proxy zu verwenden, um meinen Server auf einer neuen Subdomain abzubilden. Ich konnte wirklich nicht herausfinden, wie mod_proxy funktioniert, aber ich könnte mir vorstellen, dass ich weiß, dass sie den gleichen Effekt haben wie bei meinem ersten Ansatz?

Was wäre der beste Weg, um diese Art von Kombination, diese Art von klassischer Website und diese langwierigen XHR-Anfragen zu erstellen? Muss ich die Bereitstellung von Inhalten auf meinem Server selbst implementieren?

    
TheHippo 07.07.2009, 13:43
quelle

5 Antworten

3

Ich bin mir ziemlich sicher, dass die Verwendung von mod_proxy einen Arbeiter blockiert, während die Anfrage bearbeitet wird.

Wenn Sie zwei IPs verwenden können, gibt es eine ziemlich einfache Lösung. Nehmen wir an, IP A ist 1.1.1.1 und IP B ist 2.2.2.2. Sagen wir, Ihre Domain ist example.com.

So funktioniert es:

- Konfigurieren Sie Apache, um Port 80 zu hören, aber NUR auf IP A.

- Starten Sie Ihren anderen Server auf Port 80, aber nur auf IP B.

- Konfigurieren Sie die XHR-Anforderungen so, dass sie sich in einer Subdomäne Ihrer Domäne befinden, jedoch mit demselben Port. Die domainübergreifenden Einschränkungen verhindern sie also nicht. Ihre Website lautet also beispiel.com, und die XHR-Anforderungen gehen beispielsweise nach xhr.beispiel.com.

- Konfigurieren Sie Ihren DNS so, dass example.com in IP A aufgelöst wird und xhr.example.com in IP B aufgelöst wird.

- Du bist fertig.

Diese Lösung funktioniert, wenn Sie 2 Server haben und jeder seine IP hat, und es funktioniert auch, wenn Sie einen Server mit 2 IPs haben.

Wenn Sie zwei IPs nicht verwenden können, habe ich vielleicht eine andere Lösung, ich überprüfe, ob es für Ihren Fall anwendbar ist.

    
FWH 17.07.2009 06:07
quelle
3

Das ist ein schwieriges Problem. Selbst wenn Sie die Sicherheitsprobleme, die Ihnen begegnen, überstanden haben, müssen Sie am Ende eine TCP-Verbindung offenhalten, die für jeden Client geöffnet ist, der gerade eine Webseite anschaut. Sie können für jede Verbindung keinen Thread erstellen, und Sie können nicht alle Verbindungen eines einzelnen Threads auswählen. Nachdem ich das schon einmal gemacht habe, kann ich Ihnen sagen, dass es nicht einfach ist. Vielleicht möchten Sie sich in libevent umsehen, welches memcached verwendet ein ähnliches Ende.

Bis zu einem gewissen Punkt können Sie wahrscheinlich lange Timeouts einstellen und Apache eine große Anzahl an Arbeitern zur Verfügung stellen, von denen die meisten die meiste Zeit im Leerlauf sind. Die sorgfältige Auswahl und Konfiguration des Apache-Worker-Moduls wird dies, glaube ich, auf tausende von Benutzern ausdehnen. Irgendwann wird es aber nicht mehr skalieren.

Ich weiß nicht, wie Ihre Infrastruktur aussieht, aber wir haben Load-Balancing-Boxen in den Netzwerk-Racks namens F5s. Diese stellen eine einzige externe Domäne dar, leiten den Datenverkehr jedoch basierend auf ihren Antwortzeiten, Cookies in den Anforderungsheadern usw. an mehrere interne Server um. Sie können so konfiguriert werden, dass sie Anforderungen für einen bestimmten Pfad innerhalb der virtuellen Domäne an einen bestimmten Server senden. Somit könnten Sie example.com/xhr/foo-Anfragen einem bestimmten Server zuordnen, um diese Komet-Anfragen zu bearbeiten. Leider ist dies keine Softwarelösung, sondern eine recht teure Hardwarelösung.

Wie auch immer, Sie benötigen möglicherweise ein System zum Lastenausgleich (oder vielleicht haben Sie bereits eines), und vielleicht kann es so konfiguriert werden, dass es diese Situation besser behandelt als Apache.

Ich hatte vor Jahren ein Problem, bei dem Kunden ein Client-Server-System mit einem proprietären Binärprotokoll verwenden sollten, um auf unsere Server an Port 80 zugreifen zu können, da sie ständig Probleme mit Firewalls auf dem vom System verwendeten benutzerdefinierten Port hatten . Was ich brauchte, war ein Proxy, der auf Port 80 leben und den Datenverkehr entweder an Apache oder den App-Server leiten würde, abhängig von den ersten paar Bytes, die vom Client stammten. Ich suchte nach einer Lösung und fand nichts passendes. Ich überlegte mir, ob ich ein Apache-Modul, ein Plugin für DeleGate usw. schreiben sollte, aber schließlich mit einem eigenen Content-Sensing-Proxy-Dienst. Das ist meiner Meinung nach das Worst-Case-Szenario für das, was Sie versuchen.

    
Tim Sylvester 19.07.2009 22:26
quelle
0

Um die spezifische Frage zu mod-proxy zu beantworten: yes , können Sie mod_proxy einrichten, um Inhalte zu liefern, die von einem Server (oder Service) erzeugt werden, der nicht öffentlich ist (dh nur verfügbar ist) über eine interne Adresse oder localhost).

Ich habe das in einer Produktionsumgebung gemacht und es funktioniert sehr, sehr gut. Apache leitet einige Anfragen über AJP-Mitarbeiter und andere an Tomcat über einen Mod-Proxy an einen GIS-Anwendungsserver weiter. Andere haben darauf hingewiesen, dass die standortübergreifende Sicherheit die Arbeit an einer Subdomain unterbindet, aber es gibt keinen Grund, warum Sie keine Anforderungen an mydomain.com/application

übertragen können

Um über Ihr spezifisches Problem zu sprechen - ich denke wirklich, Sie sind dabei, das Problem als "langlebige Anfragen" zu betrachten - d. h. angenommen, wenn Sie eine dieser Anfragen machen, muss der gesamte Prozess gestoppt werden. Es scheint, als ob Sie versuchen, ein Problem mit der Anwendungsarchitektur durch Änderungen an der Systemarchitektur zu lösen. In der Tat, was Sie tun müssen, ist diese Hintergrundanforderungen genau so zu behandeln; und multi-thread es:

  • Der Client stellt die Anfrage an den Remote-Dienst " zur Ausführung der Aufgabe X mit den Daten A, B und C "
  • Ihr Dienst empfängt die Anforderung: Er übergibt sie an einen Scheduler, der ein eindeutiges Ticket / Token für die Anforderung ausgibt. Der Dienst gibt dieses Token dann an den Client " zurück, da sich Ihre Aufgabe in einer Warteschlange unter dem Token Z befindet "
  • Der Client hängt sich dann an dieses Token, zeigt ein "Lade / Bitte warten" -Feld an und richtet einen Timer ein, der z. B. für Argumente jede Sekunde
  • auslöst
  • Wenn der Timer ausgelöst wird, sendet der Client eine weitere Anfrage an den Remote-Dienst " haben Sie die Ergebnisse für meine Aufgabe, es ist Token Z "
  • Ihr Hintergrunddienst kann dann mit Ihrem Scheduler überprüfen und wird wahrscheinlich ein leeres Dokument " nein, noch nicht fertig " oder die Ergebnisse
  • zurückgeben
  • Wenn der Client die Ergebnisse zurückbekommt, kann er einfach den Timer löschen und anzeigen.

Solange Sie mit dem Threading einigermaßen vertraut sind (was Sie sein müssen, wenn Sie angegeben haben, dass Sie Ihren eigenen HTTP-Server schreiben möchten, sollte dies nicht zu komplex sein - über dem HTTP-Listener-Teil:

  • Scheduler-Objekt - Singleton-Objekt, das nur einen "First-in-First-out" -Stapel umschließt. Neue Aufgaben gehen an das Ende des Stapels, Jobs können von Anfang an abgerufen werden: Stellen Sie nur sicher, dass der Code zum Ausgeben eines Jobs threadsicher ist (weniger erhalten Sie zwei Arbeiten, die denselben Job vom Stapel ziehen).
  • Worker-Threads können ziemlich einfach sein - Zugriff auf den Scheduler erhalten, nach dem nächsten Job fragen: Wenn es einen gibt, dann schicke die Arbeit, sende die Ergebnisse, ansonsten schlaf nur für einen bestimmten Zeitraum, fange erneut an.

Auf diese Weise werden Sie Apache niemals länger als nötig blockieren, da Sie nur Anfragen für "do x" oder "gib mir Ergebnisse für x" stellen. Wahrscheinlich möchten Sie an einigen wenigen Punkten einige Sicherheitsfunktionen einrichten, z. B. Tasks, die fehlschlagen, und sicherstellen, dass auf der Clientseite eine Zeitüberschreitung auftritt, damit nicht unbegrenzt gewartet wird.

    
Ian 21.07.2009 09:00
quelle
0

Für Nummer 2: Sie können Cross-Domain-Beschränkungen umgehen, indem Sie JSONP verwenden.

    
null_radix 25.11.2009 14:58
quelle
0

Zwei Drei Alternativen:

  1. Verwenden Sie nginx . Das bedeutet, dass Sie 3 Server betreiben: nginx, Apache und Ihren eigenen Server.
  2. Führen Sie Ihren Server an einem eigenen Port aus.
  3. Verwenden Sie den Apache mod_proxy_http (als eigenen Vorschlag).
  

Ich habe bestätigt, dass mod_proxy_http (Apache 2.2.16) als Proxy für eine Comet-Anwendung (powered by Atmosphere 0.7.1) in GlassFish 3.1.1 läuft.

     

Meine Test-App mit vollständiger Quelle finden Sie hier: Ссылка

    
Hendy Irawan 25.04.2011 18:30
quelle

Tags und Links