hadoop-logoMuy buenas,

Esta semana he estado “pegándome” un poco con Hadoop, ¡se acercan bonitos tiempos! y, aunque aún tengo pendiente un par de post sobre HPC, tendrán que esperar por el momento.

Cuando hablamos de Hadoop, también hablamos de Big Data, (¡si, efectivamente, muchos datos y muy grandes !), ambos términos están relacionados. Concretamente, Big data, se refiere a conjuntos de datos que crecen tan enormemente que son difíciles de capturar, almacenar, gestionar, analizar, visualizar y compartir con las herramientas de bases de datos más comunes de hoy día. Teniendo en cuenta esto, existe tres características que definen a Big Data muy bien:

  1. Volumen: Terabytes y Petabytes de información
  2. Velocidad: Clusters dedicados a la ejecución de tareas/jobs y, un algoritmo: MapReduce, también muy utilizado en HPC.
  3. Variedad: Texto, BBDD, redes sociales, etc

Por otro lado, Wikepedia nos dice:

Apache Hadoop es un framework de software que soporta aplicaciones distribuidas bajo una licencia libre. Permite a las aplicaciones trabajar con miles de nodos y petabytes de datos. Hadoop se inspiró en los documentos Google para MapReduce y Google File System (GFS).

Hadoop es un proyecto de alto nivel Apache que está siendo construido y usado por una comunidad global de contribuidores, mediante el lenguaje de programación Java. Yahoo! ha sido el mayor contribuidor al proyecto, y usa Hadoop extensivamente en su negocio.

Y si queremos un poco más de detalle antes de ponernos manos a la obra, nuestro compañero Ibon Landa, nos cuenta más en este post (Big Data, Hadoop y Windwos Azure).

Para comenzar, una vez más contamos con los tutoriales de Microsoft y que por supuesto, no vamos a pasar por alto, si no que los aprovecharemos para profundizar, en concreto, pariremos de este (Hadoop on Windows Azure – Working With Data), donde veremos como procesar un fichero de log de IIS pudiendo explotar toda la información del mismo muy fácilmente, utilizando además, el Storage de Azure. Para ello:

  1. Podemos optar bien por crear un WebRole como nos dice el ejemplo para navegar y obtener el log o, simplemente partir de un fichero de logs IIS cualquiera ya existente.
  2. Creamos un programa de Consola en C#, que será la función “MAP” del algoritmo y cuya finalidad es:
    • Obtener las urls (que comiencen por “http://” o terminen por “.aspx” o “.html”).
  3. Creamos un programa de Consola en C#, función “REDUCE” y cuya finalidad será:
    • A partir de la información proporcionada por el MAP, obtener el número de veces que aparece cada url.
    • Ordenar la lista descendentemente

Importante: Cuando trabajamos con Hadoop On Azure con C# (Streaming), siempre tenemos que incluir la siguiente línea de código al comienzo de nuestra aplicación consola MAP y REDUCE:

if (args.Length > 0)
{
Console.SetIn(new StreamReader(args[0]));
}

Una vez tengamos nuestros ficheros “Map.exe” y “Reduce.exe” y un fichero de logs de IIS cualquiera procedemos a cargar los datos en Hadoop:

1) Desde la consola Interactiva de Javascript subimos los ficheros a HDFS (Hadoop File System).

js> fs.put()

image

Donde en, Destination, introduciremos el valor “/example/apps/map.exe”.  Es importante tener en cuenta el comienzo de este valor, puesto que no es lo mismo “/example/…” que “./example/…”. En este último caso, al acceder al fichero tendremos que indicar la ruta completa desde el root, es decir, “/users/juanluelguerre/examples/apps/map.exe”.

De la misma manera lo haremos para Reduce.exe.

2) Utilizando “Azure Storage Explorer”, conectamos con el Storage de Azure y subir el fichero de log de IIS a un container denominado “fivetopuri”. Adicionlamente crear otro container para los resultados, denominado “fivetopuriresults”

image

3) Configurar Hadoop para que pueda trabajar con el Storage de Azure.

image imageimage

4) Creamos un Job con la siguiente información:

  • JAR File.
    • Descargar el “.jar” para Streaming (hadoop-streaming.jar).  La release es la “v1.0.3”, aunque la “v2.0.1-alpha”, al menos para este ejemplo también funciona perfectamente.
  • Parámetros
    • Parametro 1: -files "hdfs:///example/apps/map.exe,hdfs:///example/apps/reduce.exe"
    • Parametro 2: -input "asv://fivetopuri/iislog.txt" -output "asv://fivetopuriresults/results.txt"
    • Parametro 3: -mapper "map.exe" -reducer "reduce.exe"
  • El comando final queda como sigue:

