2016-05-27 9 views
0

Ich habe einen kleinen Server, der viele Dateien verarbeiten muss. Die Dateien werden über eine PUT-Anfrage an den Server gesendet. Ich verwende das net/http-Paket für den Server. Ich weiß, dass für jede Anfrage eine Go-Routine geöffnet wird. Das Problem besteht jedoch darin, dass nach Beendigung einer Anfrage der verwendete Speicher des Handlers nicht freigegeben wird.Wie kann ich meinen Server (in Golang geschrieben) nicht aus dem Speicher gehen lassen?

Der Server (sollte) auf einem Raspery Pi 3 mit 1 GB Speicher laufen. Das Problem ist, dass nicht genügend Arbeitsspeicher zur Verfügung steht, wenn ich viele Dateien sende. An dieser Stelle kann ich nicht warten, bis der Garbage Collector den Speicher freigibt.

Diese beiden Themen sind über das Problem:

Why is the memory block not cleaned by the garbage collector?

Go 1.3 Garbage collector not releasing server memory back to system

Aber es gibt keine Lösung für mein Problem.

Jetzt ist die Frage: Gibt es eine Möglichkeit, einen HTTP-Handler als totaly bereit zu machen, dass der Garbage Collector den Speicher für die aufrufende Routine freigibt? Ich habe versucht, am Ende des Handlers eine return hinzuzufügen, aber das funktioniert nicht. Ich habe immer noch keine Erinnerung mehr.

+0

Überprüfen Sie auch dies: [Golang - Speicher kann nicht einmal durch bytes.Buffer] (http://stackoverflow.com/questions/37382600/golang-cannot-free-memory-once-ccupied-by-bytes- Puffer), gibt es ['debug.FreeOSMemory()'] (https://golang.org/pkg/runtime/debug/#FreeOSMemory). Sie können auch gleichzeitige Anfragen/Datei-Uploads/Downloads beschränken. – icza

+0

Um klar zu sein, bist du sicher, dass die Goroutine zurückgekehrt ist und der Handler das Problem ist?Ich denke, Sie können eine Goroutine verlieren, ähnlich wie wenn Sie ein Objekt in nicht-GC'd-Sprachen nicht freigeben. – evanmcdonnal

+0

Erhalten Sie einen Stack-Trace, während Sie unseren Speicher ausführen und sehen Sie, welche Gruoutines noch laufen. Es kann auch nicht schaden, die aktuelle Version von Go zu testen, wenn Sie Probleme mit ARM haben. – JimB

Antwort

0

Die kurze Antwort: Ich aktualisierte auf Version 1.6.2. Jetzt gibt es keine zusätzliche Speicherzuweisung für jede Routine.


Vielen Dank für Ihre Kommentare. Sie brachten mich auf den richtigen Weg zurück.

Der Speicherverbrauch stammt von einer Funktion, die für jede hochgeladene Datei einen MD5-Hash erstellt. Also 100MB Datei benötigt auch 100MB Speicher. Gehen Sie in Version 1.3 für jede Anfrage zugewiesen (gehen Sie Routine) neuen Speicher. Also nach max. 1 GB hochgeladenen Dateien die Raspbery hatte keinen Speicher mehr.

Woher kommen alle Goroutines?

Ein Kommentar war über die Logik, um eine Go-Routine für jede Anfrage zu öffnen. Diese Logik wurde nicht von mir implementiert, es ist in der Art und Weise geht die Anfragen.

Mehr über, dass Sie in diesem großen Open-Source-Buch über die Erstellung von Web-Anwendungen mit Go finden: Get into http package

Was passiert jetzt in Version 1.6.2?

Für jeden Upload reserviert der Server Speicher. Der Unterschied besteht nun darin, dass Go die Speichermenge reserviert, aber es auch für andere Routinen verwendet.

Beispiel für Version 1.6.2:

1st file 10 MB -> 10 MB RAM is used by the server 
2nd file 5 MB -> 10 MB RAM is used by the server 
3rd file 100 MB -> 100 MB RAM is used by the server 
4th file 50 MB -> 100 MB is used by the server 

Also, bis keine Datei größer als der Speicher ist der Server funktionieren soll.