Anatomía de un Sistema Distribuido en PHP


Tengo un problema que me está dando un tiempo difícil tratando de averiguar la solución ideal y, para explicarlo mejor, voy a exponer mi escenario aquí.

Tengo un servidor que recibirá los pedidos de varios clientes. Cada cliente enviar un conjunto de tareas recurrentes que debe ser ejecutado en algún especificado intervalos, por ejemplo.: cliente A envía tarea AA que debe ser ejecutado cada minuto entre 2009-12-31 y 2010-12-31; así que si mi matemáticas tiene razón eso es alrededor de 525 600 operaciones en un año, dado más clientes y tareas sería inviable dejar que el servidor procese todas estas tareas así que se le ocurrió la idea de trabajador máquinas. El servidor será desarrollado en PHP.

Las máquinas de trabajo son baratas Basado en Windows equipos que voy a anfitrión en mi casa o en mi lugar de trabajo, cada trabajador tendrá un dedicado Conexión a Internet ( con IPS dinámicas ) y un UPS para evitar cortes de energía. Cada worker también consultará el servidor cada 30 segundos más o menos a través de llamadas de servicio web, obtener el siguiente trabajo pendiente y procesarlo. Una vez completado el trabajo, el trabajador enviar la salida al servidor y solicitar un nuevo trabajo y así sucesivamente hasta el infinito. Si es necesario escalar el sistema I sólo debe establecer un nuevo trabajador y el todo debería funcionar sin problemas. Se desarrollará el cliente trabajador en PHP o Python.

En cualquier momento mis clientes debería ser capaz de iniciar sesión en el servidor y comprobar el estado de las tareas que ordenaron.

Aquí es donde entra en juego la parte complicada:

  • debo ser capaz de reconstruir la tareas ya procesadas si para algunos razón por la que el servidor se cae.
  • Los trabajadores no son específicos del cliente, un trabajador debe procesar trabajos para cualquier número dado de clientes.

Tengo algunas dudas con respecto al diseño general de la base de datos y que tecnologías a utilizar.

Originalmente pensé en usar varias bases de datos SQLite y unirlas todas en el servidor, pero no puedo averiguar cómo agruparía por clientes para generar los informes de trabajo.

Nunca he trabajado con ninguna de las siguientes tecnologías: memcached, CouchDB, Hadoop y todos los similares, pero me gustaría saber si alguno de estos es adecuado para mi problema, y si es así, ¿qué recomienda para un novato es "computación distribuida" (¿o es esto paralelo?) como yo. Tenga en cuenta que los trabajadores tienen IP dinámicas.

Como dije antes, también tengo problemas con el diseño general de la base de datos, en parte porque todavía no he elegido ningún DBMS de R(D)en particular, pero un problema que tengo y creo que es agnóstico al DBMS que elijo está relacionado con el sistema de colas ... Debería precalcular todas las marcas de tiempo absolutas para un trabajo específico y tener un gran conjunto de marcas de tiempo , ejecutarlas y marcarlas como completas en orden ascendente o debería tener un sistema más inteligente como "cuando módulo de marca de tiempo 60 = = 0 -> ejecutar". El problema con este sistema "inteligente" es que algunos trabajos no se ejecutarán en el orden deberían ser porque algunos trabajadores podrían estar esperando sin hacer nada mientras que otros están sobrecargados. ¿Qué sugieres?

PD: No estoy seguro de si el título y las etiquetas de esta pregunta reflejan correctamente mi problema y lo que estoy tratando de hacer; si no por favor editar en consecuencia.

Gracias por tu aporte!

@timdev:

  1. La entrada será una cadena codificada en JSON muy pequeña, la salida también será una cadena codificada en JSON pero un poco más grande (en el orden de 1-5 KB).
  2. La salida se calculará utilizando varios recursos disponibles de la Web, por lo que el principal cuello de botella probablemente será el ancho de banda. Las escrituras de base de datos también pueden ser una-dependiendo de la R (D) DBMS.
