Hintergrund
Ich arbeite an einer Actix-Webanwendung mit Diesel über r2d2 und bin mir nicht sicher, wie ich am besten asynchrone Abfragen durchführen kann. Ich habe drei Optionen gefunden, die vernünftig erscheinen, bin mir aber nicht sicher, welche die beste ist.
Potentielle Lösungen
Schauspieler synchronisieren
Zum einen könnte ich das Actix-Beispiel verwenden , aber es ist ziemlich kompliziert und erfordert einiges an Boilerplate, um es zu bauen. Ich hoffe, es gibt eine vernünftigere Lösung.
Actix_web::web::block
Als weitere Option könnte ich actix_web::web::block
meine Abfragefunktionen in eine Zukunft einbinden, bin mir jedoch nicht sicher, welche Auswirkungen dies auf die Leistung hat.
Läuft die Abfrage dann im selben Tokio-System? Nach dem, was ich in der Quelle finden konnte, wird ein Thread im zugrunde liegenden Actix-Web-Threadpool erstellt . Ist das ein Problem?
Wenn ich den Code richtig lese, blockiert r2d2 seinen Thread beim Erwerb einer Verbindung, wodurch ein Teil des zentralen Actix-Web-Pools blockiert wird. Gleiches gilt für Datenbankabfragen. Dies würde dann das gesamte actix-web blockieren, wenn ich mehr Abfragen mache, als ich Threads in diesem Pool habe? Wenn ja, großes Problem.
Futures-cpupool
Schließlich ist futures-cpupool die sichere Wette, die möglicherweise unnötigen Overhead verursacht . Das Hauptproblem ist, dass dies bedeutet, meinem Projekt eine weitere Kiste hinzuzufügen, obwohl mir die Idee, dass mehrere CPU-Pools unnötig in meiner Anwendung herumschweben, nicht gefällt.
Da sowohl r2d2 als auch Diesel blockieren, gibt es hier überraschend viele knifflige Dinge.
Teilen Sie diesen cpupool vor allem nicht mit Benutzern, die nicht denselben r2d2-Pool verwenden (da alle erstellten Threads möglicherweise nur das Warten auf eine r2d2-Verbindung blockieren und den gesamten Pool sperren, wenn Arbeit vorhanden ist).
Zweitens (etwas offensichtlicher) sollten Sie daher nicht mehr r2d2-Verbindungen als Threads im Pool haben und umgekehrt, da der größere Ressourcen verschwenden würde (nicht verwendete Verbindungen / ständig blockierte Threads) (vielleicht ein weiterer Thread, vielleicht schneller Verbindungsübergabe durch den OS-Scheduler und nicht durch den cpupool-Scheduler.
Denken Sie schließlich daran, welche Datenbank Sie verwenden und welche Leistung Sie dort haben. Das Ausführen einer einzelnen Verbindung r2d2 und eines einzelnen Threads im Pool ist möglicherweise am besten in einer schreiblastigen SQLite-Anwendung (obwohl ich eine geeignete Datenbank für eine solche empfehlen würde).
Alte Antworten
Alte Lösungen, die funktionieren könnten
https://www.reddit.com/r/rust/comments/axy0hp/patterns_to_scale_actixweb_and_diesel/
Im Wesentlichen empfiehlt Futures-cpupool.
Was ist der beste Ansatz, um blockierende E / A in zukünftigen Daten zu kapseln?
Empfiehlt Futures-cpupool für allgemeine Fälle.
Alte Lösungen, die nicht funktionieren
https://www.reddit.com/r/rust/comments/9fe1ye/noob_here_can_we_talk_about_async_and_databases/
Eine wirklich schöne Lösung für eine alte Actix-Web-Version. Nach allem, was ich finden kann, haben Anfragen keinen CPU-Pool mehr.
futures-cpupool
die empfohlene Problemumgehung für die mangelndeasync
Unterstützung von Diesel ist.