Desarrollo de aplicaciones

con Hadoop

Tomas Delvechio
@tdelvechio
tomasdelvechio17@gmail.com

Indice

  1. Instalación de Hadoop
  2. Uso básico de HDFS
  3. Desarrollo en Hadoop
  4. Hadoop Streaming

El objetivo es poder realizar una instalación local y desarrollar algunas aplicaciones MapReduce, haciendo un uso simple del Sistema de Archivos Distribuido que proporciona Hadoop.

Objetivo

Instalación de Hadoop

  • Single Node
  • Multi Node

Instalar Hadoop implica instalar sus 3 componentes principales:

  • Hadoop common
  • HDFS
  • MapReduce

En todos los nodos. La diferencia entre nodo master y nodo slave se establece en la configuración e inicialización de los servicios

Instalación Single Node

Sistema Operativo Linux

No hay procesamiento distribuido

Instalación para desarrollo

Linux: Ubuntu 14.04

Hadoop 2.7 / Hadoop 2.4 / Hadoop 2.5

OpenJDK 6 / 7

Instalación vía Docker

Instalación vía Docker

  1. Instalar Docker
     
  2. Descargar imagen
     
  3. Iniciar Contenedor
     
  4. Ejecutar Test

Instalación vía Docker

  1. Instalar Docker

 

https://docs.docker.com/engine/installation/

Comprobar si el cliente esta instalado:

 

$ docker --version
Docker version 1.12.1

Instalación vía Docker

2. Descargar imagen

 

 

$ docker pull sequenceiq/hadoop-docker:2.7.1

Instalación vía Docker

3. Iniciar Contenedor

docker run -it sequenceiq/hadoop-docker:2.7.1 /etc/bootstrap.sh -bash

4. Ejecutar Test
(Dentro del contenedor)

cd $HADOOP_PREFIX
bin/hadoop jar \
> share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.1.jar \
> grep input output 'dfs[a-z.]+'
bin/hdfs dfs -cat output/*

Instalación vía Docker

mkdir ~/cursohadoop
docker run -v ~/cursohadoop:/cursohadoop \
-w /cursohadoop -it sequenceiq/hadoop-docker:2.7.1 \
/etc/bootstrap.sh -bash

Ejecución de contenedor para trabajar en el curso.

Agregar los ejecutables de hadoop al path del sistema

export PATH=$PATH:/usr/local/hadoop/bin

Web UI Hadoop

Desde el navegador web de nuestro equipo

 

 

ResourceManager: <ip_container>:8088

 

NameNode: <ip_container>:50070

ResourceManager Web UI

NameNode Web UI

Uso basico de HDFS

Listar archivos y directorios

 

Crear directorios en HDFS

 

 

Copiar archivos locales al HDFS

 

Descarga de archivos de ejemplo: https://goo.gl/ngB0aP

hdfs dfs -ls /
hdfs dfs -mkdir /user/hduser
hdfs dfs -mkdir /user/hduser/test
hdfs dfs -ls /user/hduser/
$ ls
pg135.txt  pg1661.txt  pg4300.txt
$ hdfs dfs -copyFromLocal pg135.txt pg1661.txt pg4300.txt /user/hduser/test
$ hdfs dfs -ls /user/hduser/test/
Found 3 items
-rw-r--r--   1 hduser supergroup    3322651 2014-09-08 13:21 /user/hduser/test/pg135.txt
-rw-r--r--   1 hduser supergroup     594933 2014-09-08 13:21 /user/hduser/test/pg1661.txt
-rw-r--r--   1 hduser supergroup    1573150 2014-09-08 13:21 /user/hduser/test/pg4300.txt

Uso básico de HDFS (Sigue)

Ver contenido de un archivo en el FS

 

 

Descargar archivos desde HDFS

 

hdfs dfs -cat /user/hduser/test/pg1661.txt
hdfs dfs -copyToLocal /user/hduser/test/pg1661.txt pg1661_bis.txt
diff pg1661_bis.txt pg1661.txt

Programar en Hadoop: WordCount

Aplicación MapReduce que computa la frecuencia de cada termino de la entrada

MapReduce WordCount DataFlow

WordCount: Version Java (Mapper)

public static class Map extends Mapper<LongWritable, Text, Text, IntWritable> {

    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();
    
    @Override
    public void map(LongWritable key, Text value, Context context) 
        throws IOException, InterruptedException {
        
        String line = value.toString();
        StringTokenizer tokenizer = new StringTokenizer(line);
        
        while (tokenizer.hasMoreTokens()) {
            word.set(tokenizer.nextToken());
            context.write(word, one);
        }
    }
}

WordCount: Version Java (Reducer)

public static class Reduce extends Reducer<Text, IntWritable, Text, IntWritable> {
    
    @Override
    public void reduce(Text key, Iterable<IntWritable> values, Context context)
        throws IOException, InterruptedException {
        
        int sum = 0;
        for (IntWritable val : values) {
            sum += val.get();
        }
        context.write(key, new IntWritable(sum));
    }
}

WordCount: Version Java (Main class)

public class WordCount {

    public static void main(String[] args) throws Exception {
        
        Configuration conf = new Configuration();
        
        Job job = Job.getInstance(conf);
        
        job.setJarByClass(WordCount.class);
        
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
        
        job.setMapperClass(Map.class);
        job.setReducerClass(Reduce.class);
        
        job.setInputFormatClass(TextInputFormat.class);
        job.setOutputFormatClass(TextOutputFormat.class);
        
        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));
        
        job.waitForCompletion(true);
    }
}

WordCount: Version Java (API import)

package wordCount;

import java.io.IOException;
import java.util.*;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.conf.*;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapreduce.*;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;

Ejemplo completo

Pasos para correr el programa

  1. Descargar el código en un archivo de nombre WordCount.java
  2. Crear una carpeta de nombre wordCount: mkdir wordCount
  3. Compilar el código: javac -classpath `hadoop classpath` -d wordCount WordCount.java
  4. Armar paquete: jar -cvf wordcount.jar -C wordCount/ .
  5. Ejecutar en Hadoop: 
    
    ​hadoop jar wordcount.jar wordCount.WordCount /user/hduser/test/* /user/hduser/out-wc

Hadoop Streaming

Map / Reduce con otros lenguajes

 

Ejemplo: Contar la cantidad de palabras de un archivo

 

hadoop jar hadoop-streaming-2.7.1.jar \
    -input /user/hduser/test/* \
    -output /user/hduser/out-wc-sh \
    -mapper /bin/cat \
    -reducer /usr/bin/wc

 

La librería hadoop-streaming se puede localizar en el path

/usr/local/hadoop/share/hadoop/tools/lib/hadoop-streaming-2.7.1.jar

Hadoop Streaming

El flujo de datos es similar al visto para Hadoop

 

 

 

 

 

 

 

Sin embargo, Map y Reduce ejecutan los scripts que se pasan por parametro. El I/O se hace por Entrada y Salida Estandar.

 

Ejercicio con Streaming

Elija el lenguaje que crea conveniente (Python, Ruby, Perl, Bash), y porgráme un Mapper y un Reducer para que realicen un WordCount.

Recordar que el I/O del script Map y Reduce es via Entrada/Salida Estandar.

 

Por ejemplo, en python, un script que haga print "Hola mundo" imprime el string por la salida estandar.

Trabajo Practico

Tomando el ejemplo de WordCount, piense alguna modificación para crear un programa que realice otra tarea.

Implementarlo en Hadoop

Ejemplos:

Contador de Bigramas

Indice Invertido Booleano

 

Ayuda: Muchas veces programas de estructura similar ofrecen respuestas diferente en función de las decisiones de que es clave o valor en map y reduce.