Author: Alix Axel, 2009-10-04

7 answers

Parece que estás a punto de recrear Gearman. Aquí está la introducción para Gearman:

Gearman proporciona una aplicación genérica marco para sacar el trabajo a otros máquinas o procesos que son mejores adecuado para hacer el trabajo. Permite hacer el trabajo en paralelo, cargar procesamiento de saldo, y para llamar funciones entre idiomas. Puede ser utilizado en una variedad de aplicaciones, de sitios web de alta disponibilidad a el transporte de la base de datos replicación evento. En otras palabras, es el sistema nervioso para cómo se distribuye procesamiento comunica.

Puede escribir tanto su cliente como el código de back-end worker en PHP.


Re su pregunta sobre un servidor Gearman compilado para Windows: No creo que esté disponible en un paquete ordenado pre-construido para Windows. Gearman es todavía un proyecto bastante joven y puede que no hayan madurado hasta el punto de producir distribuciones listas para ejecutar para Windows.

Los empleados de Sun/MySQL Eric Day y Brian Aker dieron un tutorial para Gearman en OSCON en julio de 2009, pero sus diapositivas solo mencionan paquetes de Linux.

Aquí hay un enlace al proyecto Perl CPAN Testers, que indica que Gearman-Server se puede construir en Win32 usando el compilador Microsoft C (cl.exe), y pasa las pruebas: http://www.nntp.perl.org/group/perl.cpan.testers/2009/10/msg5521569.html Pero supongo que tienes que descargar el código fuente y construirlo a ti mismo.

 15
Author: Bill Karwin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-13 18:38:51

Gearman parece el candidato perfecto para este escenario, es posible que incluso desee virtualizar sus máquinas windows a múltiples nodos de trabajo por máquina dependiendo de la cantidad de potencia de cálculo que necesita.

También el sistema de colas persistentes en gearman evita que los trabajos se pierdan cuando un trabajador o el servidor gearman se bloquea. Después de reiniciar un servicio, la cola simplemente continúa donde lo dejó antes de que se bloquee/reinicie, no tiene que encargarse de todo esto en su aplicación y que es una gran ventaja y ahorra mucho tiempo/código

Elaborar una solución personalizada podría funcionar, pero las ventajas de gearman, especialmente la cola persistente, me parecen que esta podría ser la mejor solución para usted en este momento. No se sobre un binario de Windows para Gearman, pero creo que debería ser posible.

 4
Author: ChrisR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-13 23:58:48

Una solución más simple sería tener una sola base de datos con múltiples nodos php conectados. Si utiliza un RDBMS adecuado (mSQL + InnoDB lo hará), puede hacer que una tabla actúe como una cola. Cada trabajador luego extraerá tareas de eso para trabajar y las escribirá de nuevo en la base de datos al completarse, utilizando transacciones y bloqueo para sincronizar. Esto depende un poco del tamaño de los datos de entrada/salida. Si es grande, este puede no ser el mejor esquema.

 3
Author: troelskn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-05 07:00:22

Evitaría sqlite para este tipo de tareas, aunque es una base de datos muy maravillosa para aplicaciones pequeñas, no maneja la concurrencia muy bien, solo tiene una estrategia de bloqueo que es bloquear toda la base de datos y mantenerla bloqueada hasta que se complete una transacción sinlge.

Considere Postgres que tiene concurrencia de fuerza industrial y administración de bloqueos y puede manejar múltiples transacciones simultáneas muy bien.

También esto suena como un trabajo para hacer cola! Si fueras en hte Java world recomendaría una arquitectura basada en JMS para su solución. Hay un proyecto 'dropr' para hacer algo similar en php, pero todo es bastante nuevo, por lo que podría no ser adecuado para su proyecto.

