wie man idempotente Webservice-Aufrufe implementiert

8

Ich entwickle eine wcf-basierte Lösung für eine Webservice-Schicht, die "gelegentlich verbundene" mobile Geräte verwenden. Der Dienst verwendet (zu diesem Zeitpunkt) aufgrund der zusätzlichen Komplexität keine Warteschlangen und verwendet stattdessen einen einfachen Anforderungs- / Antwortansatz.

Als mobiles Gerät ist es natürlich möglich, dass die Geräte während des Einfügens / Aktualisierens das Signal verlieren. Der Webservice selbst hat die Transaktion möglicherweise abgeschlossen, der Client erhält diese Nachricht jedoch nie. Aus diesem Grund wird die Anforderung erneut gesendet. Zu diesem Zeitpunkt muss der Server dies als doppelte Anforderung erkennen und dieselbe Antwort zurückgeben, die er bei der ersten Instanz versucht hat.

Daher versuche ich, die Dienste Idempotent zu machen. Um dies zu erreichen, implementiere ich DTO-Objekte für Anforderungsparameter, die aus der RequestID und den zum Abschließen des Aufrufs erforderlichen Parametern bestehen.

Meine Schwierigkeit besteht jedoch darin, eine Methode zur Überwachung der Anforderungs-IDs zu implementieren. Da der Dienst derzeit zustandslos ist, kann ich mir derzeit nur eine ServiceRequest-Tabelle in der Datenbank vorstellen, die die RequestID als primäre Tabelle verwendet. Wenn Sie dies abfragen, wird offensichtlich angezeigt, ob die Anforderung bereits bearbeitet wurde, da der Client dieselbe Anforderungs-ID sendet. Der Dienst muss jedoch auch wissen, welche Nachricht zurückgesendet werden soll. Im Falle einer Einfügung / Aktualisierung muss die betroffene aggregierte Stamm-ID auch irgendwo gespeichert werden, entweder direkt in der Anforderungstabelle oder in einer RequestToObjectLookup-Tabelle

Ich frage mich also, ob es eine bewährte Methode zur Implementierung gibt. Meine Gedanken sind eine ServiceRequest-Tabelle (dienstspezifisch), in der Anforderungs-IDs, zusätzliche Informationen und auch eine Suche nach der Ergebnisobjekt-ID (beim Speichern / Einfügen / Aktualisieren) gespeichert sind. Wenn also eine neue Anforderung eingeht, kann diese Tabelle zuerst konsultiert werden, bevor mit dem Rest der Anforderung fortgefahren wird, um das Speichern durchzuführen oder einfach das zuvor aktualisierte Objekt zurückzugeben (das beim ersten Anforderungsversuch ausgeführt wurde).

Ich denke auch (wie angegeben), dass ich nur die Root-Aggregat-ID behalten muss, auf die mit der Anfrage verwiesen wird, da ich nur Beziehungen verwenden sollte, um den Rest der Informationen zu erhalten.

Milambardo
quelle

Antworten:

2

Das Löschen kann idempotent gemacht werden, indem nur das Löschen basierend auf IDs zugelassen wird. Sie müssen eine Möglichkeit haben, damit IDs "in Gebrauch" bleiben und möglicherweise ablaufen.

Mit einem solchen Reservierungssystem; Das Erstellen eines Objekts kann erfolgen, indem zuerst eine ID reserviert und dann ein zweiter Aufruf ausgeführt wird, um das Objekt mit dieser ID zu erstellen (im Wesentlichen eine Aktualisierung des neuen leeren Objekts). Wenn eine ID angefordert wird, greift der Server nach einer freien ID und erstellt ein nicht initialisiertes Objekt mit dieser ID. Der zweite Aufruf zur Initialisierung enthält die zuvor zurückgegebene ID (plus alle erforderlichen Daten). Dies bedeutet, dass der zweite Aufruf im Wesentlichen ein Aktualisierungsaufruf ist, der an sich idem-potent ist (ein mehrmaliger Aufruf mit denselben Daten führt zu demselben Ergebnis).

Wenn die Reservierung mehrmals erfolgt, werden mehrere IDs zurückgegeben und das initialisierte Objekt bleibt erhalten. Diese nicht initialisierten Objekte können nach einiger Zeit automatisch von einem Rhoomba gereinigt werden.

Dadurch muss der Client sicherstellen, dass er für den Aufruf der Initialisierung verantwortlich ist, wenn er eine ID erhält. Wenn der Client während der Transaktion ausfällt, sollte er ein eigenes Protokoll für die Vorgänge führen, damit er beispielsweise weiß, dass er eine ID erhalten hat und mit der Initialisierung des Objekts beschäftigt war.

Es ist schwieriger, ein Update idempotent zu machen, aber ein Vergleichs- und Set-Vorgang (mit wahrem / falschem Ergebnis) hilft.

Ratschenfreak
quelle
Könnten Sie etwas mehr über das Reservierungssystem erklären? Meinen Sie damit, dass der Client zuerst eine ID vom Dienst anfordern muss, bevor er einen zweiten Aufruf tätigt, bei dem das Objekt die ID festgelegt hat?
Milambardo