Recuerda que puedes descargarte algunos de los ejemplos en la pestaña de Código Fuente

miércoles, 10 de julio de 2013

Técnicas de Debugging y Logging

Debugging

Depurar los programas MapReduce es muy complicado, ya que cada instancia de un Mapper se ejecuta en una tarea diferente y quizás en máquinas diferentes, así que adjuntar una técnica de debug en el proceso no es tarea fácil.

El problema es que con cantidades tan grandes de datos puede haber una entrada inesperada o errónea y es un evento que hay que tener en cuenta y controlar.
Porque piénsalo de esta forma, estamos realizando un proyecto de Big Data, eso quiere decir que estamos tratando tales cantidades de datos que los procesos pueden tardar horas o incluso días, imaginemos que a mitad de ese proceso que tarda días hay una entrada de un dato inesperado y el programa falla por no haber tomado ninguna medida.
La conclusión es que al desarrollador sólo le queda tomar una serie de estrategias para evitar este tipo errores:
  • Código defensivo: siempre suponer que un dato puede ser incorrecto o esperar que las cosas vayan mal. Habría que añadir control de excepciones o código que controle los posibles fallos.
  • Empieza un desarrollo pequeño y ve agrandándolo poco a poco
  • Escribe pruebas unitarias, utilizando, por ejemplo, MRunit.
  • Prueba primero en local con cantidades reducidas de datos, luego pasa a modo pseudodistribuído (asegurándote que el entorno es similar al del clúster) y finalmente prueba en todo el clúster.
  • Utiliza Counters, por ejemplo, para conocer el número de entradas inválidas.

Para hacer pruebas en local no se usa HDFS, se usa el sistema de ficheros local y sólo se ejecuta un proceso llamado LocalJobRunner.


Logging

Como logging lo más efectivo es usar librerías como el log4java, ya que éste se puede configurar en niveles y desactivarlo en situaciones de producción.

Como buenas prácticas nunca se debería usar println como estrategia de loggin cuando hacemos nuestras primeras pruebas, ya que posteriormente deberíamos borrarlo en todo el código. Si dejáramos estas líneas y pasáramos el código al clúster en modo producción, podría afectar considerablemente a los tiempos de ejecución, piensa que son procesos que necesitamos que sean lo más rápidos posibles y el realizar un println supone un consumo de tiempo ejecutando el comando y realizando la escritura.
En el clúster deben estar desactivadas todas las escrituras de logging innecesarias (no perjudica el rendimiento el hacer loggin en los métodos setup y cleanup).







5 comentarios:

  1. Hola, me gusta mucho tu blog. Me está ayudando mucho, auque estoy bastante verde todavía. Últimamente estoy desesperado porque no sé cómo ejecutar dos jobs. Bueno, ejecutarlos no es el problema, sino que el segundo job tiene que recoger los datos generados con el primer job en el archivo part-r-00000 y no lo consigo. ¿Tienes alguna entrada en el blog que explique cómo hacerlo? Lo he intentado con el paso de parámetros a través de la configuración y ni por esas.

    ResponderEliminar
  2. Hola, gracias por tu comentario.

    Lo que me dices es que tienes configurados dos jobs en el mismo driver y quieres que la entrada del job 2 coja la salida del job 1, lo único que tienes que hacer es poner el mismo valor. Es decir:
    FileInputFormat.setInputPaths(job1, new Path(args[0]));
    FileOutputFormat.setOutputPath(job1, new Path(args[1]));

    FileInputFormat.setInputPaths(job2, new Path(args[1]));
    FileOutputFormat.setOutputPath(job2, new Path(args[2]));

    Espero que te sirva de ayuda.

    Un saludo

    ResponderEliminar
  3. Muchísimas gracias por tu respuesta.

    No exactamente. No me he explicado nada bien. Tengo dos clases, cada una con su job, y una clase que se encarga de lanzar las dos clases anteriores. Lo hice así para poder probar cada job independientemente. Los dos jobs tienen el mismo fichero de entrada, pero además el segundo job necesita los datos generados por el primero en el archivo part-r-00000. Según lo entiendo, he creado el método setup() en el Mapper del segundo job, donde extraería la info del archivo y la utilizo posteriormente. Pero no lo consigo, me muestra el mensaje "Wrong FS: [ruta] expected file:///".

    Entonces, según me comentas, ¿debo añadir una tercera línea en mi pestaña de argumentos del proyecto para la salida final?:

    hdfs://localhost/user/cloudera/ficheroentrada
    hdfs://localhost/user/cloudera/carpetasalidayentrada2
    ¿hdfs://localhost/user/cloudera/carpetasalidafinal?

    Muchas gracias por tu tiempo.

    Un saludo

    ResponderEliminar
  4. Este comentario ha sido eliminado por un administrador del blog.

    ResponderEliminar
  5. Este comentario ha sido eliminado por un administrador del blog.

    ResponderEliminar

Gracias por dejar vuestras sugerencias, dudas, críticas o comentarios en general