Introducción a Spring Data Hadoop

0
7728

Introducción a Spring Data Hadoop

0. Índice de contenidos.


1. Introducción.

Spring dispone de la librería spring-data-hadoop que nos simplifica el desarrollo con Hadoop principalmente a través de una fácil configuración de los elementos necesarios para trabajar con MapReduce y un API sencillo para trabajar con HDFS, Pig, Hive, HBase, etc. Adicionalmente nos proporciona integración con otros proyectos como Spring Integration y Spring Batch proporcionando un entorno completo para crear soluciones Big Data.

En este tutorial vamos a rehacer el Job MapReduce con el API de Hadoop de este tutorial para hacerlo con Spring Data.

Puedes descargarte el código del tutorial desde mi repositorio de github pinchando aquí.

2. Entorno.

El tutorial se ha realizado con el siguiente entorno:

  • Ubuntu 12.04 64 bits
  • Oracle Java SDK 1.6.0_27
  • Apache Hadoop 2.2.0
  • Spring Data 2.0.0 RC2
  • Apache Maven 3.1.1

3. Configuración del proyecto

Lo primero será crear el proyecto, para eso vamos a utilizar un arquetipo de maven:

mvn archetype:generate

...
187: remote -> eu.stratosphere:quickstart-scala (-)
188: remote -> eu.vitaliy:java6se-spring3-archetype (Simple spring 3 archetype)
189: remote -> fr.ybonnel:simpleweb4j-archetype (An archetype for SimpleWeb4j.)
...

De la interminable lista que hay, voy a escoger el 188 que te crea la estructura de un proyecto simple de spring. Rellenamos la información que nos va pidiendo:

Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 380: 188
...
Define value for property 'groupId': : com.autentia.tutoriales
Define value for property 'artifactId': : spring-data-hadoop
Define value for property 'version':  1.0-SNAPSHOT: : 
Define value for property 'package':  com.autentia.tutoriales: : 
Confirm properties configuration:
groupId: com.autentia.tutoriales
artifactId: spring-data-hadoop
version: 1.0-SNAPSHOT
package: com.autentia.tutoriales
 Y: : Y

3.1 pom.xml

Lo que nos crea nos va a servir como punto de partida pero vamos a ir borrando las cosas que no nos hacen falta y añadiendo la configuración necesaria para trabajar con Spring Data, las librerías que habrá que añadir al pom.xml así como el repositorio de Spring ya que vamos a probar la última versión disponible 2.0.0 release candidate:

	
	    ...
	    
			org.springframework.data
			spring-data-hadoop
			2.0.0.RC2
	    
	

	
	    
			spring-milestones
			Spring Milestones
			http://repo.spring.io/milestone
			
			    false
			
	    
	

También vamos a utilizar el plugin appassembler-maven-plugin para generar un shell script para ejecutar nuestro código más fácilmente.

	
		org.codehaus.mojo
		appassembler-maven-plugin
		1.8
		
			
				
					com.autentia.tutoriales.Init
					airQuality
				
			
		
	

3.2 application-context.xml

Para tener el soporte de Spring para trabajar con Hadoop lo primero será configurar la ruta al namenode que tenemos configurada en el ${HADOOP_HOME}/etc/hadoop/core-site.xml. Si aún no tienes instalado Hadoop puedes consultar este tutorial.

En mi caso la configuración es la siguiente:


  
    fs.default.name
    hdfs://localhost:8020
    true


En el fichero application-context.xml de Spring añadimos la siguiente configuración:

Fichero application-context.xml

<?xml version="1.0" encoding="UTF-8"?>

	
	
		fs.default.name=${fs.default.name}
	
	
	

	
		 
		  

Fichero hadoop.properties

fs.default.name=hdfs://localhost:8020
input.path=input
output.path=output

