2016-06-10 5 views
0

Mein RESTful-Dienst in Java geschrieben verbraucht eine große Anzahl kleiner Dateien (etwa 300 Byte), schreibt sie auf die Festplatte, fügt sie als BLOB in eine Oracle-Datenbank ein und löscht sie schließlich. Um zu verhindern, dass Dateien aufgrund eines Netzwerkausfalls oder etwas fehlen, muss ich sie auf den Datenträger schreiben, um sie in großen Mengen einzufügen, wenn sich mehr als eine Datei auf dem Datenträger befindet.RESTful-Dienst in Java/Tomcat Multithread (?) Probleme

Mein Problem ist: Wenn ich sequentielle POST-Anfragen über cURL und Windows-Batch ausführen, funktioniert alles wie erwartet für eine unbegrenzte Zeit, etwa 3-5 Dateien pro Sekunde.

Wenn ich einen anderen Stapel erstellen, um den Server/Dienst zu benchmarken, werden einige Dateien doppelt in die Datenbank eingefügt.

Es funktioniert wie folgt: POST request (octet-stream) -> RESTful service [ -> checks for valid file -> writes to disk -> directoryscanner reads all *.XYZ files in directory into String-array -> insert into DB -> if insert OK: delete file].

Ich glaube aufgrund der multithreaded Natur meines Dienstes, wenn in einem gewissen Zeitraum (zB: wenige Millisekunden) zwei Anträge bearbeitet werden, wobei der Einsatz Verfahren beiden Threads die gleiche Datei einfügen in der DB löscht ein Thread sie, der erste Thread kann die Datei nicht mehr finden (weil Thread2 sie bereits gelöscht hat), etc.

Meine Frage ist: Wie kann ich das verhindern? Ich fing an, alle Variablen usw. als privat zu erstellen, damit der andere Thread nicht auf sie zugreifen kann (ich glaube, so funktioniert es). Aber in der sehr begrenzten Zeitspanne, in der beide (oder alle) Threads gleichzeitig existieren, "stiehlt" thread2 die Datei von thread1, aber AFTER thread1 hat sie bereits eingefügt.

Wie Sie wahrscheinlich ableiten können, bin ich kein professioneller Java-Programmierer, also können Sie mir vielleicht in die richtige Richtung zeigen. Lassen Sie es mich wissen, wenn Sie Code-Schnipsel oder ähnliches benötigen.


EDIT
den Workflow zu klären: Der Dienst wird zu einem gewissen URI /service/{ID}/{file} einen Oktett-Datenstrom, der über HTTP POST, wobei ID eine ganze Zahl ist und die Datei ist die Erweiterung der Datei in der Anforderung .
Der Dienst schreibt die Datei auf die Festplatte und fügt sie dann in den DB (BLOB) ein.
Manchmal kann die Datei eine zip-komprimierte Datei sein, die ich extrahieren muss, dann die extrahierten Dateien in die DB einfügen.
Im Falle eines Netzwerkausfalls kann ich keine Verbindung zur DB herstellen. Deshalb schreibe ich jede einzelne Datei auf einen Datenträger, lese sie in ein String-Array und füge sie in die DB ein, sobald die Verbindung wieder hergestellt ist.

Ich denke, das Problem ist, dass zwei Threads schreiben zwei Dateien gleichzeitig, beide Threads scannen die Datei in ihre eigenen String-Array, laden beide Threads die Dateien. (< - Das ist, wo ich denke, ich könnte falsch liegen). Ich kann dieses Problem reproduzieren und sogar bis zu 3 oder 4 oder 5 cURL-Stapel, dann 3 oder 4 oder 5 Dateien sind Duplikate.

EDIT2 (log Beispiel)

10-Jun-2016 09: 56: 14.400 severe [pool-275-thread-1] ServiceResource.doSendData Array: file1.tst - [Ljava .lang.String; @ 3107ce05

10-Jun-2016 09: 56: 14.400 SCHWER [pool-274-thread-1] ServiceResource.doSendData array: file1.tst - [Ljava.lang.String; @ 6996e2db

+1

Klingt wie Sie Datenbankeinschränkungen benötigen, so dass die Datenbank sicherstellt, dass Sie keine Duplikate (und vielleicht Transaktionen?) Einfügen können. Aber ich verstehe nicht, wie diese Dateien Duplikate sein können. Was sind sie und wie kann es sein, dass 2 Anfragen auf die gleiche Datei verweisen? Kannst du erklären, wie & was auf Festplatte geschrieben wird und was der Verzeichnis-Scanner-Teil benötigt (du hast gerade diese Dateien geschrieben, warum scannt man sie?) – zapl

+0

Synchronisiere den Methodenaufruf, dann kann er nicht zweimal ausgeführt werden es hat seine Arbeit beendet öffentliche synchronisierte void yourmethod() { // do sachen } – David

+1

@zapl oh tut mir leid, ich habe vergessen zu erwähnen, dass ich Einschränkungen in der Tabelle nicht verwenden kann. Manchmal muss ich den Namen in der DB duplizieren, um einige Dateien zu reparieren. Was "wie & was auf die Festplatte geschrieben wird ...", versuche ich in meiner Frage zu klären. – Lenniey

Antwort

0

Nun ging ich mit recording der Directoryscanner Teil. Jetzt erhalte ich die Datei, entpacke sie, wenn es sich um eine Zip-Datei handelt, hole die Dateiheader, füge sie in die Datenbank ein und lösche sie schließlich, wenn sie korrekt übertragen werden. Wenn keine Verbindung zur DB besteht, werden die Dateien auf den Datenträger geschrieben und sobald die DB wieder online ist, in die DB eingefügt.
Danke für die Eingabe, ich habe wirklich einiges hier gelernt :)