nimble install mummy
Referência da API
A múmia é um HTTP 1.1 e o servidor WebSocket multitread e o WebSocket escrito inteiramente no NIM.
Um retorno aos modos antigos dos fios.
A múmia foi escrita especificamente para maximizar o desempenho do hardware do seu servidor sem comprometer a felicidade do programador.
{.async.} . A múmia requer --threads:on e --mm:orc ou --mm:arc .
O nome da múmia refere -se a coisas históricas do Egito.
A múmia opera com este modelo básico: manipule todos os soquetes IO em um thread e envie solicitações HTTP recebidas e eventos da WebSocket para um pool de threads de trabalhadores. Seus manipuladores HTTP provavelmente nem precisam pensar em tópicos.
Esse modelo tem muitos grandes benefícios e está pronto para aproveitar os aumentos contínuos da contagem de núcleo do servidor (a AMD acaba de anunciar uma CPU do 96 Core 192 Thread Server!).
Não há mais necessidade de usar {.async.} , Future[] , await etc. e lidar com funções com cores.
Mantenha a mesma taxa de transferência excelente do soquete não bloqueado multiplexado.
Nenhuma preocupação de que alguém bloqueie ou chamado caro paro seu servidor inteiro.
Bloco assíncrono em coisas surpreendentes, como resolução DNS e leituras de arquivos, que impedirão todo o manuseio de solicitações.
Mais simples de escrever manipuladores de solicitação. Bloquear o fio está totalmente bem! Precisa fazer uma consulta Postgres? Não tem problema, apenas aguarde os resultados.
Há uma vantagem substancial em escrever código mais simples versus teoricamente rápido, mas possivelmente complicado e com código de buggy.
Depuração muito mais simples. Os traços de pilha assíncrona são enormes e confusos.
Manipulação de erros mais fácil, try except como você normalmente. Exceções não capturadas nos manipuladores de mamãe também não reduzem todo o seu servidor.
A múmia lida com a rosqueamento e a expedição para que seus manipuladores possam não precisar pensar em threads.
Aproveite vários núcleos e o incrível trabalho da equipe NIM no ARC / ORC e NIM 2.0.
Os websockets são maravilhosos e podem ter vantagens substanciais sobre os paradigmas de API mais tradicionais como o REST e vários sabores do RPC.
Infelizmente, a maioria dos servidores HTTP finge que os websockets não existem.
Isso significa que os desenvolvedores precisam invadir o suporte por meio de dependências adicionais, conexões sequestrando etc. e tudo raramente se adiciona em algo realmente ótimo.
Não vejo razão para que os websockets não funcionem excepcionalmente bem prontos, salvando os desenvolvedores de muita incerteza e tempo pesquisando quais das maneiras possíveis de abaixar o suporte do WebSocket em um servidor HTTP é "melhor".
Tudo vem com trocas. A múmia está focada em ser um servidor de API excepcional. Pense em descanso, json, rpc, websockets, html de modelos etc.
A propriedade que eles compartilham em comum é que todos são relativamente à luz da memória. A maioria das coisas é, o que é ótimo, mas se você estiver especificamente, servir a muitos arquivos muito grandes ou esperar uploads de arquivos grandes, a mamãe provavelmente não é a melhor opção, a menos que seu servidor tenha a RAM para lidar com os arquivos grandes.
Por que a mamãe não é ótima para arquivos grandes? Isso ocorre porque os despacho de múmia recebem solicitações na memória totalmente recebidas para tópicos do trabalhador e envia respostas na memória. Isso é ótimo para tudo, exceto arquivos muito 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 os exemplos/ pasta para obter mais código de amostra, incluindo um exemplo do WebSocket Chat Server.
nim c --threads:on --mm:orc -r examples/basic_websockets.nim
Os servidores HTTP de benchmarking são um pouco como tênis de corrida de benchmarking.
Certamente, existem alguns sapatos terríveis para correr (saltos, entupimentos, etc.), mas quando você está em um par de sapatos razoável, é o corredor que vai importar, não os sapatos.
Nesta analogia, o corredor é o que seus manipuladores estão realmente fazendo e os sapatos são a escolha do servidor HTTP.
Com isso em mente, sugiro três prioridades:
Verifique se a sua opção de servidor HTTP não prejudica desnecessariamente o desempenho.
Evite servidores HTTP com fáceis vulnerabilidades de desempenho.
Priorize o que permitirá que você escreva e mantenha manipuladores de desempenho e confiável.
Eu acredito que a mamãe limpa todas as três prioridades:
A múmia prioriza a eficiência em receber e despachar solicitações recebidas e enviar respostas de saída. Isso significa coisas como evitar a cópia desnecessária da memória, garantindo que a CPU gaste todo o seu tempo em seus manipuladores.
Como a mamãe usa o IO multiplexado como o Async, a mamãe não é vulnerável a ataques como o baixo e o llow ao qual os servidores tradicionalmente multitreados são vulneráveis. Além disso, enquanto uma única operação de bloqueio ou CPU pode parar um servidor Async inteiro, isso não é um problema para a mamãe.
Os manipuladores de solicitação com mamãe são apenas o código NIM em linha. Eles têm uma API direta de solicitação em resposta. Manter as coisas simples é ótimo para manutenção, confiabilidade e desempenho.
O benchmarking foi realizado em um servidor Ubuntu 22.04 com uma CPU de 4 núcleo / 8 thread.
Os servidores testes/wrk_ que estão sendo comparados tentam simular solicitações que levam ~ 10ms para concluir.
Todos os benchmarks foram testados por:
wrk -t10 -c100 -d10s http://localhost:8080
Os comandos exatos para cada servidor são:
nim c --mm:orc --threads:on -d:release -r tests/wrk_mummy.nim
Solicitações/Sec: 9.547.56
nim c --mm:orc --threads:off -d:release -r tests/wrk_asynchttpserver.nim
Solicitações/Sec: 7.979.67
nim c --mm:orc --threads:on -d:release -r tests/wrk_httpbeast.nim
Solicitações/Sec: 9.862.00
nim c --mm:orc --threads:off -d:release -r tests/wrk_jester.nim
Solicitações/Sec: 9.692.81
nim c --mm:orc --threads:off -d:release -r tests/wrk_prologue.nim
Solicitações/Sec: 9.749.22
node tests/wrk_node.js
Solicitações/Sec: 8.544.60
go run tests/wrk_go.go
Solicitações/Sec: 9.171.55
Um Fuzzher foi executado contra o código de leitura e análise de soquete da mamãe para garantir que a múmia não trave ou, de outra forma, se comportasse mal em dados ruins dos soquetes. Você pode executar o Fuzzher a qualquer momento executando nim c -r tests/fuzz_recv.nim .