Con esto le estamos diciendo a Spring que nos cree una instancia de tipo singleton de org.apache.hadoop.mapreduce.Job y lo añada a su contexto. Será nuestro Job que ejecute la tarea MapReduce donde no hay que especificarle más que la clase del Mapper y la del Reduce. Spring ya sabe identificar los tipos de entrada y salida del Mapper y el Reducer por lo que nos ahorra un montón de código que no sirve más que para configurar el Job.

4. Job MapReduce.

Las clases del Job MapReduce encargado de procesar el fichero de entrada y generar el resultado son las mismas que las del tutorial de primeros pasos de MapReduce con Hadoop. En este caso se ha separado un poco el código por legibilidad:

  • Mapper

    	package com.autentia.tutoriales;
    
    	import java.io.IOException;
    
    	import org.apache.commons.lang.math.NumberUtils;
    	import org.apache.hadoop.io.DoubleWritable;
    	import org.apache.hadoop.io.Text;
    	import org.apache.hadoop.mapreduce.Mapper;
    
    	public class AirQualityMapper extends Mapper {
    
    		private static final String SEPARATOR = ";";
    
    		public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
    			final String[] values = value.toString().split(SEPARATOR);
    
    			final String co = format(values[1]);
    			final String province = format(values[10]);
    
    			if (NumberUtils.isNumber(co.toString())) {
    				context.write(new Text(province), new DoubleWritable(NumberUtils.toDouble(co)));
    			}
    		}
    
    		private String format(String value) {
    			return value.trim();
    		}
    	}
    	
  • Reducer

    	package com.autentia.tutoriales;
    
    	import java.io.IOException;
    	import java.text.DecimalFormat;
    
    	import org.apache.hadoop.io.DoubleWritable;
    	import org.apache.hadoop.io.Text;
    	import org.apache.hadoop.mapreduce.Reducer;
    
    	public class AirQualityReducer extends Reducer {
    
    		private final DecimalFormat decimalFormat = new DecimalFormat("#.##");
    
    		public void reduce(Text key, Iterable coValues, Context context) throws IOException, InterruptedException {
    			int measures = 0;
    			double totalCo = 0.0f;
    
    			for (DoubleWritable coValue : coValues) {
    				totalCo += coValue.get();
    				measures++;
    			}
    
    			if (measures > 0) {
    				context.write(key, new Text(decimalFormat.format(totalCo / measures)));
    			}
    		}
    	}
    	
  • Clase main

    Es la clase que carga el contexto de Spring.

    	package com.autentia.tutoriales;
    
    	import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    	public class Init {
    		public static void main(String[] args) {
    			new ClassPathXmlApplicationContext("META-INF/spring/application-context.xml");
    		}
    	}
    	

5. Ejecución.

Los pasos para la ejecución del Job son muy sencillos:

  • Paso 1: empaquetar el proyecto

    Para ello ejecutamos el comando que genera el empaquetado del código fuente y a través del plugin appassembler nos generará un ejecutable:

    	mvn clean package appassembler:assemble
    	
  • Paso 2: ejecutar el código

    Una vez generado un shell script bastará con ejecutarlo. Antes habría que subir al HDFS el fichero de entrada:

    	hadoop -copyFromLocal input/calidad_del_aire_cyl_1997_2013.csv input
    	sh target/appassembler/bin/airQuality
    	

Si todo ha ido bien, en el directorio de salida configurado en el hadoop.properties nos habrá dejado el resultado de la ejecución.

6. Conclusiones.

Una vez más la gente de Spring se ha currado una librería para facilitarnos el trabajo a la hora de trabajar con Hadoop eliminándonos la mayoría de la configuración necesaria para montar el Job. Si te resultaba tediosa la configuración y la forma de trabajar con Hadoop, mediante Spring Data este trabajo parecerá un juego de niños.

Puedes descargarte el código del tutorial desde mi repositorio de github pinchando aquí.

Espero que te haya sido de ayuda.

Un saludo.

Juan

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad