3 Stimmen

Langlebige RESTful-Interaktionen

In meinem Team findet derzeit eine Diskussion statt, und ich wäre an anderen Meinungen interessiert. Nehmen wir an, wir haben einen RESTful-Webdienst, dessen Aufgabe es ist, Dokumente durch die Anwendung einer Reihe von Analysealgorithmen und -diensten zu annotieren. Die grundlegende Interaktion ist klar: Wir haben eine Ressource, die Dokumentensammlung; der Client POSTet ein neues Dokument an die Sammlung, erhält den URI des neuen Dokuments zurück und kann dann dieses Dokument GETEN docURI um das Dokument zurückzubekommen oder GET {docURI}/metadata um die allgemeinen Metadaten zu sehen, {docURI}/ne für benannte Entitäten, usw. Das Problem ist, dass einige der Analysen sehr lange dauern können. Angenommen, der Client ruft den Metadaten-URI ab, bevor die Analyse abgeschlossen ist, weil er in der Lage sein möchte, Teilergebnisse oder inkrementelle Ergebnisse auf der Benutzeroberfläche anzuzeigen. Die Wiederholung des GET in der Zukunft kann mehr Ergebnisse liefern.

Wir haben unter anderem folgende Lösungen diskutiert:

  • Offenhalten der HTTP-Verbindung bis alle Analysen abgeschlossen sind (was nicht skalierbar zu sein scheint)
  • mit content-length y accept-range Kopfzeilen, um inkrementelle Inhalte zu erhalten (aber wir wissen nicht im Voraus, wie lang der endgültige Inhalt sein wird)
  • die Bereitstellung von einen Atom-Feed für jede Ressource, so dass der Client Aktualisierungsereignisse abonniert Ereignisse abonniert, anstatt die Ressource einfach zu GETTEN der Ressource (scheint übermäßig kompliziert und möglicherweise ressourcenhungrig, wenn es viele aktive Dokumente gibt)
  • nur mit GET zurück was auch immer zu diesem Zeitpunkt verfügbar ist (aber es bleibt bleibt das Problem, dass der Client weiß, wann wir endlich fertig sind) [bearbeitet, um den Hinweis auf die Idempotenz nach den Kommentaren zu entfernen] .

Gibt es Meinungen oder Vorschläge für alternative Möglichkeiten zur Handhabung von langlebigen oder asynchronen Interaktionen in einer RESTful-Architektur?

Ian

0 Stimmen

Eigentlich gibt es zwei Lösungen. Einfache Lösung: verwenden GET Geben Sie die Metadaten zurück, die Sie zu diesem Zeitpunkt haben, und setzen Sie den Cache-Lebensdauer-Header auf Null, wenn diese Daten noch generiert werden. Komplexe Lösung: Push verwenden, um die Metadaten an die Clients zu senden, wenn sie generiert werden... imo chaotisch, pita, nicht wert es. Verwenden Sie GET .

3voto

aku Punkte 118808

Ich würde es folgendermaßen umsetzen:

1) Kunde fordert Metadaten an
2) Der Server gibt entweder die aktuellen Daten zurück (wenn sie bereits verfügbar sind) oder die NotReady-Markierung
3) Der Client fragt den Server, wann die Daten verfügbar sein werden (dieser Schritt kann mit dem vorherigen zusammengelegt werden)
4) Der Server gibt das Zeitintervall zurück (möglicherweise gibt es eine Heuristik für die Gesamtzahl der ausgeführten Aufträge usw.)
5) Der Kunde wartet eine bestimmte Zeit und geht zu Schritt 1 über

Auf diese Weise können Sie den Kunden so schnell wie möglich Daten zur Verfügung stellen. Sie können die Serverauslastung beeinflussen, indem Sie das in Schritt 4 angegebene Verzögerungsintervall anpassen.)

0 Stimmen

Vielen Dank für die Antwort. Dies würde die Daten für den Client alle auf einmal zur Verfügung haben, wenn es bereit ist, während ich möchte Daten inkrementell auf der Benutzeroberfläche zu präsentieren, wie es verfügbar wird.

