Hallo !
Wir erstellen einen langen Bericht im PDF-Format, der etwa 3 Minuten dauert, und stellen ihn über Plumber bereit.
Die HTTP-Verbindung wird nach etwa 1 Minute 40 Sekunden (100 Sekunden) geschlossen.
Wir haben also die logische Fehlermeldung, weil Klempner versuchen, Daten an eine geschlossene Verbindung zu senden:
ERROR: [on_request_read] connection reset by peer
Ich denke, es kann mit # 12 zusammenhängen und übrigens https://github.com/rstudio/httpuv/issues/49
Gibt es eine Möglichkeit, das in Plumber zu beheben? Kann durch manuelles Senden in Klempner so etwas sein:
Keep-Alive: timeout=300
Connection: Keep-Alive
Aber auf jeden Fall wollen wir #12 vermeiden
Mit freundlichen Grüßen,
Emmanuel
Leider bin ich mit den Interna von httpuv nicht vertraut genug, um vernünftig darüber sprechen zu können, warum dies passieren könnte.
Um jedoch einen Schritt zurückzutreten, besteht das übliche Muster bei der Ausführung dieser Art langlebiger Aufgaben in anderen Systemen darin, sofort auf die eingehende Anfrage zu reagieren und die Arbeit dann asynchron zu starten. Der Client erhält eine ID als Antwort auf die ursprüngliche Anfrage und kann diese dann abfragen, um herauszufinden, wann sie abgeschlossen ist.
Leider ist R Single-Threaded, daher ist dies etwas komplizierter. Aber wenn Sie ausreichend motiviert wären, könnten Sie sich fork
den R-Prozess ansehen (siehe Parallel- oder Multicore-Pakete) und dann den Bericht in einem Fork des Prozesses generieren, wobei der übergeordnete Prozess verfügbar bleibt, um auf API-Anforderungen zu antworten (wie Kunden, die abfragen, ob ihr Bericht erstellt wurde).
Hallo,
Hier haben wir unseren R-Code optimiert, sodass dies eigentlich kein Problem darstellt. Aber das Problem kann in anderen Fällen wieder auftreten. Wenn ich eine Lösung gefunden habe, werde ich zurückkommen und sie hier veröffentlichen.
Nur für den Fall, dass jemand dieses Problem relevant findet: fork
ing funktioniert recht gut und ist mit dem Paket parallel
einfach zu erledigen.
parallel <- function() {
# Long running calculation here
print("Sleeping...")
Sys.sleep(10)
print("Finished.")
return(Sys.time())
}
#* <strong i="8">@get</strong> /parallel
parallelTest <- function() {
parallel::mcparallel(parallel())
return(TRUE)
}
Hilfreichster Kommentar
Nur für den Fall, dass jemand dieses Problem relevant findet:
fork
ing funktioniert recht gut und ist mit dem Paketparallel
einfach zu erledigen.