¿Debería ejecutarse diesel utilizando un actor de sincronización, actix_web :: web :: block o futures-cpupool?

10

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::blockpara 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.

logina
fuente
De los comentarios en este número , parece que futures-cpupooles la solución recomendada para la falta de asyncsoporte en Diesel.
Jmb
Esa es más una solución general. Espero algo que aproveche el sistema actix. Sin embargo, ahora investigaré en futures-cpupool para buscar problemas.
logina
¡Bienvenido a Stack Overflow! Parece que su pregunta podría ser respondida por las respuestas de ¿Cuál es el mejor enfoque para encapsular el bloqueo de E / S en futuros rs? . Si no, edite su pregunta para explicar las diferencias. De lo contrario, podemos marcar esta pregunta como ya respondida.
Shepmaster el
Como el cpupool también interactúa con el grupo de conexiones de bloqueo en r2d2, no estoy seguro de cómo resolverlo mejor. Lo estoy investigando ahora mismo y lo actualizaré pronto.
logina

Respuestas:

3

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.

logina
fuente
66
leyendo mis hallazgos anteriores , por favor ponga información relevante para la respuesta en la respuesta , no en la pregunta.
Shepmaster el