nimble install mummy
Referencia de API
Mummy es un servidor HTTP 1.1 y WebSocket de múltiples subprocesos escrito completamente en NIM.
Un regreso a las antiguas formas de hilos.
Mummy ha sido escrita específicamente para maximizar el rendimiento de su hardware de servidor sin comprometer la felicidad del programador.
{.async.} . Mummy requiere --threads:on y --mm:orc o --mm:arc .
El nombre de la momia se refiere a cosas históricas de Egipto.
Mummy opera con este modelo básico: maneje todo el socket IO en un hilo y envíe solicitudes HTTP entrantes y eventos WebSocket a un grupo de subprocesos de trabajadores. Sus manejadores HTTP probablemente ni siquiera necesitarán pensar en los hilos.
Este modelo tiene muchos beneficios excelentes y está listo para aprovechar los aumentos continuos del conteo del núcleo del servidor (¡AMD acaba de anunciar una CPU 96 Core 192 Thread Server!).
No es más necesario usar {.async.} , Future[] , await , etc. y tratar con funciones que tienen colores.
Mantenga el mismo excelente rendimiento de enchufe sin bloqueo multiplexado IO.
No se preocupe que una llamada de bloqueo o costosa detenga todo su servidor.
Async bloquea cosas sorprendentes como la resolución DNS y las lecturas de archivos que detendrán todo el manejo de solicitudes.
Los manejadores de solicitudes más simples de escribir. ¡Bloquear el hilo está totalmente bien! ¿Necesitas hacer una consulta de Postgres? No hay problema, solo espera los resultados.
Existe una ventaja sustancial en escribir código más simple frente a código teóricamente rápido pero posiblemente complicado y errante.
Depuración mucho más simple. Las trazas de pila asíncronas son enormes y confusas.
Manejo de errores más fácil, solo try except como lo hace normalmente. Las excepciones no capturas en los manejadores de momias tampoco derriban todo su servidor.
Mummy maneja el roscado y el despacho para que sus manejadores no necesiten pensar en los hilos.
Aprovecha múltiples núcleos y el increíble trabajo del equipo NIM en ARC / ORC y NIM 2.0.
Los websockets son maravillosos y pueden tener ventajas sustanciales sobre los paradigmas de API más tradicionales como el descanso y varios sabores de RPC.
Desafortunadamente, la mayoría de los servidores HTTP fingen que WebSockets no existen.
Esto significa que los desarrolladores deben piratear el soporte a través de dependencias adicionales, conexiones de secuestro, etc., y rara vez se suma a algo realmente genial.
No veo ninguna razón por la cual WebSockets no funcione excepcionalmente bien fuera de la caja, ahorrando a los desarrolladores mucha incertidumbre y tiempo investigando cuál de las posibles formas de acumular el soporte de WebSocket en un servidor HTTP es "mejor".
Todo viene con compensaciones. Mummy se centra en ser un servidor API excepcional. Piense en reposo, JSON, RPC, WebSockets, HTML de plantillas, etc.
La propiedad que estos comparten en común es que todos son relativamente ligeros de memoria. La mayoría de las cosas son, lo cual es excelente, pero si específicamente va a servir muchos archivos muy grandes o espera cargas de archivos grandes, Mummy probablemente no sea la mejor opción a menos que su servidor tenga la RAM para manejar los archivos grandes.
¿Por qué mamá no es excelente para archivos grandes? Esto se debe a que los despachos de momias recibieron solicitudes en memoria por completo a los subprocesos de trabajadores y envían respuestas en memoria. Esto es ideal para todo excepto archivos muy grandes.
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 ))Consulte los ejemplos/ carpeta para obtener más código de muestra, incluido un ejemplo de servidor de chat de WebSocket.
nim c --threads:on --mm:orc -r examples/basic_websockets.nim
Los servidores HTTP de la evaluación comparativa son un poco como las zapatillas para correr.
Ciertamente, hay algunos zapatos terribles para correr (tacones, zuecos, etc.), pero una vez que estás en un par de zapatos razonables, es el corredor que va a importar, no los zapatos.
En esta analogía, el corredor es lo que realmente están haciendo sus manejadores y los zapatos son la elección del servidor HTTP.
Con eso en mente, sugiero tres prioridades:
Asegúrese de que la elección de su servidor HTTP no obstaculice innecesariamente el rendimiento.
Evite los servidores HTTP que tienen vulnerabilidades de rendimiento fáciles.
Priorice lo que le permitirá escribir y mantener manejadores performantes y confiables.
Creo que mamá despeja las tres prioridades:
Mummy prioriza la eficiencia en la recepción y el envío de solicitudes entrantes y el envío de respuestas salientes. Esto significa que cosas como evitar la copia de memoria innecesaria, asegurar que la CPU pase todo su tiempo en sus manejadores.
Debido a que Mummy usa IO multiplexado al igual que Async, Mummy no es vulnerable a ataques como bajo y lento, a los que tradicionalmente los servidores de múltiples subcontratación son vulnerables. Además, mientras que un solo bloqueo o una operación pesada de CPU puede detener un servidor Async completo, esto no es un problema para la momia.
Los manejadores de solicitud con Mummy son simplemente un código NIM en línea simple. Tienen una API directa de solicitud de respuesta. Mantener las cosas simples es excelente para el mantenimiento, la confiabilidad y el rendimiento.
La evaluación comparativa se realizó en un servidor Ubuntu 22.04 con una CPU de 4 hilos de 4 núcleos.
Los servidores Tests/WRK_ que están siendo comparados intentan simular solicitudes que toman ~ 10 ms para completar.
Todos los puntos de referencia fueron probados por:
wrk -t10 -c100 -d10s http://localhost:8080
Los comandos exactos para cada servidor son:
nim c --mm:orc --threads:on -d:release -r tests/wrk_mummy.nim
Solicitudes/seg: 9,547.56
nim c --mm:orc --threads:off -d:release -r tests/wrk_asynchttpserver.nim
Solicitudes/seg: 7,979.67
nim c --mm:orc --threads:on -d:release -r tests/wrk_httpbeast.nim
Solicitudes/seg: 9,862.00
nim c --mm:orc --threads:off -d:release -r tests/wrk_jester.nim
Solicitudes/seg: 9,692.81
nim c --mm:orc --threads:off -d:release -r tests/wrk_prologue.nim
Solicitudes/seg: 9,749.22
node tests/wrk_node.js
Solicitudes/seg: 8,544.60
go run tests/wrk_go.go
Solicitudes/seg: 9,171.55
Se ha ejecutado un fuzzer contra el código de lectura y análisis de Socket de Mummy para garantizar que Mummy no se bloquee o se porta mal en los malos datos de los enchufes. Puede ejecutar el fuzzer en cualquier momento ejecutando nim c -r tests/fuzz_recv.nim .