Ich habe folgendes Szenario:
- Ein Benutzer stellt eine GET- Anfrage an
/projects/1
und empfängt einen ETag . - Der Benutzer stellt ab Schritt 1 eine PUT- Anfrage
/projects/1
mit dem ETag. - Der Benutzer stellt
/projects/1
ab Schritt 1 eine weitere PUT-Anfrage mit dem ETag.
Normalerweise erhält die zweite PUT-Anforderung eine 412-Antwort, da das ETag jetzt veraltet ist. Die erste PUT-Anforderung hat die Ressource geändert, sodass das ETag nicht mehr übereinstimmt.
Was aber, wenn die beiden PUT-Anforderungen gleichzeitig (oder genau nacheinander) gesendet werden? Die erste PUT-Anforderung hat keine Zeit, die Ressource zu verarbeiten und zu aktualisieren, bevor PUT # 2 eintrifft, was dazu führt, dass PUT # 2 PUT # 1 überschreibt. Der springende Punkt beim optimistischen Sperren ist, dass dies nicht geschieht ...
rest
language-agnostic
concurrency
http
maximiert
quelle
quelle
Antworten:
Der ETag-Mechanismus gibt nur das Kommunikationsprotokoll für optimistisches Sperren an. Es liegt in der Verantwortung des Anwendungsdienstes, den Mechanismus zum Erkennen gleichzeitiger Aktualisierungen zu implementieren, um die optimistische Sperre zu erzwingen.
In einer typischen Anwendung, die eine Datenbank verwendet, öffnen Sie normalerweise eine Transaktion, wenn Sie eine PUT-Anforderung verarbeiten. Normalerweise lesen Sie den vorhandenen Status der Datenbank in dieser Transaktion (um eine Lesesperre zu erhalten), überprüfen Ihre Etag-Gültigkeit und überschreiben die Daten (auf eine Weise, die einen Schreibkonflikt verursacht, wenn eine inkompatible gleichzeitige Transaktion vorliegt). dann begehen. Wenn Sie die Transaktion korrekt eingerichtet haben, sollte eines der Commits fehlschlagen, da beide versuchen, dieselben Daten gleichzeitig zu aktualisieren. Sie können diesen Transaktionsfehler dann verwenden, um entweder 412 zurückzugeben oder die Anforderung erneut zu versuchen, wenn dies für die Anwendung sinnvoll ist.
quelle
AND ETag = ...
inUPDATE
dieWHERE
Klausel Ihrer Anweisung aufnehmen und anschließend die Anzahl der aktualisierten Zeilen überprüfen. (Oder durch Verwendung einer strengeren Transaktionsisolationsstufe, aber das empfehle ich nicht wirklich.)Sie müssen das folgende Paar atomar ausführen:
Andere nennen dies eine Transaktion - aber im Grunde verhindert die atomare Ausführung dieser beiden Operationen, dass die eine die andere versehentlich überschreibt. Ohne dies haben Sie eine Rennbedingung, wie Sie bemerken.
Dies wird immer noch als optimistisches Sperren angesehen, wenn Sie das Gesamtbild betrachten: Die Ressource selbst wird nicht durch das anfängliche Lesen (GET) eines Benutzers oder eines Benutzers gesperrt, der die Daten betrachtet, unabhängig davon, ob sie aktualisiert werden sollen oder nicht.
Ein gewisses atomares Verhalten ist erforderlich, dies geschieht jedoch innerhalb einer einzelnen Anforderung (PUT), anstatt zu versuchen, eine Sperre für mehrere Netzwerkinteraktionen aufrechtzuerhalten. Dies ist eine optimistische Sperrung: Das Objekt ist vom GET nicht gesperrt, kann jedoch vom PUT sicher aktualisiert werden.
Es gibt auch viele Möglichkeiten, um eine atomare Ausführung dieser beiden Operationen zu erreichen. Das Sperren der Ressource ist nicht die einzige Option. Beispielsweise kann eine einfache Thread- oder Objektsperre ausreichen und hängt von der Architektur und dem Ausführungskontext Ihrer Anwendung ab.
quelle
Es liegt beim Anwendungsentwickler, das E-Tag tatsächlich zu überprüfen und diese Logik bereitzustellen. Es ist keine Zauberei, die der Webserver für Sie erledigt, da er nur weiß, wie
E-Tag
Header für statische Inhalte berechnet werden. Nehmen wir also Ihr Szenario oben und teilen Sie auf, wie die Interaktion stattfinden soll.Der Server empfängt die Anforderung, ermittelt das E-Tag für diese Version des Datensatzes und gibt dieses mit dem tatsächlichen Inhalt zurück.
Da der Client jetzt den E-Tag-Wert hat, kann er diesen in die
PUT
Anforderung aufnehmen:Zu diesem Zeitpunkt muss Ihre Anwendung Folgendes tun:
Senden Sie die Erfolgsantwort.
Wenn eine andere Anforderung eingeht und versucht, eine
PUT
ähnliche Anforderung wie oben auszuführen, müssen Sie die Fehlermeldung bereitstellen, wenn Ihr Servercode sie zum zweiten Mal auswertet.Senden Sie bei einem Fehler die Fehlerantwort.
Dies ist Code, den Sie tatsächlich schreiben müssen. Das E-Tag kann tatsächlich ein beliebiger Text sein (innerhalb der in der HTTP-Spezifikation definierten Grenzen). Es muss keine Zahl sein. Es kann auch ein Hashwert sein.
quelle
Als Ergänzung zu den anderen Antworten werde ich eines der besten Zitate in der ZeroMQ-Dokumentation veröffentlichen , das das zugrunde liegende Problem genau beschreibt:
quelle