2. Desarrollo con Storm
● Recordemos que los componentes de Storm se pueden definir en cualquier
lenguaje de programación
○ Java
○ Ruby
○ Python
○ Javascript
○ Perl
○ ...
3. Topología simple
TopologyBuilder builder = new TopologyBuilder();
builder.setSpout(“words”, new TestWordSpout(), 10);
builder.setBolt(“exclaim1”, new ExclamationBolt(), 3)
.shuffleGrouping(“words”);
Builder.setBolt(“exclaim2”, new ExclamationBolt(), 2)
.shuffleGrouping(“exclaim1”);
Una topología con 1 Spout y 2 Bolts. El Spout emite palabras y los
Bolts añaden “!!!” al final.
Los métodos set() reciben como parámetro un id de tipo String, un objeto que
contiene la lógica de procesado y el nivel de paralelismo del nodo. El último
parámetro indica el número de hilos que se ejecutan en ese componente.
El objeto de procesado implementa la interfaz IRichSpout para los Spouts e
IRichBolt para los bolts.
4. Topología simple
TopologyBuilder builder = new TopologyBuilder();
builder.setSpout(“words”, new TestWordSpout(), 10);
builder.setBolt(“exclaim1”, new ExclamationBolt(), 3)
.shuffleGrouping(“words”);
Builder.setBolt(“exclaim2”, new ExclamationBolt(), 2)
.shuffleGrouping(“exclaim1”);
setBolt devuelve un objeto InputDeclarer que se utiliza para definir las entradas en
el bolt. Indicamos que “exclaim1” quiere leer todas las tuplas de “words” utilizando
shuffle grouping y que “exclaim2” quiere leer todas las tuplas de “exclaim1”.
“ShuffleGrouping” indica que las tuplas se distributen de forma
uniformemente aleatoria entre las entrada-salida.
5. El método importante a implementar es nextTuple().
public void nextTuple() {
// hacemos lo que sea
Utils.sleep(100);
final String[] words = new String[]{“bigData”, “ebd”, “utad”};
final Random rand = new Random();
final String word = words[rand.nextInt(words.length)];
_collector.emit(new Values(word));
}
nextTuple() es invocado de forma periódica en el mismo bucle que los métodos
ack() y fail(). Libera el control del hilo cuando no hay trabajo y permite que se
ejecuten los otros métodos.
Spout
6. Tiene los siguientes métodos:
public void prepare(Map conf, TopologyContext ctx, OutputCollector c){
_collector = c;
}
Proporciona al bolt un OutputCollector que se utiliza para emitir las
tuplas de este Bolt. Las tuplas se pueden emitir en cualquier parte del
bolt. Es llamado antes de que el bolt empiece a procesar tuplas.
public void execute(Tuple tuple) {
_collector.emit(tuple, new Values(tuple.getString(0) + “!!!”));
_collector.ack(tuple);
}
Procesa una tupla de las entradas del Bolt. En el ejemplo le añade la
cadena “!!!” al string. Si el bolt está subscrito a multiples fuentes de
entrada, se puede determinar el origen con el método
Tuple#getSourceComponen
Bolt
7. public void cleanup(){}
Este método es invocado cuando se va a apagar el bolt y debería
limpiar ordenadamente los recursos abiertos.
public void declareOutputFields(OutputFieldsDeclarer declarer){
declarer.declare(new Fields(“word”));
}
Este método indica que el bolt emite una tupla con el campo “word”.
Declara el esquema de salida del bolt.
Public Map getComponentConfiguration() {}
Permite configurar aspectos de como se ejecuta el componente.
Bolt
Introducción
8. La forma más sencilla de crear bolts es extender la clase BaseRichBolt:
public static class ExclamationBolt extends BaseRichBolt {
OutputCollector Mycollector;
public void prepare(Map conf, TopologyContext ctx, OutputCollector collector)
{
Mycollector = collector;
}
public void execute(Tuple tuple) {
Mycollector.emit(tuple, new Values(tuple.getSting(0)+”!!!”));
Mycollector.ack(tuple);
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields(“word”));
}
}
Bolt
10. public class HolaMundoSpout extends BaseRichSpout {
private static final long serialVersionUID = 1L;
private SpoutOutputCollector collector;
private int referenceRandom;
private static final int MAX_RANDOM = 10;
public HolaMundoSpout() {
final Random rand = new Random();
referenceRandom = rand.nextInt(MAX_RANDOM);
}
@Override
public void nextTuple() {
Utils.sleep(100);
final Random rand = new Random();
int instanceRandom = rand.nextInt(MAX_RANDOM);
if (instanceRandom == referenceRandom) {
collector.emit(new Values("Hola Mundo"));
} else {
collector.emit(new Values("Otro Mundo Aleatorio"));
}
}
@Override
public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
this.collector = collector;
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("sentence"));
}
}
Hola mundo: Spout
El método Open() inicializa el objeto SpoutOutputCollector.
El Spout va a invocar de forma repetida el método nextTuple().
El método declareOutputFields() indica el contenido de las tuplas
enviadas con emit() en el método nextTuple().
11. Esta clase consume las tuplas producidas e implementa la lógica necesaria.
La creamos dentro del mismo paquete storm.ebd y que herede
de la clase BaseRichBolt. Declaramos una variable miembre privada y
proporcionamos la siguiente implementación para el método execute( ) que realiza
la mayor parte del trabajo.
public void execute(Tuple input) {
String test = input.getStringByField("sentence");
if("Hola Mundo".equals(test)){
myCount++;
System.out.println("Encontrado Hola Mundo!. Contador:" + Integer.toString(myCount));
}
}
Hola mundo: Bolt
12. public class HolaMundoTopology {
public static void main(String[] args) {
TopologyBuilder builder = new TopologyBuilder();
builder.setSpout("randomHolaMundo", new HolaMundoSpout(), 10);
builder.setBolt("HolaMundoBolt", new HolaMundoBolt(), 2).shuffleGrouping("randomHolaMundo");
Config conf = new Config();
conf.setDebug(true);
if(args != null && args.length > 0) {
conf.setNumWorkers(3);
try {
StormSubmitter.submitTopology(args[0], conf, builder.createTopology());
} catch (AlreadyAliveException e) {
e.printStackTrace();
} catch (InvalidTopologyException e) {
e.printStackTrace();
}
} else {
LocalCluster cluster = new LocalCluster();
cluster.submitTopology("test", conf, builder.createTopology());
Utils.sleep(10000);
cluster.killTopology("test");
cluster.shutdown();
}
}
}
Hola mundo: Topology
Ahora creamos nuestra primera Topology donde
unimos los Spouts y Bolts.
13. Hola mundo: Ejecucion
El HolaMundoSpout genera un número aleatorio en su constructor y luego en el
método nextTuple() genera números aleatorios y los compara con el que se ha
generado en el constructor. El método nextTuple() emite una sentencia entre
dos posibles: "Hola Mundo", "Otro Mundo Aleatorio" dependiendo de si el
número aleatorio coincide con el generado en el constructor o no.
El bolt simplemente cuenta las apariciones de la frase “Hola Mundo” y muestra
los incrementos
secuenciales
● Desde consola:
mvn compile exec:java-Dexec.classpathScope=compile -
Dexec.mainClass=storm.ebd.HolaMundoTopology
● Se puede empaquetar para enviar al cluster
mvn package