Hadoop jar hadoop-streaming-1.0.3.jar -files "hdfs:///example/apps/map.exe,hdfs:///example/apps/reduce.exe" -input "asv://fivetopuri/iislog.txt" -output "asv://fivetopuriresults/results.txt" -mapper "map.exe" -reducer "reduce.exe"

Nota: ASV: indica una ruta del Storage de Azure.

5) Ejecutamos el Job y esperamos.

Si hemos seguido el ejemplo tal cual, probablemente encontraremos algunos errores:

  • Error “Failed Map Tasks exceed allowed limit. Failed Count: 1”
  • o incluso que el Job tarde en responder (que se haya quedado “colgado”), en cuyo caso es posible que queramos “matarlo”. Para ello:

1) En primer lugar identificaremos el  JobId, que se encontrará “…in progress” o “RUNNING”:

image

  • Una vez hemos el “JobId”, nos conectamos al cluster mediante Remote Desktop y abrimos la consola de Hadoop (“Hadoop command Shell”):

imageimage

  • Ejecutamos la siguiente línea de comando, obteniendo un resultado indicando que el Job ha sido eliminado.
c:\apps\dist>hadoop job -kill job_201210061842_0019
Killed job job_201210061842_0019

Después de muchos intentos continuaremos el problema hasta que lo resolvamos.  En nuestro ejemplo tendremos que hacer una modificación, es decir, cambiar el caracter “\t” por cualquier otro,  por ejemplo “”, de manera que la función “Map” queda así:

private const char SEPARATOR = '-';

Console.WriteLine(string.Format("{0}{1}{2}", uri, SEPARATOR, counters[uri]));

Y la función “Reduce” así:

private const char SEPARATOR = '-';
...

string line;
while ((line = Console.ReadLine()) != null)
{
// parse the uri and the number of request
var values = line.Split(SEPARATOR);
string uri = values[0];
int numOfRequests = int.Parse(values[1]);

// save the max number of requests for each uri in UriCounters
if (!UriCounters.ContainsKey(uri))
UriCounters.Add(uri, numOfRequests);
else if (UriCounters[uri] < numOfRequests)
UriCounters[uri] = numOfRequests;
}

6) Volvemos al punto 1) y eliminamos el contenido del container “fivetopuriresult” del  storage de Azure.

7) Ejecutamos nuevamente el Job. Y ahora sí:

12/10/07 17:16:18 INFO mapred.FileInputFormat: Total input paths to process : 1

12/10/07 17:16:19 INFO streaming.StreamJob: getLocalDirs(): [/hdfs/mapred/local]

12/10/07 17:16:19 INFO streaming.StreamJob: Running job: job_201210071446_0030

12/10/07 17:16:19 INFO streaming.StreamJob: To kill this job, run:

12/10/07 17:16:19 INFO streaming.StreamJob: c:\Apps\dist/bin/hadoop job -Dmapred.job.tracker=10.26.110.33:9010 -kill job_201210071446_0030

12/10/07 17:16:19 INFO streaming.StreamJob: Tracking URL: http://10.26.110.33:50030/jobdetails.jsp?jobid=job_201210071446_0030

12/10/07 17:16:20 INFO streaming.StreamJob: map 0% reduce 0%

12/10/07 17:16:47 INFO streaming.StreamJob: map 50% reduce 0%

12/10/07 17:16:50 INFO streaming.StreamJob: map 100% reduce 0%

12/10/07 17:16:56 INFO streaming.StreamJob: map 100% reduce 33%

12/10/07 17:17:08 INFO streaming.StreamJob: map 100% reduce 100%

12/10/07 17:17:21 INFO streaming.StreamJob: Job complete: job_201210071446_0030

12/10/07 17:17:21 INFO streaming.StreamJob: Output: asv://fivetopuriresults/results.txt

image

A partir de aquí sólo nos queda complicar las funciones “Map” y “Reduce” tanto como queramos para explotar mucha más información.

En los siguientes post veremos como manejar toda esta información con “Hive” (Datawarehouse de Hadoop) y “Exel”.

Saludos @WorkingRoom

Juanlu, ElGuerre