2010-06-29 12 views
5

Tengo una aplicación, en su forma más simple, lee una gran cantidad de números de una base de datos (unos 15 millones) y envía cada número de una línea a la vez a una url para su procesamiento. Diseñé la aplicación de esta manera:Heavy Asynchronous Processing

  1. exportar a granel los números de teléfono de sql a un archivo de texto utilizando SSIS. Esto es muy rápido y es cuestión de 1 o 2 minutos.
  2. carga los números en una cola de mensajes (utilizo MSMQ en este momento).
  3. Decae los mensajes de una aplicación de línea de comandos y active la solicitud a través de http para algún servicio, como 3 llamadas por número de teléfono y finalmente inicie sesión en una base de datos.

El problema es que todavía tarda en completarse. MSMQ también tiene un límite en el tamaño de los mensajes que puede tomar y ahora tengo que crear varias colas de mensajes. Necesito mucha tolerancia a las fallas, pero no me atrevo a hacer que mi cola de mensajes sea transaccional debido al rendimiento. Estoy pensando en publicar la cola de mensajes (actualmente una cola privada) en el directorio activo para que los procesos puedan dequeue de diferentes sistemas para que esto se complete más rápido. Además, mis procesadores alcanzan el 100% durante la ejecución y lo estoy cambiando para usar un threadpool en este momento. Estoy dispuesto a explorar JMS en este momento si manejará mejor la cola. Hasta ahora, la parte más eficiente de todo el procesamiento es la parte de SSIS.

Me gustaría escuchar un mejor enfoque de diseño, especialmente si ya manejó este tipo de volúmenes. Estoy listo para cambiar a Unix o hacer lisp si maneja mejor esta situación.

Gracias.

+2

15 millones de registros procesados ​​uno a la vez a través de HTTP ** ** le llevará mucho tiempo - no sé cuánto tiempo toma cada solicitud, pero incluso con una latencia de 250 ms para todo el proceso que está probablemente mirando> 1,000 horas de procesamiento (suponiendo una solicitud secuencial). Incluso enviando 10 solicitudes en paralelo y asumiendo que tienen la misma latencia total, tomaría 250 horas procesarlas. Comenzaría por ver si su "url" admite la aceptación de más de un registro a la vez: esa sería la forma más fácil de paralelizar el trabajo para que se complete más rápido. – LBushkin

+1

Cualquiera que sea la solución que encuentre: haga los cálculos antes de encontrar el tiempo que lleva hacerlo y luego multiplique eso por 15,000,000. Debe poder realizar un lote de las solicitudes. –

+0

La URL del lote no está disponible, y sí, hice los cálculos y me pregunto si alguien podría tener un enfoque interesante. – keni

Respuesta

0

No tengo experiencia en MSMQ pero solo una pregunta general. ¿Por qué leer la lista de números enteros en cola al inicio? ¿Por qué no leer un número del archivo de texto, procesarlo y luego leer a continuación? Leer todos los números en el objeto a la vez puede exceder el límite de la RAM y la paginación causará demoras en el intercambio de objetos de un lado a otro entre la RAM y el archivo de la página.

+0

Usar algo como MSMQ le dará una manera de manejar qué números ya ha procesado para que no vuelva a comenzar desde el principio en caso de falla. – kasperjj

+0

Eso significa que cada número se convierte en su propia entrada en MSMQ, esto podría ser absurdo con 15 millones de números. Ignoraría MSMQ y usaría la base de datos para registrar el estado actual de los números procesados. –

+0

Aún sería mejor leer un montón de filas, digamos 1000 filas en lotes de DB, procesarlas y actualizar el estado de las filas una vez que se haya procesado cada fila. La lectura de filas en partes se ahorrará en llamadas repetidas a bases de datos, lo que puede ser costoso en términos de tiempo, mientras que el estado de guardado en BD es mucho más fácil de manejar para la conmutación por recuperación. –

0

Como alternativa, puede exponer el acceso a los números de teléfono a través de un servicio web. En lugar del proceso de lectura de MSMQ, puede solicitar al servicio web un lote de números de teléfono que pueden marcarse como bloqueados en SQL. A continuación, puede llamar al servicio web indicando éxito o error, para que puedan marcarse como completado o sin marcar como bloqueado en SQL. De esta forma, no necesita innecesariamente seleccionar todas las filas y obstruir el sistema, y ​​obtendrá la tolerancia a fallas del SQL en sí mismo.

Además de esto, puede implementar algunas tareas de mantenimiento para desmarcar filas como bloqueadas si no han tenido respuesta en mucho tiempo, y luego ignorar los resultados si la persona que llama original finalmente se comunica con usted. Puede hacerlo marcando las filas con alguna forma de ID de llamada.

