2016-07-22 5 views
0

Entschuldigung: Ich habe keinen einfachen Testfall, der dieses Problem reproduziert, da es sehr zeitweise passiert. Ich wäre jedoch sehr dankbar für einige Hilfe, wie Sie überhaupt mit der Diagnose beginnen können.Jersey-Antwort mit falschen Daten

Ich habe einen Jersey-Server läuft auf Tomcat.

Wenn der Client eine Anforderung sendet, wird manchmal eine Antwort von einer völlig anderen Anforderung mit der richtigen Antwort gemischt.

Die "richtige" Anfrage kann von jeder Art sein, aber die "schlechte" Antwort, die eingemischt wird, kommt immer von einem SSE-Stream (EventOutput) oder einer AsyncResponse.

Zum Beispiel ist dies die Ausgabe von einem Client durch eine normale Anforderung empfangen:

event: message_sent 
id: 1 
data: {"value":"hello world"} 

{"event-id":"13"}event: message_sent 
id: 2 
data: {"value":"hello world"} 

Die echte Antwort {"event-id":"13"} vorhanden ist ... aber umgibt, dass es zwei fehlerhafte SSE Ereignisse.

Die Methode, um diese Anforderung zu verarbeiten gibt einfach:

return Response.created(uri).entity(eventId).build(); 

So verstehe ich nicht an, die der unerwünschte Datenpunkt (gesendet wird, es sei denn Response.created() wird ein Antwortobjekt zurückkehrt, die bereits für eine SSE verwendet worden waren, Strom).

Die Serverprotokolle zeigen immer die korrekte Ausgabe an. Wir wissen jedoch, dass der Client keinen Fehler hat, da wir einen Paket-Sniffer verwendet haben, um zu bestätigen, dass die Antworten fehlerhaft sind.

Hinweise:

  • Für SSE-Streams, überprüfe ich immer, dass die EventOutput nicht geschlossen ist, bevor
  • auf sie zu schreiben Wenn zu AsyncResponse Objekte zu schreiben, überprüfe ich isSuspended() immer an erster Stelle (und sie sind mit der injizierte @Suspended Annotation)

Noch einmal, alle Hinweise oder Hinweise wären so eine große Hilfe. Mir sind die Ideen ausgegangen!

Antwort

0

Nach viel Forschung, habe ich festgestellt, dass mein Problem (natürlich) ein Benutzerfehler sein muss, obwohl ich den Fehler nicht reproduzieren konnte, wenn ich den Apache-Proxy aus der Gleichung entfernte. In meinem Fall musste ich vorsichtiger sein, wenn ich EventOutputs als geschlossen betrachte - da man nur feststellen kann, ob die Verbindung offen ist, wenn man versucht, darauf zu schreiben. Im Allgemeinen sind meine Ergebnisse jedoch:

Ein Fehler dieser Art tritt auf, wenn Sie Verweise auf Antwortobjekte herum behalten und dann zu ihnen schreiben, nachdem Tomcat sie für eine andere Anforderung wiederverwendet hat. Dies könnte eine Liste von z.B. AsyncResponse- oder EventOutput-Objekte, die Sie behalten müssen, um zu einem späteren Zeitpunkt fortzufahren oder zu schreiben.

Wenn es jedoch ein Fehler ist, der schwierig aufzuspüren und Sie brauchen eine Lösung, gibt es eine Tomcat-Einstellung, die für die Weiterverwendung dieser Objekte auf Kosten der Leistung deaktiviert werden kann, wie es hier sagt: https://tomcat.apache.org/tomcat-8.0-doc/security-howto.html

Die Einstellung org.apache.catalina.connector.RECYCLE_FACADES Systemeigenschaft auf True bewirkt, dass für jede Anforderung ein neues Fassadenobjekt erstellt wird. Dies verringert die Wahrscheinlichkeit eines Fehlers in einer Anwendung, die Daten von einer Anfrage an eine andere aussetzt.

(nicht durch den Namen verwechselt werden; RECYCLE_FACADES=true bedeutet, dass die Fassaden werden nicht wiederverwendet werden, und werden neue geschaffen erhalten, wie sie benötigt werden).

Es gibt examples von Anwendung Bugs wie dies nur manifestieren, wenn hinter einem Apache-Proxy, so wenn der Fehler verschwindet, wenn Sie direkt auf Tomcat zugreifen bedeutet es nicht unbedingt, dass Apache ist schuld.

Wie ich sage, ist es unwahrscheinlich, dass dies durch einen Fehler in Tomcat, Apache oder mod_proxy_ajp verursacht wird ... aber wenn Sie ein Pech haben, können Sie versuchen, einen anderen Connector (zum Beispiel mod_jk) zu verwenden.