0 Stimmen

Ian Dickinson, nicht notwendig. Sie können Teildaten zurückgeben, diese aber als unvollständig markieren und ein Abfrageintervall angeben.

0 Stimmen

@aku Vielleicht auch mit Exponential Backoff?

3voto

Jim Punkte 70896

Bereitstellung eines Atom-Feeds für jede Ressource, so dass der Client Aktualisierungsereignisse abonniert, anstatt die Ressource einfach nur zu GETEN (scheint übermäßig kompliziert und möglicherweise ressourcenintensiv zu sein, wenn es viele aktive Dokumente gibt)

Haben Sie bedacht SUP ?

Wenn die Abfrage eine Option ist, warum sollte man sich dann mit einem Feed beschäftigen? Warum lassen Sie die Clients nicht einfach die Ressource selbst abfragen?

Könnten Sie unnötige Umfragen einsparen, indem Sie eine geschätzte Zeit für den Abschluss der Analysen angeben?

0 Stimmen

Hallo Jim, danke für den Hinweis auf SUP - ich werde mich mal einlesen. Der Grund für die Erwägung eines Feeds anstelle einer reinen Abfrage ist, dass es für den Kunden einfacher wäre, die jüngsten Änderungen zu ermitteln und diese in der Benutzeroberfläche anders darzustellen.

0 Stimmen

Natürlich wissen Sie das besser als ich, aber ich hätte nicht gedacht, dass es für einen Kunden schwierig sein würde, die aktualisierten Felder zu identifizieren. Er kann doch sicher die empfangenen Daten mit den bereits vorhandenen vergleichen?

0 Stimmen

Ja, der Kunde kann den Vergleich selbst durchführen (die Ergebnisse sind RDF-Dokumente und keine Felder, aber der Punkt ist immer noch gültig). Ich habe mich noch nicht für die eine oder andere Seite entschieden, wollte aber nur einen Grund nennen, warum ein Feed einen Vorteil haben könnte. Ad-hoc-Mashups könnten ein weiterer Grund sein, obwohl ich davon noch nicht überzeugt bin!

2voto

Hank Gay Punkte 67607

Utilice HTTP 202 Akzeptiert .

Besuchen Sie auch RESTful Webdienste - Dort habe ich von den oben genannten Dingen erfahren.

0 Stimmen

Unter demselben Link scheint 206 Partial Content anwendbar zu sein.

0 Stimmen

@JeroenWyseur: Nein, "Die Anfrage MUSS ein Range-Header-Feld enthalten haben".

2voto

Matt Quail Punkte 6059
  • einfach die Idempotenz ignorieren und GET das zurückgeben lassen, was gerade verfügbar ist (aber es bleibt immer noch das Problem, dass der Client weiß, wann wir endlich fertig sind).

Bedeutet ein GET, das im Laufe der Zeit unterschiedliche Ergebnisse liefert, wirklich, dass es nicht idempotent ist? Die Spezifikation sagt:

Methoden können auch die Eigenschaft der "Idempotenz" haben, so dass (abgesehen von Fehler- oder Ablaufproblemen) die Nebenwirkungen von N > 0 identischen Anfragen die gleichen sind wie bei einer einzigen Anfrage

Das heißt, dass mehrere GET-Aufrufe unterschiedliche Ergebnisse liefern können, solange die Aufrufe selbst frei von Nebeneffekten sind.

In diesem Fall könnte Ihre REST-Methode vielleicht die bedingten GET- und Caching-Mechanismen verwenden, um anzuzeigen, wann sie fertig ist:

  • Während die Analyse im Gange ist, wird eine GET {docURI}/metadata Antwort haben könnte:
    • un Expires Kopfzeile auf einige Sekunden in der Zukunft eingestellt.
    • pas de ETag Kopfzeile.
  • Sobald die Analyse abgeschlossen ist, haben die Antworten für diese Ressource:
    • pas de Expires Kopfzeile.
    • un ETag . Spätere Anfragen bei der ETag sollte zurückkehren 304 Not Modified .