Cualquiera que sea la tecnología que utilice, debe buscar una solución de "libre mercado" donde los hilos de trabajo consuman los "trabajos" disponibles lo más rápido posible, en lugar de una "economía dirigida" donde un proceso central asigna tareas a los trabajadores elegidos.

 3
Author: James Anderson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-15 01:56:51

La configuración de un servidor maestro y varios trabajadores se ve bien en su caso.

En el servidor maestro instalaría MySQL (la versión Percona InnoDB es estable y rápida) en la replicación maestro-maestro para que no tenga un solo punto de falla. El servidor maestro alojará una API que los trabajadores extraerán cada N segundos. El maestro comprobará si hay un trabajo disponible, si es así tiene que marcar que el trabajo ha sido asignado al trabajador X y devolver el entrada apropiada al worker (todo esto vía HTTP). Además, aquí puede almacenar todos los archivos de script de los trabajadores.

En los workers , le sugiero encarecidamente que instale una distribución de Linux. En Linux es más fácil configurar tareas programadas y en general creo que es más apropiado para el trabajo. Con Linux puedes incluso crear una imagen live cd o iso con un trabajador perfectamente configurado e instalarla rápida y fácilmente en todas las máquinas que quieras. A continuación, establecer un trabajo cron que se RSync con el servidor maestro para actualizar / modificar los scripts. De esta manera cambiarás los archivos en un solo lugar (el servidor maestro) y todos los trabajadores obtendrán las actualizaciones.

En esta configuración no le importan las direcciones IP o el número de trabajadores porque los trabajadores se están conectando al maestro, no viceversa.

El trabajo del trabajador es bastante fácil: pida un trabajo a la API, hágalo y devuelva el resultado a través de la API. Aclarar y repetir :-)

 3
Author: Lucacri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-17 04:20:54

En lugar de reinventar la rueda de cola a través de SQL, podría usar un sistema de mensajería como RabbitMQ o ActiveMQ como el núcleo de su sistema. Cada uno de estos sistemas proporciona el protocolo AMQP y tiene colas respaldadas por el disco duro. En el servidor tiene una aplicación que introduce nuevos trabajos en una cola" worker "de acuerdo con su programación y otra que escribe los resultados de una cola" result " en la base de datos (o actúa sobre ella de otra manera).

Todos los trabajadores se conectan a RabbitMQ o ActiveMQ. Sacan el trabajo de la cola de trabajo, hacen el trabajo y ponen la respuesta en otra cola. Después de haber hecho eso, ACK la solicitud de trabajo original para decir "está hecho". Si un trabajador abandona su conexión, el trabajo se restaurará a la cola para que otro trabajador pueda hacerlo.

Todo lo que no sean las colas (descripciones de trabajo, detalles del cliente, trabajo completado) se puede almacenar en la base de datos. Pero cualquier cosa en tiempo real debe ponerse en otro lugar. En mi propio trabajo estoy transmitir datos de uso de energía en vivo y tener muchas personas que visitan la base de datos para sondear es una mala idea. Heescrito sobre datos en vivo en mi sistema .

 2
Author: Tom Leys,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-19 03:06:18

Creo que vas en la dirección correcta con un distribuidor de trabajo maestro y trabajadores. Me gustaría que se comunicaran a través de HTTP.

Elegiría C, C++ o Java como clientes, ya que tienen capacidades para ejecutar scripts (execvp en C, System.Desktop.algo en Java). Jobs podría ser el nombre de un script y argumentos para ese script. Puede hacer que los clientes devuelvan un estado en los trabajos. Si los trabajos no, usted puede reintentar. Puede hacer que los clientes sondeen los trabajos cada minuto (o cada x segundos y hacer que el servidor ordene los trabajos)

PHP funcionaría para el servidor.

MySQL funcionaría bien para la base de datos. Solo haría dos marcas de tiempo: inicio y fin. En el servidor, yo buscaría CUANDO SEGUNDOS = = 0

 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-04 18:43:11