2017-02-19 1 views
1

Teil der Anwendung, die ich schreibe, erfordert die Übertragung beliebig groß (für diese Frage werde ich 100-200 GB annehmen) Dateien vom Client zum Server. Wichtig ist, dass der Empfänger (Server) diese Datei nicht speichert - er liest nur den Strom und sendet ihn zum nächsten Punkt. Da ich nie eine ganze Datei benötige, sondern mehrere Übertragungen gleichzeitig erwarte, möchte ich die RAM-Nutzung minimieren und die Plattennutzung eliminieren. Ich möchte Dateien in Blöcken von 1 MB verarbeiten.Große Datei über reaktiven Strom senden

Momentan verwendet der Server Spring Boot und Akka.

Mein erster Versuch war es, gepufferte Datei-Input-Stream auf Client-Seite zu öffnen, lesen Sie es in Blöcken von 1 MB und senden Sie sie Nachrichten in separaten Thread. Es funktioniert, aber das Problem ist, dass der Client Nachrichten nacheinander sendet, ohne sich Gedanken darüber zu machen, ob der Server einen Puffer zum Speichern hat (es fehlt der Gegendruck).

Mein zweiter Gedanke war Akka-Ströme wie folgt zu verwenden:

How to use Reactive Streams for NIO binary processing?

mit Verwendung von ActorPublisher wie folgt aus:

akka-streams with akka-cluster

aber, wie hier angegeben:

http://doc.akka.io/docs/akka/2.4.16/scala/stream/stream-integrations.html#Implementing_Reactive_Streams_Publisher_or_Subscriber

"Warnung ActorPublisher und ActorSubscriber werden in zukünftigen Versionen von Akka wahrscheinlich nicht weiter unterstützt.

Warnung ActorPublisher und ActorSubscriber kann nicht mit entfernten Akteuren verwendet werden, da, wenn die Signale der reaktiven Streams Protokoll (zB Anfrage) die verloren sind der Strom Deadlock kann.“

es sieht nicht so gute Idee.

Ich möchte es nicht in einem Speicheranbieter (Dropbox, Google Drive, ...) speichern, weil ich Daten on-the-fly analysieren möchte.Ich habe Spring 5 und Akka an Bord, aber ich kann verwenden jede andere Software, die das lösen wird Raw-Sockel hat keinen Gegendruck und Torrents garantieren kein sequentielles/geordnetes Lese-Schreib-Verfahren (das ich brauche)

Hauptfrage ist: Wie große Datei von Client zu Server streamen, unter der Annahme, dass Server nicht in der Lage ist, Datei auf Festplatte oder in RAM gleichzeitig zu speichern?

Bonus Frage ist: Wie berechnet man "richtige" Größe von Chunk in solchen Transfer?

Ich habe seit Tagen nach der Antwort gesucht, und sieht aus, als ob ich nicht der einzige mit einem Problem wie diesem bin, aber es gibt keine Antworten oder Antworten wie "tue es nicht", ohne andere angemessene alternative Lösung zu zeigen.

+1

Es ist nicht wirklich klar, was genau dein Problem ist.Akka-Streams bieten alle Werkzeuge, die Sie benötigen - es gibt Stream-Wrapper um TCP-Sockets (natürlich mit Gegendruck), und es gibt 'GraphStage' (was der beabsichtigte Ersatz für ActorSubscriber und ActorPublisher ist), mit dem Sie die Verarbeitung implementieren können Logik, wenn keiner der Standard-Kombinatoren zu Ihnen passt. Sie müssen sie nur kombinieren. –

+0

Wären Sie so nett und zeigen Sie mir bitte ein minimales Beispiel für Remote Stream? – spam

+1

Sicher, hier ist es: https://gist.github.com/netvl/1245564b106c02691dd0808fe98d07eb. Es ist ziemlich dreckig (vor allem um die Server-Shutdown-Behandlung), aber es sollte die Grundidee vermitteln. Es verwendet rohe TCP-Sockets für die Kommunikation; Sie können auch dafür akka-http verwenden, da es Ihnen auch die TLS-Konfiguration erleichtert (obwohl es wahrscheinlich auch mit rohen TCP-Streams durchgeführt werden kann). TCP-Streams sind dokumentiert [hier] (http://doc.akka.io/docs/akka/2.4/scala/stream/stream-io.html#streaming-tcp), und akka-http ist dokumentiert [hier] (http : //doc.akka.io/docs/akka-http/current/scala.html). –

Antwort

3

Akka Stream bietet Funktionen speziell für diesen Anwendungsfall: streaming File IO. Aus der Dokumentation:

import akka.stream.scaladsl._ 
val file = Paths.get("example.csv") 

val foreach: Future[IOResult] = 
    FileIO.fromPath(file) 
     .to(Sink.ignore) 
     .run() 

In Bezug auf Ihre Bonusfrage für die "richtige Größe" von Chunk; Dies hängt stark von Ihren Hardware- und Softwarekonfigurationen ab. Am besten schreiben Sie einen Testclient und modulieren die Chunkgröße, bis Sie einen "Sweet Spot" für Ihren Server gefunden haben.