getting start with storm 翻译 第二章 part-1

转载请注明出处:http://blog.csdn.net/lonelytrooper/article/details/9960723

第二章 开始

在本章中,我们会建一个storm工程和我们的第一个storm topology。

 下述假设你安装了至少1.6版本的Java运行时环境(JRE)。我们推荐使用oracle提供的JRE,可以在这里找到http://www.java.com/downloads/

操作模式

在我们开始之前,理解storm的操作模式很重要。有两种方式运行storm。

本地模式

在本地模式中,storm topologies运行在本地机器一个单独的JVM中。由于是最简单的查看所有的topology组件一起工作的模式,这种方式被用来开发,测试和调试。在这种模式下,我们可以调整参数,这使得我们可以看到我们的topology在不同的storm配置环境下是怎么运行的。为了以本地模式运行topologies,我们需要下载storm的开发依赖包,其中包含了我们开发和测试topology所需的所有东西。

当我们建立自己的第一个storm工程的时候我们很快就可以看到是怎么回事了。

在本地模式运行topology与在storm集群中运行它是类似的。然而,确保所有的组件线程安全是重要的,因为当它们被部署到远程模式中时,它们可能运行在不同的JVM中或者在不同的物理机器上,这样的话,它们之间没有直接的交流或者内存共享。

本章的所有示例,我们都以本地模式运行。

远程模式

在远程模式中,我们提交topology到storm集群,该集群由许多进程组成,通常运行在不同的机器上。远程模式不显示调试信息,这也是它被认为是生产模式的原因。然而,在一台单独的开发机器上建立storm集群是可能的,并且它被认为是在部署至生产前的一个好方法,这可以确保在生产环境中运行topology时没有任何问题。

你在第六章中可以了解到更多关于远程模式的内容,我会在附录B里展示怎样安装一个集群。

Hello World Storm

在这个工程中,我们会建立一个简单的topology来为单词计数。我们可以把这个工程

认为是storm topologies的“hello world”。然而,它是一个非常强大的topology,因为

它只需要做一些小的改动便可以扩展到几乎无限规模并且,我们甚至可以用它来做一个统计系统。例如,我们可以修改这个项目来找出Twitter上的话题趋势。

为了建立这个topology,我们将使用一个spout来负责读取单词,第一个bolt来标准化单词,

第二个bolt来为单词计数,正如我们在图2-1中看到的那样。


图2-1 开始topology

你可以在https://github.com/storm-book/examples-ch02-getting_started/zipball/master

下载示例源代码的ZIP文件。

如果你使用git(一个分布式的校正控制及源代码管理工具),你可以在你想

要下载的源代码的目录中运行git clone git@github.com:storm-book/examplesch02-

getting_started.git。

验证Java安装

安装环境的第一步是验证你正在运行的java的版本。打开一个终端窗口,运行命令java –version。我们可以看到如下类似的信息:

 

java -version

java version "1.6.0_26"

Java(TM) SE Runtime Environment(build 1.6.0_26-b03)

Java HotSpot(TM) Server VM (build 20.1-b02,mixed mode)