Beachten Sie auch die anderen Antwort-Header, die an der Zwischenspeicherung beteiligt sind, nicht nur Expires.

Dies "fühlt" sich an wie ein RESTful-Entwurf - man kann sich vorstellen, dass ein Webbrowser das Richtige tut, wenn er aufeinanderfolgende Anfragen an diese Ressource stellt.

0 Stimmen

Matt (und auch Jim) - Ja, du hast Recht mit der Idempotenz, danke für die Klarstellung. Ich werde meine Frage ändern, um diese potenzielle Quelle der Verwirrung zu beseitigen!

1voto

S.Lott Punkte 371691

"GET soll nur das zurückgeben, was gerade verfügbar ist", ist sehr sinnvoll. Nur sollte man bei Umfragen nicht ständig etwas zurückgeben, was sie schon wissen. Die Antworten werden bei jeder Abfrage länger.

Sie müssen Ihnen in der GET-Anfrage mitteilen, "was ich bisher gesehen habe". Dadurch erhalten Sie Idempotenz. Wenn sie nach Chunk 1 fragen, erhalten sie immer die gleiche Antwort. Sobald sie Chunk 1 gesehen haben, können sie nach Chunk 2 fragen.

Die Antwort wird nicht größer. Es werden mehr Teile verfügbar. Ein GET auf "Sammlungsebene" liefert die Größe der Antwort. Sie haben "Detail-Level" GETs für jedes verfügbare Teil.

Im Wesentlichen handelt es sich dabei um einen Algorithmus wie bei der TCP/IP-Bestätigung. Wenn ein Teil bestätigt wird, sendet man den nächsten Teil. Wenn es ein nächstes Stück gibt, senden Sie andernfalls eine 200 - nichts Neues zu berichten.

Das "Problem, dass der Kunde weiß, wann wir endlich fertig sind", ist unwägbar. Sie können es nicht wissen, und Sie können nicht vorhersagen, wie lange es dauern wird.

Sie wollen nicht, dass sie "busy waiting" machen - abfragen, ob Sie schon fertig sind - das ist eine ziemlich große Belastung für Ihren Server. Wenn sie ungeduldig sind. Sie können ihre Anfragen drosseln. Sie können ihnen eine Nachricht schicken, dass sie in x Sekunden zurückkommen sollen, wobei x immer größer wird.

Sie können sogar einen Unix-ähnlichen Scheduler-Algorithmus verwenden, bei dem die Punktzahl sinkt, wenn sie abfragen, und steigt, wenn sie X Sekunden lang nicht abfragen.

Die Alternative ist eine Art Warteschlange, in die Sie die Ergebnisse zurückschicken. Dazu müssten sie einen URI bereitstellen, den Sie POSTen können, um ihnen zu sagen, dass Sie fertig sind.

Oder sie verwenden Atom für eine leichtgewichtige Polling-Architektur. Während Atom komplex erscheint - und es beinhaltet immer noch Polling - geben Sie eine minimale Atom-Antwort ("noch nicht geändert"), bis Sie fertig sind, wenn Sie ("neue Ergebnisse") liefern, damit sie die real Schwergewicht bekommen. Dies ist für alles oder nichts, anstelle der inkrementellen Antwort Technik oben.

Sie können sich das GET auf "Sammlungsebene" auch als Ihren Atom-Status für den Prozess als Ganzes vorstellen.

1 Stimmen

Bezüglich "Sie wollen nicht ständig Dinge zurückgeben, die sie bereits kennen" - HTTP kümmert sich bereits mit 304-Antworten um dieses Problem. Bezüglich "was ich bisher gesehen habe" - HTTP kümmert sich bereits um dieses Problem mit If-None-Match. Sie erfinden das Rad neu.

0 Stimmen

Nicht neu erfinden. Das sind gute Wege, um die Ergebnisse zu kodieren. Sie müssen jedoch immer noch die Ergebnisse berechnen und bestimmen, was der Kunde wissen muss, damit Sie zwischen einer 200 und einer 304 entscheiden können.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X