programacion - ¿Cómo se pueden hacer objetos de Python persistentes en una aplicación web?
poo python 3 (6)
Creo que el marco de multiprocesamiento tiene lo que podría ser aplicable aquí, a saber, el módulo ctypes compartido.
El multiprocesamiento es bastante nuevo en Python, por lo que podría tener algunas rarezas. No estoy seguro de si la solución funciona con procesos que no se generan a través de multiprocessing
.
Estoy escribiendo una aplicación web razonablemente compleja. El backend de Python ejecuta un algoritmo cuyo estado depende de los datos almacenados en varias tablas de bases de datos interrelacionadas que no cambian a menudo, más los datos específicos del usuario que cambian a menudo. El estado por usuario del algoritmo sufre muchos pequeños cambios a medida que un usuario trabaja con la aplicación. Este algoritmo se usa a menudo durante el trabajo de cada usuario para tomar ciertas decisiones importantes.
Por razones de rendimiento, volver a inicializar el estado en cada solicitud desde la base de datos (seminormalizada) rápidamente se vuelve inviable. Sería preferible, por ejemplo, guardar en caché el objeto Python del estado de alguna manera para que simplemente se pueda usar y / o actualizar siempre que sea necesario. Sin embargo, como se trata de una aplicación web, existen varios procesos que atienden las solicitudes, por lo que no se puede usar una variable global.
Intenté serializar el objeto relevante (mediante pickle) y guardar los datos serializados en el DB, y ahora estoy experimentando con el almacenamiento en caché de los datos serializados a través de memcached. Sin embargo, esto todavía tiene la sobrecarga significativa de serializar y deserializar el objeto a menudo.
He analizado las soluciones de memoria compartida, pero la única cosa relevante que he encontrado es POSH . Sin embargo, el POSH no parece ser ampliamente utilizado y no me resulta fácil integrar dicho componente experimental en mi aplicación.
¡Necesito un consejo! Esta es mi primera oportunidad para desarrollar una aplicación web, por lo que espero que este sea un problema tan común que existen soluciones bien conocidas para tales problemas. En este punto, las soluciones que supongan que el back-end de Python se ejecuta en un solo servidor serían suficientes, pero también puntos extra para las soluciones que se adaptan a varios servidores también :)
Notas:
- Tengo esta aplicación funcionando, actualmente en vivo y con usuarios activos. Comencé sin hacer ninguna optimización prematura, y luego optimicé según lo necesitado. Hice la medición y las pruebas para asegurarme de que el problema mencionado anteriormente sea el cuello de botella real. Estoy seguro de que podría sacar más rendimiento de la configuración actual, pero quería preguntar si hay una mejor manera.
- La configuración en sí sigue siendo un trabajo en progreso; supongamos que la arquitectura del sistema puede ser cualquiera que sea su solución.
Creo que puedes darle una oportunidad a ZODB.
"Una característica importante de ZODB es la transparencia. No necesita escribir ningún código para leer o escribir explícitamente sus objetos desde o hacia una base de datos. Simplemente coloque sus objetos persistentes en un contenedor que funciona como un diccionario de Python. el diccionario se guarda en la base de datos. Se dice que este diccionario es la "raíz" de la base de datos. Es como una bolsa mágica, cualquier objeto de Python que pongas dentro se vuelve persistente ".
Initailly fue una parte integral de Zope, pero últimamente también está disponible un paquete independiente.
Tiene la siguiente limitación:
"En realidad, hay algunas restricciones sobre lo que puede almacenar en ZODB. Puede almacenar cualquier objeto que pueda ser" escabechado "en un formato serial multiplataforma estándar. Objetos como listas, diccionarios y números pueden ser escabeche. como archivos, sockets y objetos de código de Python, no se pueden almacenar en la base de datos porque no se pueden escanear ".
Lo he leído pero no lo he probado.
Otra cosa posible podría ser un db sqlite en memoria, que puede acelerar un poco el proceso, es decir, un db en memoria, pero aún tendría que hacer las tareas de serialización y todo. Nota: En memoria, db es costoso para los recursos.
Aquí hay un enlace: http://www.zope.org/Documentation/Articles/ZODB1
En primer lugar, su enfoque no es una práctica común de desarrollo web. Incluso se está utilizando multi threading, las aplicaciones web están diseñadas para poder ejecutar entornos de procesamiento múltiple, tanto para la escalabilidad como para una implementación más sencilla.
Si solo necesita inicializar un objeto grande, y no necesita cambiarlo más tarde, puede hacerlo fácilmente utilizando una variable global que se inicializa mientras se está creando su aplicación WSGI, o el módulo contiene el objeto que se está cargando, etc. el procesamiento múltiple le irá bien.
Si necesita cambiar el objeto y acceder a él desde cada hilo, debe asegurarse de que su objeto sea seguro para hilos, use bloqueos para garantizarlo. Y usa un contexto de servidor único, un proceso. Cualquier servidor de python multi threading te servirá bien, también FCGI es una buena opción para este tipo de diseño.
Pero, si hay varios hilos que acceden y cambian su objeto, los bloqueos pueden tener un efecto realmente negativo en su ganancia de rendimiento, lo que probablemente hará que todos los beneficios desaparezcan.
Otra opción es revisar el requisito de estado, parece que si la serialización es el cuello de la botella, entonces el objeto es muy grande. ¿Realmente necesitas un objeto tan grande?
Sé en el podcast 27 que los chicos reddit discuten lo que usan para el estado, por lo que tal vez sea útil escucharlo.
Tenga cuidado con la optimización prematura.
Además: el "back-end de Python ejecuta un algoritmo cuyo estado ..." es la sesión en el marco web. Eso es. Deje que el marco de trabajo de Django mantenga el estado de la sesión en la memoria caché. Período.
"El estado por usuario del algoritmo sufre muchos pequeños cambios a medida que un usuario trabaja con la aplicación". La mayoría de los marcos web ofrecen un objeto de sesión en caché. A menudo es de muy alto rendimiento. Vea la documentación de la sesión de Django para esto.
Consejo. [Revisado]
Parece que tienes algo que funciona. Aproveche para aprender su marco de referencia, aprender las herramientas y aprender qué mandos puede activar sin sudar. Específicamente, usando el estado de la sesión.
En segundo lugar, juega con el almacenamiento en caché, la administración de sesiones y cosas que son fáciles de ajustar, y ver si tienes velocidad suficiente. Averigüe si el socket MySQL o named pipe es más rápido probándolos. Estas son las optimizaciones sin programación.
En tercer lugar, mida el rendimiento para encontrar su cuello de botella real. Esté preparado para proporcionar (y defender) las mediciones lo suficientemente finas como para ser útiles y lo suficientemente estables como para proporcionar una comparación significativa de las alternativas.
Por ejemplo, muestre la diferencia de rendimiento entre sesiones persistentes y sesiones en caché.
Este es Durus, un sistema persistente de objetos para aplicaciones escritas en el lenguaje de programación Python. Durus ofrece una manera fácil de usar y mantener una colección coherente de instancias de objeto utilizadas por uno o más procesos. El acceso y el cambio de una instancia persistente se gestiona a través de una instancia de conexión en caché que incluye los métodos commit () y abort () para que los cambios sean transaccionales.
http://www.mems-exchange.org/software/durus/
Lo he usado antes en algún código de investigación, donde quería persistir con los resultados de ciertos cálculos. Eventualmente cambié a Pytables ya que satisfacía mis necesidades mejor.