fundo
Estou trabalhando em um aplicativo actix-web usando diesel através de r2d2 e não tenho certeza de como fazer consultas assíncronas da melhor maneira. Encontrei três opções que parecem razoáveis, mas não tenho certeza de qual é a melhor.
Soluções Potenciais
Ator de sincronização
Por um lado, eu poderia usar o exemplo actix , mas é bastante complicado e requer uma boa dose de clichê para construir. Espero que exista uma solução mais razoável.
Actix_web::web::block
Como outra opção, eu poderia usar o actix_web::web::block
para agrupar minhas funções de consulta em um futuro, mas não tenho certeza das implicações de desempenho disso.
A consulta está sendo executada no mesmo sistema Tokio? Pelo que pude encontrar na fonte, ele cria um encadeamento no pool de encadeamentos actix-web subjacente . Isso é um problema?
Se eu ler o código corretamente, o r2d2 bloqueia seu encadeamento ao adquirir uma conexão, o que bloquearia parte do pool principal do actix-web. Mesmo com consultas de banco de dados. Isso bloquearia todo o actix-web se eu fizer mais consultas do que ter threads nesse pool? Se assim for, grande problema.
Futuros-cpupool
Finalmente, a aposta segura que pode ter uma sobrecarga desnecessária é o cpupool de futuros . A questão principal é que isso significa adicionar outra caixa ao meu projeto, embora eu não goste da ideia de vários pools de CPUs flutuando no meu aplicativo desnecessariamente.
Como o r2d2 e o diesel bloquearão, há uma quantidade surpreendente de coisas complicadas aqui.
Mais importante, não compartilhe esse cpupool com nada que não esteja usando o mesmo pool r2d2 (pois todos os threads criados podem bloquear a espera de uma conexão r2d2, bloqueando todo o pool quando houver trabalho).
Em segundo lugar (um pouco mais óbvio), você não deveria ter mais conexões r2d2 do que threads no pool e vice-versa, pois a maior desperdiçaria recursos (conexões não utilizadas / threads constantemente bloqueadas) (talvez mais um thread, talvez mais rápido transferência de conexão pelo agendador do SO em vez do agendador do cpupool).
Por fim, lembre-se do banco de dados que você está usando e do desempenho que você tem lá. A execução de uma única conexão r2d2 e um único encadeamento no pool pode ser melhor em um aplicativo sqlite pesado de gravação (embora eu recomende um banco de dados adequado para isso).
Respostas antigas
Soluções antigas que podem funcionar
https://www.reddit.com/r/rust/comments/axy0hp/patterns_to_scale_actixweb_and_diesel/
Em essência, recomenda Futures-cpupool.
Qual é a melhor abordagem para encapsular E / S de bloqueio no futuro-rs?
Recomenda o Futures-cpupool para casos gerais.
Soluções antigas que não funcionam
https://www.reddit.com/r/rust/comments/9fe1ye/noob_here_can_we_talk_about_async_and_databases/
Uma correção muito boa para uma versão antiga do actix-web. Pelo que posso encontrar, os pedidos não têm mais um conjunto de CPUs.
fonte
futures-cpupool
é a solução alternativa recomendada para a falta deasync
suporte no Diesel.Respostas:
Eu estou indo com futuros-cpupool. É a melhor solução devido à natureza de bloqueio das minhas interações.
O uso do actix_web :: web :: block é decente o suficiente, mas utilizará um pool de threads compartilhado no actix (e devido às chamadas de bloqueio que eu uso, isso pode bloquear todo o pool de threads e interferir em outras tarefas atribuídas ao actix_web).
É melhor usar o futures-cpupool para criar um pool de threads separado por banco de dados apenas para interações com o banco de dados. Dessa forma, você agrupa todas as tarefas que precisam esperar uma pela outra (quando há mais tarefas que conexões) em um pool, impedindo-as de bloquear outras tarefas que não precisam de conexão e potencialmente limitando o número de threads ao número de conexões (para que a tarefa seja agendada apenas quando não for bloqueada).
No caso em que você deseja usar apenas uma conexão com o banco de dados (ou muito poucas), o agente de sincronização é uma opção muito boa. Ele agirá como um futuros-cpupool com um encadeamento, garantindo que todas as tarefas sejam executadas uma de cada vez, exceto pelo uso de um dos encadeamentos subjacentes do actix-web em vez de um separado (portanto, apenas bom para pouquíssimas conexões) . Acho que o clichê grande demais para valer a pena, no entanto.
fonte