如果没有,验证下你的java安装。(见http://www.java.com/download/.)

创建工程

为开始这个工程,先建立一个用来存放应用的文件夹(就像对任何的java应用一样)。该文件夹包含工程的源代码。

接着我们需要下载storm的依赖包:一个我们将添加到应用类路径的jar包的集合。你可以用两种方式中的一种做这件事:

﹒下载依赖包,解压,添加到类路径。

﹒使用ApacheMaven

maven是一套软件工程管理的工具。它可以被用来管理软件开发周期中的多个方面,从依赖到发布构建过程。在本书中我们会广泛的使用它。为验证是否已安装了maven,运行命令mvn。如果没有,可以从http://maven.apache.org/download.html下载。尽管使用storm没有必要成为一个maven专家,但是知道maven是怎样工作的基础知识是有帮助的。你可以找到更多信息在Apache Maven的网站(http://maven.apache.org/)。

为了定义工程的结构,我们需要建立一个pom.xml(工程对象模型)文件,该文件描述依赖,包,源码等。我们将使用依赖包及nathanmarz建立的maven库(https://github.com/nathan

marz/)。这些依赖可以在这里找到https://github.com/nathanmarz/storm/wiki/Maven。

storm的maven依赖包引用了在本地模式运行storm所需的所有库函数。

使用这些依赖包,我们可以写一个包含运行topology基本的必要组件的pom.xml文件:

<projectxmlns="http://maven.apache.org/POM/4.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0

http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>storm.book</groupId>

<artifactId>Getting-Started</artifactId>

<version>0.0.1-SNAPSHOT</version>

 

<build>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>2.3.2</version>

<configuration>

<source>1.6</source>

<target>1.6</target>

<compilerVersion>1.6</compilerVersion>

</configuration>

</plugin>

</plugins>

</build>

 

<repositories>

 

<!-- Repository where we can found the storm dependencies -->

<repository>

<id>clojars.org</id>

<url>http://clojars.org/repo</url>

</repository>

</repositories>

 

<dependencies>

 

<!-- Storm Dependency -->

<dependency>

<groupId>storm</groupId>

<artifactId>storm</artifactId>

<version>0.6.0</version>

</dependency>

</dependencies>

</project>

前几行指定了工程的名字和版本。然后我们添加了一个编译器插件,该插件告诉maven我们的代码应该用Java1.6编译。接下来我们定义库(maven支持同一工程的多个库)。Clojars是storm依赖包所在的库。Maven会自动下载本地模式运行storm所需的所有子依赖包。

应用有如下的结构,典型的maven java工程:


Java下的文件夹包含我们的源代码并且我们会将我们的单词文件放到resources文件夹中来处理。

mkdir –p 建立所有所需的父目录。

建立我们第一个Topology

为建立我们第一个topology,我们要创建运行单词计数的所有的类。或许示例的一些部分在目前阶段不是很清晰,我们将在后边的章节中解释它们。

Spout

WordReader spout是实现了IRichSpout接口的类。我们在第四章会看到更多的细节。WordReader负责读文件并且将每行提供给一个bolt。

一个spout发射一个定义的域的列表。这个架构允许你有多种bolt读取相同的spout流,然后这些bolt定义域供其他的bolt消费等等。

示例2-1包含了这个类的完整代码(我们在示例后分析代码的每个部分)。

Example 2-1.src/main/java/spouts/WordReader.java

package spouts;

import java.io.BufferedReader;

import java.io.FileNotFoundException;

importjava.io.FileReader;

import java.util.Map;

import backtype.storm.spout.SpoutOutputCollector;

import backtype.storm.task.TopologyContext;

import backtype.storm.topology.IRichSpout;

import backtype.storm.topology.OutputFieldsDeclarer;

import backtype.storm.tuple.Fields;

import backtype.storm.tuple.Values;

 

public class WordReaderimplementsIRichSpout{

private SpoutOutputCollector collector;

private FileReader fileReader;

private booleancompleted=false;

private TopologyContext context;

public booleanisDistributed(){returnfalse;}

public voidack(Object msgId) {

System.out.println("OK:"+msgId);

}

public voidclose(){}

public voidfail(Object msgId) {

System.out.println("FAIL:"+msgId);

}

/**

* The only thing that the methods will do It is emit each

* file line

*/

public voidnextTuple() {

/**

* The nextuple it is called forever, so if we have beenreaded the file

* we will wait and then return

*/

if(completed){

try {

Thread.sleep(1000);

} catch(InterruptedExceptione) {

//Do nothing

}

return;

}

String str;

//Open the reader

BufferedReader reader =newBufferedReader(fileReader);

try{

//Read all lines

while((str=reader.readLine())!=null){

/**

* By each line emmit a new value with the line as a their

*/

this.collector.emit(newValues(str),str);

}

}catch(Exception e){

throw new RuntimeException("Errorreading tuple",e);

}finally{

completed = true;

                   }

}

/**

* We will create the file and get the collector object

*/

public voidopen(Map conf,TopologyContextcontext,

SpoutOutputCollector collector) {

try {

this.context=context;

this.fileReader=newFileReader(conf.get("wordsFile").toString());

} catch(FileNotFoundExceptione) {

throw new RuntimeException("Errorreading file

["+conf.get("wordFile")+"]");

}

this.collector=collector;

}

/**

* Declare the output field "word"

*/

public voiddeclareOutputFields(OutputFieldsDeclarerdeclarer) {

declarer.declare(newFields("line"));

}       

}

在任何spout中都调用的第一个方法是void open(Map conf, TopologyContext

context, SpoutOutputCollector collector)。方法的参数是TopologyContext,它包含了所有的topology数据;conf对象,它在topology定义的时候被创建;SpoutOutputCollector,它使得我们可以发射将被bolt处理的数据。下面的代码是open方法的实现:

public voidopen(Map conf,TopologyContext context,

SpoutOutputCollector collector) {

try {

this.context=context;

this.fileReader=newFileReader(conf.get("wordsFile").toString());

} catch(FileNotFoundException e) {

throw new RuntimeException("Error reading file ["+conf.get("wordFile")+"]");

}

this.collector=collector;

}

在这个方法中,我们也创建了reader,它负责读文件。接着我们需要实现public void nextTuple(),在这个方法里我们发射将被bolt处理的值。在我们的例子中,这个方法读文件并且每行发射一个值。

public voidnextTuple(){

if(completed){

try {

Thread.sleep(1);

} catch(InterruptedException e) {

//Do nothing

}

return;

}

String str;

BufferedReader reader =newBufferedReader(fileReader);

try{

while((str=reader.readLine())!=null){

this.collector.emit(newValues(str));

}

}catch(Exception e){

throw new RuntimeException("Errorreading tuple",e);

}finally{

completed =true;

}

}

Values是ArrayList的一个实现,其中把list的元素传到了构造方法中。

 

nextTuple()方法在相同的循环中被周期性的调用,正如ack()和fail()方法。当没有工作要做时,必须释放对线程的控制这样其他的方法有机会被调用。所以nextTuple方法的第一行是检查处理是否完成了。如果已经完成,在返回前它会休眠至少一毫秒来降低处理器的负载。如果有工作要做,那么文件的每一行被读取为一个值并且发射。

元组(Tuple)是一个值的命名列表,它可以是任何类型的java对象(只要这个对象是可序列化的)。Storm在缺省的情况下可以序列化常用的类型例如strings,bytearrays,ArrayList,HashMap和HashSet。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值