Como alternativa, abandone el servicio web y conéctese directamente a la base de datos. De cualquier forma, proporciona tolerancia a fallas, es fácil de implementar, es tan rápido como lo que se obtendrá, y se puede distribuir a través de muchas computadoras de procesamiento.

0

¿Por qué lee todo el lote de la base de datos a la vez? ¿No sería más efectivo leer los números de teléfono en lotes, para que desaparezcan los problemas con las colas?

2

Aquí es una sencilla solución muy pragmática:

Primera dividir archivos su texto en archivos más pequeños, tal vez con algo así como 10.000 entradas en cada archivo. Vamos a llamarlos numbers_x.queue.

Crear una aplicación basada en subprocesos, donde cada hilo procesa los archivos usando los siguientes pasos:

  1. Busque un archivo llamado numbers_x.done si existe encontrar el último número completo en ella.
  2. Si encuentra un archivo .done escanear a través numbers_x.queue para posicionarse en el número después de la última en el archivo .done.
  3. Leer un número del archivo .queue
  4. Haga su Web API llama
  5. Haga su registro
  6. Anexar el número en el fichero de .done
  7. Si el archivo no es .queue al final todavía , ir a 3
  8. Borrar el archivo de cola, entonces el archivo de hecho
  9. Grab otro archivo .queue sin procesar y continúe desde el 1

Si bien este es un enfoque bastante crudo, que es muy fácil de poner en práctica, bastante tolerante a fallos y se puede fácilmente dividir los archivos .queue entre un conjunto de servidores y hacer que trabajen en paralelo.

+0

¿Es esto realmente tan diferente de un enfoque que utiliza una cola de mensajes? Esto parece que quitaría la abstracción de cola de mensajes y volvería a implementar una estructura similar a una cola de trabajo. El servicio web remoto aún sería un cuello de botella. –

+0

Sí, es diferente ya que es una estructura de cola mucho más simple que aprovecha sus requisitos específicos para ofrecer un rendimiento mucho más alto debido al diseño de transmisión io sin la opción de agregar entradas a la cola. Pero sí, el servicio web aún podría ser un cuello de botella. Sin embargo, no tiene que ser (latencia de 100 ms, 32 hilos en paralelo = 13 horas) y no lo menciona en su pregunta, así que elegí centrarme en sus problemas al usar MSMQ. – kasperjj

0

cuál es el objetivo en el uso de 2 aplicaciones separadas + JMS - una aplicación para la carga de los datos y el otro para enviar a la basura durante el uso de JMS a la cola de los números? ¿Son ambas aplicaciones aplicaciones independientes o está la de "lectura" integrada en algún servidor? Y la última pregunta, ¿los números de alguna manera son rastreados que han sido enviados lejos?

Después de todo, en mi opinión, no hay ningún beneficio en el uso de JMS. Solo trae gastos adicionales.

Permite resumir: aplicación que envía los números aparte, a un servidor web para su procesamiento. Supongo que la parte receptora no puede procesar/recibir más números a la vez. Supongo que la base de datos desde la que está cargando los datos es una tienda de "solo lectura" del cliente o más. Supongo que quieres hacer un seguimiento de los números enviados.

Lo que yo haría:

  • de combinación de las dos aplicaciones en una sola
  • crean algunos (posiblemente incorporado) DB para realizar un seguimiento de los números procesados ​​(esto es mejor que mantener algún archivo de forma manual o tenerlo en la memoria - en caso de accidente usted está comenzando desde el beggining; db ha características interesantes que ofrecer)
  • crear el grupo de remitentes que se toman montón de digamos 10 números y enviarlo a algún lugar
  • crear lector de datos que lee los números de lotes (no veo beneficio en re ading all at the beggining, que retrasa el inicio del envío). Esto también es más rastreable a medida que mantiene conjuntos más pequeños de datos. El papel del lector es también hacer un seguimiento de los remitentes de inactividad y alimentarlos con los datos que se leen durante el tiempo en que todos los emisores están trabajando.
  • los remitentes están actualizando la base de datos interna con los números que ya procesados ​​

yo diría, que esto es bastante configurable, así como se pueden modificar las cantidades de números procesados ​​por los remitentes y modificar número de emisores.

Si el ambiente deseado se distribuye más - es posible que tenga más ordenadores - y luego hacerlo de esta manera:

  • Mantenga JMS con uno (o más equivalentes) cola (s) para la alimentación de los emisores; crear cola para notificar a la parte del lector sobre el trabajo terminado (para que las colas de alimentación no se sobrecarguen).
  • Haga que el lector sea parte de los datos, conjuntos de números y lea la cola de notificaciones.
  • Crear base de datos para hacer un seguimiento de los números procesados ​​- hacer que sea compartida por los remitentes o aislada para el lector al enviar 'informes de procesamiento' de los remitentes. Lector que actualiza la base de datos.
Cuestiones relacionadas