Antecedentes
Estoy trabajando en una aplicación web actix que usa diesel a través de r2d2 y no estoy seguro de cómo hacer mejor las consultas asincrónicas. He encontrado tres opciones que parecen razonables, pero no estoy seguro de cuál es la mejor.
Soluciones potenciales
Sincronizar actor
Por un lado, podría usar el ejemplo actix , pero es bastante complicado y requiere una buena cantidad de repeticiones para construir. Espero que exista una solución más razonable.
Actix_web::web::block
Como otra opción, podría usar actix_web::web::block
para ajustar mis funciones de consulta en un futuro, pero no estoy seguro de las implicaciones de rendimiento de esto.
¿La consulta se ejecuta en el mismo sistema Tokio? Por lo que pude encontrar en la fuente, crea un hilo en el conjunto de hilos actix-web subyacente . ¿Es eso un problema?
Si leo el código correctamente, r2d2 bloquea su hilo cuando adquiere una conexión, lo que bloquearía parte del núcleo del grupo web actix. Lo mismo con las consultas de la base de datos. ¿Esto bloquearía toda la web actix si hago más consultas de las que tengo en ese grupo? Si es así, gran problema.
Futures-cpupool
Finalmente, la apuesta segura que puede tener algunos gastos innecesarios es futures-cpupool . El problema principal es que esto significa agregar otra caja a mi proyecto, aunque no me gusta la idea de que múltiples cpu-pools floten innecesariamente en mi aplicación.
Dado que tanto el r2d2 como el diésel se bloquearán, hay una cantidad sorprendente de cosas difíciles aquí.
Lo que es más importante, no comparta este cpupool con nada que no use el mismo grupo de r2d2 (ya que todos los subprocesos creados pueden bloquear la espera de una conexión de r2d2, bloqueando todo el grupo cuando existe trabajo).
En segundo lugar (un poco más obvio), por lo tanto, no debería tener más conexiones r2d2 que subprocesos en el grupo y viceversa, ya que el más grande desperdiciaría recursos (conexiones no utilizadas / subprocesos constantemente bloqueados) (quizás un subproceso más, para quizás más rápido transferencia de conexión por el planificador del sistema operativo en lugar del planificador cpupool).
Finalmente, tenga en cuenta qué base de datos está utilizando y el rendimiento que tiene allí. Ejecutar una sola conexión r2d2 y un solo subproceso en el grupo podría ser mejor en una aplicación sqlite de escritura pesada (aunque recomendaría una base de datos adecuada para tal).
Viejas respuestas
Viejas soluciones que pueden funcionar
https://www.reddit.com/r/rust/comments/axy0hp/patterns_to_scale_actixweb_and_diesel/
En esencia, recomienda Futures-cpupool.
¿Cuál es el mejor enfoque para encapsular el bloqueo de E / S en futuros rs?
Recomienda Futures-cpupool para casos generales.
Viejas soluciones que no funcionan
https://www.reddit.com/r/rust/comments/9fe1ye/noob_here_can_we_talk_about_async_and_databases/
Una buena solución para una versión anterior de actix-web. Por lo que puedo encontrar, las solicitudes ya no tienen un cpu-pool en ellas.
fuente
futures-cpupool
es la solución recomendada para la falta deasync
soporte en Diesel.Respuestas:
Voy con futures-cpupool. Es la mejor solución debido a la naturaleza de bloqueo de mis interacciones.
El uso de actix_web :: web :: block es lo suficientemente decente, pero usará un conjunto de subprocesos compartido en actix (y debido a las llamadas de bloqueo que uso, esto puede bloquear todo el conjunto de subprocesos e interferir con otras tareas asignadas a actix_web).
Es mejor usar futures-cpupool para crear un threadpool separado por base de datos solo para las interacciones de la base de datos. De esta forma, agrupa todas las tareas que deben esperarse entre sí (cuando hay más tareas que conexiones) en un grupo, evitando que bloqueen cualquier otra tarea que no necesite una conexión y limitando potencialmente el número de subprocesos al número de conexiones (de modo que la tarea solo se programará cuando no se bloquee).
En el caso de que solo desee utilizar una conexión de base de datos (o muy pocas), el actor de sincronización es una muy buena opción. Actuará como un cpupool de futuros con un hilo, asegurando que todas las tareas se ejecuten una a la vez, excepto que usará uno de los hilos subyacentes de actix-web en lugar de uno separado (por lo tanto, solo es bueno para muy pocas conexiones) . Sin embargo, considero que el repetitivo es demasiado grande para que valga la pena.
fuente