什麼是jstorm
基本概念
元組(tuple)
jstorm 消息傳遞的基本單位,是一個命名的值列表,元組中的字段可以是任何類型的。支持所有的基本類型、字符串和字節數組,也支持自定義的序列化接口對象。
流(stream)
數據之間通過流進行傳遞,是核心抽象。流有元組組成,實質是元組序列。
龍捲(spout)
拓撲中流的來源,即數據的來源。
- 閃電(bolt)
流的處理節點,即接受到spout流出的數據並進行處理。
- 流分組(Stream grouping)
spout和bolt、bolt和bolt之間數據如何分發和接受,通過流分組定義。流分組定義了流/元組如何在bolt任務之間分發。 拓撲(topology)
各組件的消息流動形成邏輯上的拓撲結構,是jstorm中一個實時應用程序。類似於MapReduce 的作業。拓撲與MapReduce的區別在於,後者的作業始終會完成,而拓撲會永遠運行知道他被kill。
工作進程(worker)
- 任務(task)
- 執行器(executor)
- 主空節點和工作節點
集羣有主控節點(MasterNode)和工作節點(Worker Node) ,主控節點只有一個,工作節點有多個。 - nimbus進程和supervisor進程
主控節點運行nimbus進程,類似hadoop的jobTracker,用來在集羣中分發jar,對節點進行任務分配,並檢測主機故障。工作節點運行supervisor進程,監聽主機分配的作業。
==總結:==
jstorm 的各組件關係,可以用一句話來概括:
一個topology 包含多個spout和bolt ,bolt和spout的基本單位是tuple,spout 和bolt、bolt和bolt之間通過stream傳遞數據。數據的傳遞和接受規則通過流分組實現。
如何創建一個簡單的topology
創建一個簡單的topology- 實現spout接口
數據處理的數據來源,接受數據 - 實現bolt接口
從spout中接受數據進行邏輯處理 - 生成topology
畫出拓撲圖,spout、bolt之間的關係
如下是一個簡單的topology定義
# pom文件中引入jstorm依賴
<dependency>
<groupId>com.alibaba.jstorm</groupId>
<artifactId>jstorm-core</artifactId>
<version>2.4.0</version>
<!--本地測試時需要註釋,提交集羣時需要釋放註釋-->
<scope>provided</scope>
</dependency>
# 1. 定義spout
public class SimpleSpout implements IRichSpout {
private static final Logger LOG = LoggerFactory.getLogger(com.hollycrm.hollyvoc.batchexample.SimpleSpout.class);
private Random rand;
private int batchSize = 100;
private SpoutOutputCollector collector;
@Override
public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
rand = new Random();
rand.setSeed(System.currentTimeMillis());
this.collector = collector;
}
@Override
public void close() {
}
@Override
public void activate() {
}
@Override
public void deactivate() {
}
@Override
public void nextTuple() {
for (int i = 0; i < batchSize; i++) {
long value = rand.nextInt(10);
collector.emit("stream-id",new Values(value));
}
}
@Override
public void ack(Object msgId) {
}
@Override
public void fail(Object msgId) {
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declareStream(
"stream-id",
new Fields("value")
);
}
@Override
public Map<String, Object> getComponentConfiguration() {
return null;
}
# 2. 定義bolt
public class SimpleBolt implements IBasicBolt {
public final static String NAME = "simple-bolt";
private static Logger logger = LoggerFactory.getLogger(SimpleBolt.class);
@Override
public void prepare(Map stormConf, TopologyContext context) {
}
@Override
public void execute(Tuple input, BasicOutputCollector collector) {
if("stream-id".equals(input.getSourceStreamId())) {
try {
Long value = input.getLongByField("value");
// todo 對value 邏輯處理
logger.info(" 接受到的值是: " + value);
} catch (Exception e) {
}
}
}
@Override
public void cleanup() {
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
}
@Override
public Map<String, Object> getComponentConfiguration() {
return null;
}
# 3. 構建topology
public class SimpleTopology {
// 拓撲名稱
private static String topologyName = "SimpleTopology";
private static Logger logger = LoggerFactory.getLogger(SimpleTopology.class);
/**
* 定義拓撲
*
* @param topology 拓撲對象
* @param conf 配置
*/
public static void defineTopology(TopologyBuilder topology, Map<String, Object> conf) {
TopologyBuilder topologyBuilder = new TopologyBuilder();
int spoutParallel = JStormUtils.parseInt(conf.get("topology.spout.parallel"), 1);
// 聲明spout
SpoutDeclarer spoutDeclarer = topologyBuilder.setSpout("simple-spout",
new SimpleSpout(), spoutParallel);
int boltParallel = JStormUtils.parseInt(conf.get("topology.bolt.parallel"), 2);
// 聲明bolt
BoltDeclarer bolt = topologyBuilder.setBolt(SimpleBolt.NAME, new SimpleBolt(), boltParallel);
bolt.localOrShuffleGrouping("simple-spout","stream-id");
}
/**
* 配置參數
*/
private static Map conf = new HashMap<String, Object>();
/**
* 本地運行模式
* @param conf 配置
* @throws InterruptedException 異常
*/
private static void runLocalMode(Map<String, Object> conf) throws InterruptedException{
try {
TopologyBuilder builder = new TopologyBuilder();
LocalCluster cluster = new LocalCluster();
SimpleTopology.defineTopology(builder, conf);
logger.info("commit Topology ...");
cluster.submitTopology(topologyName, conf, builder.createTopology());
logger.info("commit Topology finish, sleep 600000");
Thread.sleep(600000);
cluster.killTopology(topologyName);
cluster.shutdown();
}catch (Exception e) {
e.printStackTrace();
}
}
/**
* 遠程運行模式
* @param conf 配置
* @throws AlreadyAliveException
* @throws InvalidTopologyException
*/
private static void runRemoteMode(Map<String, Object> conf) throws AlreadyAliveException, InvalidTopologyException {
TopologyBuilder builder = new TopologyBuilder();
SimpleTopology.defineTopology(builder, conf);
StormSubmitter.submitTopology(topologyName, conf, builder.createTopology());
}
/**
* 加載配置.
* @param arg 配置文件
*/
private static void LoadConf(String arg) {
if (arg.endsWith("yaml")) {
conf = LoadConf.LoadYaml(arg);
} else {
conf = LoadConf.LoadProperty(arg);
}
}
/**
* 加載本地參數.
* @param conf 配置
* @return 返回true說明加載的是本地的參數
*/
private static boolean local_mode(Map conf) {
String mode = (String) conf.get(Config.STORM_CLUSTER_MODE);
if (mode != null) {
if (mode.equals("local")) {
return true;
}
}
return false;
}
public static void main(String[] args) {
// 本地測試
String config = ConfigUtils.class.getResource("/topology-local.yaml").getFile();
// 集羣配置
// if (args.length == 0) {
// logger.error("Please input configuration file");
// System.exit(-1);
// }
// String config = args[0];
// 加載配置文件,判斷是本地模式還是集羣模式
LoadConf(config);
try {
if (local_mode(conf)) {
System.out.println(" loading local ...");
logger.info(" loading local ... ");
runLocalMode(conf);
} else {
runRemoteMode(conf);
}
}catch (InterruptedException e) {
logger.error("InterruptedException ", e);
}
catch (AlreadyAliveException e) {
logger.error("AlreadyAliveException ", e);
e.printStackTrace();
}catch (InvalidTopologyException e) {
logger.error("InvalidTopologyException ", e);
e.printStackTrace();
}
}
提交topology
- 將定義好得代碼打包成jar
- 然後執行以下命令,在部署的jstorm環境中提交jar,上篇jstorm環境搭建中,在hd-23服務器上登錄jstorm用戶,將jar放到用戶目錄下,執行以下命令即可。
#
jstorm jar hollyvoc-data-topology.jar com.hollycrm.hollyvoc.app.KafkaApplication topology-remote.yaml
# hollyvoc-data-topology.jar 是jar包的名稱
# com.hollycrm.hollyvoc.app.KafkaApplication 程序運行的主類
# topology-remote.yaml 配置文件