nimble install mummy
API -Referenz
Mummy ist ein Multi-Thread-HTTP 1.1- und WebSocket-Server, der vollständig in NIM geschrieben wurde.
Eine Rückkehr zu den alten Wegen der Fäden.
Mummy wurde speziell geschrieben, um die Leistung Ihrer Serverhardware zu maximieren, ohne das Programmierer -Glücksfall zu beeinträchtigen.
{.async.} . Mama benötigt --threads:on und --mm:orc oder --mm:arc .
Der mumische Name bezieht sich auf historische Ägypten -Sachen.
Mummy arbeitet mit diesem Basismodell: Behandeln Sie alle Socket -IO in einem Thread und senden Sie eingehende HTTP -Anforderungen und Websocket -Ereignisse in einen Pool von Worker -Threads. Ihre HTTP -Handler müssen wahrscheinlich überhaupt nicht über Threads nachdenken.
Dieses Modell hat viele große Vorteile und ist bereit, die Fortsetzung der Server -Kernzählerhöhungen zu nutzen (AMD hat gerade eine 96 Core 192 Thread Server -CPU angekündigt!).
Keine Notwendigkeit {.async.} , Future[] zu verwenden, await usw. und befassen Sie sich mit Funktionen mit Farben.
Behalten Sie den gleichen hervorragenden Durchsatz von Multiplexed Non -Blocking Socket IO bei.
Keine Sorge, dass eine Blockierung oder ein teurer Anruf Ihren gesamten Server zum Stillstand bringen.
Async blockiert über überraschende Dinge wie DNS -Auflösung und Dateilesen, die alle Anfragen zur Handhabung des Antrags blockieren.
Einfacher zu schreiben Anforderungshandler. Das Blockieren des Fadens ist total in Ordnung! Müssen Sie eine Postgres abfragen? Kein Problem, warten Sie einfach auf die Ergebnisse.
Das Schreiben von einfacherem Code im Vergleich zu theoretisch schnellem, aber möglicherweise verwickelten und fehlerhaften Code hat einen wesentlichen Vorteil.
Viel einfacheres Debuggen. Async Stapel -Spuren sind riesig und verwirrend.
Einfacherer Fehlerhandling, try except wie Sie es normalerweise tun. Unzereinte Ausnahmen in Mumie -Handlern bringen auch nicht Ihren gesamten Server ab.
Mummy behandelt das Faden und den Versand, sodass Ihre Handler möglicherweise überhaupt nicht über Threads nachdenken müssen.
Nutzt mehrere Kerne und die erstaunliche Arbeit des NIM -Teams auf ARC / ORC und NIM 2.0.
Websockets sind wunderbar und können erhebliche Vorteile gegenüber traditionelleren API -Paradigmen wie Ruhe und verschiedenen Aromen von RPC haben.
Leider geben die meisten HTTP -Server vor, dass WebSockets nicht existieren.
Dies bedeutet, dass Entwickler Unterstützung durch zusätzliche Abhängigkeiten, Entführungen von Verbindungen usw. einhacken müssen, und alles summiert sich selten zu etwas wirklich Großem.
Ich sehe keinen Grund, warum WebSockets nicht außergewöhnlich gut funktionieren sollten, um Entwicklern viel Unsicherheit zu sparen und zu untersuchen, welche Möglichkeiten der möglichen Möglichkeiten für die Unterstützung von WebSocket auf einem HTTP -Server "am besten" sind.
Alles kommt mit Kompromisse. Mama konzentriert sich darauf, ein außergewöhnlicher API -Server zu sein. Denken Sie an, Ruh, JSON, RPC, WebSockets, HTML aus Vorlagen usw.
Die Eigenschaft, die diese gemeinsam haben, ist, dass sie alle relativ Speicherlicht sind. Die meisten Dinge sind großartig, aber wenn Sie ausdrücklich viele sehr große Dateien bedienen oder große Dateien -Uploads erwarten, ist Mumie wahrscheinlich nicht die beste Wahl, es sei denn, Ihr Server verfügt über den RAM, um die großen Dateien zu verarbeiten.
Warum ist Mama nicht gut für große Dateien? Dies liegt daran, dass Mummy, die vollständig empfangene In-Memory-Anfragen an Arbeiter-Threads gesendet und in Memory-Antworten sendet. Dies ist großartig für alles außer sehr großen Dateien.
import mummy, mummy / routers
proc indexHandler (request: Request ) =
var headers: HttpHeaders
headers[ " Content-Type " ] = " text/plain "
request. respond ( 200 , headers, " Hello, World! " )
var router: Router
router. get ( " / " , indexHandler)
let server = newServer (router)
echo " Serving on http://localhost:8080 "
server. serve ( Port ( 8080 )) nim c --threads:on --mm:orc -r examples/basic_router.nim
import mummy, mummy / routers
proc indexHandler (request: Request ) =
var headers: HttpHeaders
headers[ " Content-Type " ] = " text/html "
request. respond ( 200 , headers, """
<script>
var ws = new WebSocket("ws://localhost:8080/ws");
ws.onmessage = function (event) {
document.body.innerHTML = event.data;
};
</script>
""" )
proc upgradeHandler (request: Request ) =
let websocket = request. upgradeToWebSocket ()
websocket. send ( " Hello world from WebSocket! " )
proc websocketHandler (
websocket: WebSocket ,
event: WebSocketEvent ,
message: Message
) =
case event:
of OpenEvent :
discard
of MessageEvent :
echo message.kind, " : " , message.data
of ErrorEvent :
discard
of CloseEvent :
discard
var router: Router
router. get ( " / " , indexHandler)
router. get ( " /ws " , upgradeHandler)
let server = newServer (router, websocketHandler)
echo " Serving on http://localhost:8080 "
server. serve ( Port ( 8080 ))In den Beispielen/ den Ordner finden Sie weitere Beispielcode, einschließlich eines Beispiel -WebSocket -Chat -Servers.
nim c --threads:on --mm:orc -r examples/basic_websockets.nim
Benchmarking -HTTP -Server sind ein bisschen wie Benchmarking -Laufschuhe.
Natürlich gibt es einige schreckliche Schuhe zu rennen (Absätze, Clogs usw.), aber sobald Sie sich in einem angemessenen Paar Schuhe befinden, ist es der Läufer, der von Bedeutung ist, nicht die Schuhe.
In dieser Analogie ist der Läufer das, was Ihre Handler tatsächlich tun, und die Schuhe sind die Wahl des HTTP -Servers.
In diesem Sinne schlage ich drei Prioritäten vor:
Stellen Sie sicher, dass Ihre Auswahl Ihrer HTTP Server die Leistung nicht unnötig behindert.
Vermeiden Sie HTTP -Server, die einfache Leistungsschwachstellen haben.
Priorisieren Sie, was Sie ermöglichen, um Performanten und zuverlässige Handler zu schreiben und zu pflegen.
Ich glaube, Mama löscht alle drei Prioritäten:
Mumie priorisiert die Effizienz beim Empfangen und Versenden von eingehenden Anfragen und das Senden ausgehender Antworten. Dies bedeutet, dass Dinge wie das Vermeiden von unnötigem Speicherkopieren und sicherstellen, dass die CPU die ganze Zeit in Ihren Handlern verbringt.
Da Mummy Multiplexed IO wie Async verwendet, ist Mumie nicht anfällig für Angriffe wie Low-and-Slow, für die traditionell Multi-Threaden-Server anfällig sind. Während ein einzelner Blockier- oder CPU -starker Betrieb einen gesamten Async -Server zum Stillstand bringen kann, ist dies für Mumie kein Problem.
Anfrage Handler mit Mumie sind einfach alte Inline-NIM-Code. Sie haben eine unkomplizierte API für die Reaktionsanfrage. Die einfachen Aufrechterhaltung ist hervorragend für Wartung, Zuverlässigkeit und Leistung.
Das Benchmarking wurde auf einem Ubuntu 22.04 -Server mit einer 4 Core / 8 -Thread -CPU durchgeführt.
Die Tests/WRK_ -Server, die einen Benchmarking -Versuch haben, Anforderungen zu simulieren, die ~ 10 ms zum Abschluss dauern.
Alle Benchmarks wurden getestet von:
wrk -t10 -c100 -d10s http://localhost:8080
Die genauen Befehle für jeden Server sind:
nim c --mm:orc --threads:on -d:release -r tests/wrk_mummy.nim
Anfragen/Sekunden: 9.547,56
nim c --mm:orc --threads:off -d:release -r tests/wrk_asynchttpserver.nim
Anfragen/Sekunden: 7.979,67
nim c --mm:orc --threads:on -d:release -r tests/wrk_httpbeast.nim
Anfragen/Sekunden: 9.862,00
nim c --mm:orc --threads:off -d:release -r tests/wrk_jester.nim
Anfragen/Sekunden: 9.692,81
nim c --mm:orc --threads:off -d:release -r tests/wrk_prologue.nim
Anfragen/Sekunden: 9.749,22
node tests/wrk_node.js
Anfragen/Sekunden: 8.544,60
go run tests/wrk_go.go
Anfragen/Sekunden: 9.171,55
Ein Fuder wurde gegen Mummys Sockel -Les- und Parsencode ausgeführt, um sicherzustellen, dass Mumie weder abstürzt oder auf andere Weise schlechte Daten von Steckdosen schlecht benimmt. Sie können den Fuzzer jederzeit ausführen, indem Sie nim c -r tests/fuzz_recv.nim ausführen.