2017-04-03 5 views
2

Betrachten Spring MVC Java-Web-Anwendung, die einige REST API bietet.Verhindern REST-Clients gleichzeitige Ausführung derselben Methoden mit denselben Argumenten

Lassen Sie uns sagen, dass es viele Methoden hat, einer von ihnen ist DELETE /api/foo/{id}, die offensichtlich mit bestimmten idfoo Entität aus der DB gelöscht.

Das Problem ist, dass aufgrund der großen Daten in der DB, dieser Vorgang nicht sofort, also, wenn Client versucht gleichzeitig mehrfach führen Operationen an derselben Einheit löschen, sagt

DELETE /api/foo/123 x N-mal (versehentlich in Client-Software natürlich),

es verursacht einige unangenehme Nebenwirkungen in der DB (wissen Sie, wenn Sie versuchen, gleiche Einheit in mehreren Transaktionen zu löschen, das ist nicht allgemein nett).

Meine Frage ist: Was ist die beste Praxis in Spring MVC, um solche Situationen zu verhindern?

Ich kann sicherlich die Synchronisation auf Foo ID in jeder solchen Update-Methode einführen (PUT/DELETE). Ich muss es für alle Entitäten und alle PUT/DELETE API-Methoden tun, die ich wirklich nicht machen möchte. Ich nehme an, es sollte eine elegante und schöne Lösung sein, wie man eine solche Art von Synchronisation auf dem Interceptor/Servlet-Level durchführt, d. H. Nicht auf dem Controller-Level.

Ich kann auch spezifische Interceptor erstellen und dort warten auf doppelte Anfragen (Anfragen mit derselben URL und Parameter). Aber wieder klingt es nicht als eine elegante Lösung (bis ich sichergestellt werde, dass es nicht möglich ist, in Spring MVC irgendwie in Schönheit Weise zu konfigurieren).

+1

Prinzipiell ist der Transaktionsmechanismus für diesen Zweck ausgelegt. Welche weiteren Anforderungen haben Sie an die Transaktion Rollback als ** unangenehme Nebenwirkungen in der DB **? –

+0

Ja, das Problem ist, dass verschiedene DBs für solche Ereignisse ein anderes Verhalten haben. In meinem Fall hatte ich wegen der komplexen Replikationsstruktur eine Art Blockierung. Ich möchte generell keine solchen Ausnahmen von der DB einfangen und erhalten, ich möchte ihr Erscheinen verhindern. – Andremoniy

+0

Ich bin richtig oder falsch. Ich weiß nicht, wie wir wissen, können wir eine Sache tun, nur überprüfen, ob die Daten in db verfügbar sind oder nicht wie getFooById (id); Wenn Sie die Daten erhalten, können Sie dieselben Daten löschen, andernfalls können Sie die Ausnahme auslösen, dass keine Daten vorhanden sind. –

Antwort

1

Dies ist ein Problem der Nebenläufigkeit, die durch die Verwendung der entsprechenden Transaktion und Sperrstufe behandelt werden soll. Leider gibt es hier keine einheitliche Größe und abhängig von Ihren tatsächlichen Anforderungen könnten Sie optimistisches oder pessimistisches Sperren sowie eine der möglichen Transaktionsebenen (von keiner Transaktion bis zu serialisierbaren Transaktionen) implementieren müssen.

Im Allgemeinen ist die Behandlung solcher Fragen auf der Web-Ebene eine schlechte Idee, weil Sie mit Fragen enden, wie Sie auf Anfrage einige Daten löschen möchten, die ein anderer zur gleichen Zeit anzeigt? In SpringMVC werden häufig transaktionale Methoden in der Serviceschicht verwendet. Zusätzlich sollten Sie ein optimistisches oder pessimistisches Sperrsystem in der Persistenzschicht deklarieren.

Optimistische Layer geben normalerweise einen höheren Durchsatz, auf Kosten von einigen Transaktionen, die in Exceptions enden. In diesem Fall sollten die aktuellen Best Practices das Problem nun dem Benutzer melden, der ihn auffordert, seine Anfrage erneut zu senden.

+0

Das Problem, dass dieser Ansatz meine aktuellen Probleme nicht abdeckt.Mehrere Mehrfachanfragen von DELETE der gleichen Raw in schwer beladenen DB verursacht Art der Blockierung, so dass alle diese mehrere Anfragen mit 504 Timeout-Fehler fehlschlagen. Natürlich werden alle Löschmethoden selbst auf Transaktionsebene durchgeführt. Aber es deckt nicht den Fall ab, wenn sich die DB selbst in einer unpassenden Weise verhält. – Andremoniy

+0

504 Timeout-Fehler bei Löschanforderungen ist in der Regel ein Symptom, das nicht in der Lage ist, eine (pessimistische) Sperre zu erhalten. Aber dies ist der schwierige Teil der Optimierung der Datenbankzugriffe und hängt stark von der Datenbank selbst und den wichtigsten Anwendungsfällen ab. Es tut mir leid, aber ich fürchte, ich kann nicht viel mehr sagen. Vielleicht könnten Sie versuchen, pessimistische Sperren durch optimistische zu ersetzen, um 504 Timeout-Fehler durch Nachrichten wie * System war ausgelastet und konnte Ihre Anfrage nicht vervollständigen, bitte versuchen Sie es erneut. * –

+0

Das ist nicht geeignet. Wie ich in meiner Frage geschrieben habe, wird der direkte Weg die Synchronisation der Ids bestimmter Entitäten sein. Dies wird einfach verhindern, dass DB gesperrt wird, so dass es keine Probleme mit Timeout-Ausnahmen gibt - sequentiell ausgeführte DELETE-Methoden werden schnell OK zurückgeben, da das Löschen einer abwesenden Entität in meiner API rechtmäßig ist. Meine Frage war: Ist es möglich oder nicht, benutze vorhandene Fähigkeiten von Spring MVC Framework, um den gleichen Trick auf höherer Ebene zu machen. – Andremoniy

Verwandte Themen