From 959dd959953d8df0edd291d57687a4e2736e285f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=BD=97=E7=A5=A5?= <1366971433@qq.com>
Date: Wed, 17 Apr 2019 11:31:20 +0800
Subject: [PATCH] =?UTF-8?q?storm=E6=95=B4=E5=90=88redis=E4=BB=A3=E7=A0=81?=
=?UTF-8?q?=E5=AE=9E=E7=8E=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
code/Storm/storm-redis-integration/pom.xml | 57 ++++++++++++++++++
.../com/heibaiying/CustomRedisCountApp.java | 45 ++++++++++++++
.../com/heibaiying/WordCountToRedisApp.java | 57 ++++++++++++++++++
.../com/heibaiying/component/CountBolt.java | 44 ++++++++++++++
.../heibaiying/component/DataSourceSpout.java | 49 +++++++++++++++
.../component/RedisCountStoreBolt.java | 52 ++++++++++++++++
.../com/heibaiying/component/SplitBolt.java | 35 +++++++++++
.../component/WordCountStoreMapper.java | 30 +++++++++
.../src/main/resources/assembly.xml | 25 ++++++++
.../Storm单机版本环境搭建.md | 2 +-
pictures/store-redis-manager.png | Bin 0 -> 19112 bytes
11 files changed, 395 insertions(+), 1 deletion(-)
create mode 100644 code/Storm/storm-redis-integration/pom.xml
create mode 100644 code/Storm/storm-redis-integration/src/main/java/com/heibaiying/CustomRedisCountApp.java
create mode 100644 code/Storm/storm-redis-integration/src/main/java/com/heibaiying/WordCountToRedisApp.java
create mode 100644 code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/CountBolt.java
create mode 100644 code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/DataSourceSpout.java
create mode 100644 code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/RedisCountStoreBolt.java
create mode 100644 code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/SplitBolt.java
create mode 100644 code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/WordCountStoreMapper.java
create mode 100644 code/Storm/storm-redis-integration/src/main/resources/assembly.xml
create mode 100644 pictures/store-redis-manager.png
diff --git a/code/Storm/storm-redis-integration/pom.xml b/code/Storm/storm-redis-integration/pom.xml
new file mode 100644
index 0000000..0b641e6
--- /dev/null
+++ b/code/Storm/storm-redis-integration/pom.xml
@@ -0,0 +1,57 @@
+
+
+ 4.0.0
+
+ com.heibaiying
+ storm-redis-integration
+ 1.0
+
+
+ UTF-8
+ 1.2.0
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 8
+ 8
+
+
+
+ maven-assembly-plugin
+
+
+ src/main/resources/assembly.xml
+
+
+
+ com.heibaiying.wordcount.ClusterWordCountApp
+
+
+
+
+
+
+
+
+
+
+ org.apache.storm
+ storm-core
+ ${storm.version}
+
+
+ org.apache.storm
+ storm-redis
+ ${storm.version}
+
+
+
+
+
\ No newline at end of file
diff --git a/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/CustomRedisCountApp.java b/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/CustomRedisCountApp.java
new file mode 100644
index 0000000..c3986b5
--- /dev/null
+++ b/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/CustomRedisCountApp.java
@@ -0,0 +1,45 @@
+package com.heibaiying;
+
+import com.heibaiying.component.*;
+import org.apache.storm.Config;
+import org.apache.storm.LocalCluster;
+import org.apache.storm.StormSubmitter;
+import org.apache.storm.generated.AlreadyAliveException;
+import org.apache.storm.generated.AuthorizationException;
+import org.apache.storm.generated.InvalidTopologyException;
+import org.apache.storm.redis.bolt.RedisStoreBolt;
+import org.apache.storm.redis.common.config.JedisPoolConfig;
+import org.apache.storm.redis.common.mapper.RedisStoreMapper;
+import org.apache.storm.topology.TopologyBuilder;
+
+public class CustomRedisCountApp {
+
+ private static final String REDIS_HOST = "192.168.200.226";
+ private static final int REDIS_PORT = 6379;
+
+ public static void main(String[] args) {
+ TopologyBuilder builder = new TopologyBuilder();
+ builder.setSpout("dataSourceSpout", new DataSourceSpout());
+ // split
+ builder.setBolt("splitBolt", new SplitBolt()).shuffleGrouping("dataSourceSpout");
+ // save to redis and count
+ JedisPoolConfig poolConfig = new JedisPoolConfig.Builder()
+ .setHost(REDIS_HOST).setPort(REDIS_PORT).build();
+ RedisStoreMapper storeMapper = new WordCountStoreMapper();
+ RedisCountStoreBolt countStoreBolt = new RedisCountStoreBolt(poolConfig, storeMapper);
+ builder.setBolt("storeBolt", countStoreBolt).shuffleGrouping("splitBolt");
+
+ // 如果外部传参cluster则代表线上环境启动否则代表本地启动
+ if (args.length > 0 && args[0].equals("cluster")) {
+ try {
+ StormSubmitter.submitTopology("ClusterCustomRedisCountApp", new Config(), builder.createTopology());
+ } catch (AlreadyAliveException | InvalidTopologyException | AuthorizationException e) {
+ e.printStackTrace();
+ }
+ } else {
+ LocalCluster cluster = new LocalCluster();
+ cluster.submitTopology("LocalCustomRedisCountApp",
+ new Config(), builder.createTopology());
+ }
+ }
+}
diff --git a/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/WordCountToRedisApp.java b/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/WordCountToRedisApp.java
new file mode 100644
index 0000000..170ca40
--- /dev/null
+++ b/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/WordCountToRedisApp.java
@@ -0,0 +1,57 @@
+package com.heibaiying;
+
+import com.heibaiying.component.CountBolt;
+import com.heibaiying.component.DataSourceSpout;
+import com.heibaiying.component.SplitBolt;
+import com.heibaiying.component.WordCountStoreMapper;
+import org.apache.storm.Config;
+import org.apache.storm.LocalCluster;
+import org.apache.storm.StormSubmitter;
+import org.apache.storm.generated.AlreadyAliveException;
+import org.apache.storm.generated.AuthorizationException;
+import org.apache.storm.generated.InvalidTopologyException;
+import org.apache.storm.redis.bolt.RedisStoreBolt;
+import org.apache.storm.redis.common.config.JedisPoolConfig;
+import org.apache.storm.redis.common.mapper.RedisStoreMapper;
+import org.apache.storm.topology.TopologyBuilder;
+
+/**
+ * 进行词频统计 并将统计结果存储到Redis中
+ *
+ * 编译打包: mvn clean assembly:assembly -Dmaven.test.skip=true
+ * 提交Topology到集群: storm jar /usr/appjar/storm-redis-integration-1.0-jar-with-dependencies.jar com.heibaiying.WordCountToRedisApp cluster
+ * 停止Topology: storm kill ClusterWordCountApp -w 3
+ */
+public class WordCountToRedisApp {
+
+ private static final String REDIS_HOST = "192.168.200.226";
+ private static final int REDIS_PORT = 6379;
+
+ public static void main(String[] args) {
+ TopologyBuilder builder = new TopologyBuilder();
+ builder.setSpout("dataSourceSpout", new DataSourceSpout());
+ // split
+ builder.setBolt("splitBolt", new SplitBolt()).shuffleGrouping("dataSourceSpout");
+ // count
+ builder.setBolt("countBolt", new CountBolt()).shuffleGrouping("splitBolt");
+ // save to redis
+ JedisPoolConfig poolConfig = new JedisPoolConfig.Builder()
+ .setHost(REDIS_HOST).setPort(REDIS_PORT).build();
+ RedisStoreMapper storeMapper = new WordCountStoreMapper();
+ RedisStoreBolt storeBolt = new RedisStoreBolt(poolConfig, storeMapper);
+ builder.setBolt("storeBolt", storeBolt).shuffleGrouping("countBolt");
+
+ // 如果外部传参cluster则代表线上环境启动否则代表本地启动
+ if (args.length > 0 && args[0].equals("cluster")) {
+ try {
+ StormSubmitter.submitTopology("ClusterWordCountToRedisApp", new Config(), builder.createTopology());
+ } catch (AlreadyAliveException | InvalidTopologyException | AuthorizationException e) {
+ e.printStackTrace();
+ }
+ } else {
+ LocalCluster cluster = new LocalCluster();
+ cluster.submitTopology("LocalWordCountToRedisApp",
+ new Config(), builder.createTopology());
+ }
+ }
+}
diff --git a/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/CountBolt.java b/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/CountBolt.java
new file mode 100644
index 0000000..2884315
--- /dev/null
+++ b/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/CountBolt.java
@@ -0,0 +1,44 @@
+package com.heibaiying.component;
+
+import org.apache.storm.task.OutputCollector;
+import org.apache.storm.task.TopologyContext;
+import org.apache.storm.topology.OutputFieldsDeclarer;
+import org.apache.storm.topology.base.BaseRichBolt;
+import org.apache.storm.tuple.Fields;
+import org.apache.storm.tuple.Tuple;
+import org.apache.storm.tuple.Values;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class CountBolt extends BaseRichBolt {
+
+ private Map counts = new HashMap<>();
+
+ private OutputCollector collector;
+
+
+ @Override
+ public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
+ this.collector=collector;
+ }
+
+ @Override
+ public void execute(Tuple input) {
+ String word = input.getStringByField("word");
+ Integer count = counts.get(word);
+ if (count == null) {
+ count = 0;
+ }
+ count++;
+ counts.put(word, count);
+ // 输出
+ collector.emit(new Values(word, String.valueOf(count)));
+
+ }
+
+ @Override
+ public void declareOutputFields(OutputFieldsDeclarer declarer) {
+ declarer.declare(new Fields("word", "count"));
+ }
+}
diff --git a/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/DataSourceSpout.java b/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/DataSourceSpout.java
new file mode 100644
index 0000000..c4a351f
--- /dev/null
+++ b/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/DataSourceSpout.java
@@ -0,0 +1,49 @@
+package com.heibaiying.component;
+
+import org.apache.storm.shade.org.apache.commons.lang.StringUtils;
+import org.apache.storm.spout.SpoutOutputCollector;
+import org.apache.storm.task.TopologyContext;
+import org.apache.storm.topology.OutputFieldsDeclarer;
+import org.apache.storm.topology.base.BaseRichSpout;
+import org.apache.storm.tuple.Fields;
+import org.apache.storm.tuple.Values;
+import org.apache.storm.utils.Utils;
+
+import java.util.*;
+
+public class DataSourceSpout extends BaseRichSpout {
+
+ private List list = Arrays.asList("Spark", "Hadoop", "HBase", "Storm", "Flink", "Hive");
+
+ private SpoutOutputCollector spoutOutputCollector;
+
+ @Override
+ public void open(Map map, TopologyContext topologyContext, SpoutOutputCollector spoutOutputCollector) {
+ this.spoutOutputCollector = spoutOutputCollector;
+ }
+
+ @Override
+ public void nextTuple() {
+ // 模拟产生数据
+ String lineData = productData();
+ spoutOutputCollector.emit(new Values(lineData));
+ Utils.sleep(1000);
+ }
+
+ @Override
+ public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
+ outputFieldsDeclarer.declare(new Fields("line"));
+ }
+
+
+ /**
+ * 模拟数据
+ */
+ private String productData() {
+ Collections.shuffle(list);
+ Random random = new Random();
+ int endIndex = random.nextInt(list.size()) % (list.size()) + 1;
+ return StringUtils.join(list.toArray(), "\t", 0, endIndex);
+ }
+
+}
diff --git a/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/RedisCountStoreBolt.java b/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/RedisCountStoreBolt.java
new file mode 100644
index 0000000..9a5cfd1
--- /dev/null
+++ b/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/RedisCountStoreBolt.java
@@ -0,0 +1,52 @@
+package com.heibaiying.component;
+
+import org.apache.storm.redis.bolt.AbstractRedisBolt;
+import org.apache.storm.redis.common.config.JedisPoolConfig;
+import org.apache.storm.redis.common.mapper.RedisDataTypeDescription;
+import org.apache.storm.redis.common.mapper.RedisStoreMapper;
+import org.apache.storm.topology.OutputFieldsDeclarer;
+import org.apache.storm.tuple.Tuple;
+import redis.clients.jedis.JedisCommands;
+
+public class RedisCountStoreBolt extends AbstractRedisBolt {
+
+ private final RedisStoreMapper storeMapper;
+ private final RedisDataTypeDescription.RedisDataType dataType;
+ private final String additionalKey;
+
+ public RedisCountStoreBolt(JedisPoolConfig config, RedisStoreMapper storeMapper) {
+ super(config);
+ this.storeMapper = storeMapper;
+ RedisDataTypeDescription dataTypeDescription = storeMapper.getDataTypeDescription();
+ this.dataType = dataTypeDescription.getDataType();
+ this.additionalKey = dataTypeDescription.getAdditionalKey();
+ }
+
+ @Override
+ protected void process(Tuple tuple) {
+ String key = storeMapper.getKeyFromTuple(tuple);
+ String value = storeMapper.getValueFromTuple(tuple);
+
+ JedisCommands jedisCommand = null;
+ try {
+ jedisCommand = getInstance();
+ if (dataType == RedisDataTypeDescription.RedisDataType.HASH) {
+ jedisCommand.hincrBy(additionalKey, key, Long.valueOf(value));
+ } else {
+ throw new IllegalArgumentException("Cannot process such data type for Count: " + dataType);
+ }
+
+ collector.ack(tuple);
+ } catch (Exception e) {
+ this.collector.reportError(e);
+ this.collector.fail(tuple);
+ } finally {
+ returnInstance(jedisCommand);
+ }
+ }
+
+ @Override
+ public void declareOutputFields(OutputFieldsDeclarer declarer) {
+
+ }
+}
\ No newline at end of file
diff --git a/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/SplitBolt.java b/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/SplitBolt.java
new file mode 100644
index 0000000..d92ca07
--- /dev/null
+++ b/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/SplitBolt.java
@@ -0,0 +1,35 @@
+package com.heibaiying.component;
+
+import org.apache.storm.task.OutputCollector;
+import org.apache.storm.task.TopologyContext;
+import org.apache.storm.topology.OutputFieldsDeclarer;
+import org.apache.storm.topology.base.BaseRichBolt;
+import org.apache.storm.tuple.Fields;
+import org.apache.storm.tuple.Tuple;
+import org.apache.storm.tuple.Values;
+
+import java.util.Map;
+
+public class SplitBolt extends BaseRichBolt {
+
+ private OutputCollector collector;
+
+ @Override
+ public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
+ this.collector = collector;
+ }
+
+ @Override
+ public void execute(Tuple input) {
+ String line = input.getStringByField("line");
+ String[] words = line.split("\t");
+ for (String word : words) {
+ collector.emit(new Values(word, String.valueOf(1)));
+ }
+ }
+
+ @Override
+ public void declareOutputFields(OutputFieldsDeclarer declarer) {
+ declarer.declare(new Fields("word", "count"));
+ }
+}
diff --git a/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/WordCountStoreMapper.java b/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/WordCountStoreMapper.java
new file mode 100644
index 0000000..21e4ab3
--- /dev/null
+++ b/code/Storm/storm-redis-integration/src/main/java/com/heibaiying/component/WordCountStoreMapper.java
@@ -0,0 +1,30 @@
+package com.heibaiying.component;
+
+import org.apache.storm.redis.common.mapper.RedisDataTypeDescription;
+import org.apache.storm.redis.common.mapper.RedisStoreMapper;
+import org.apache.storm.tuple.ITuple;
+
+public class WordCountStoreMapper implements RedisStoreMapper {
+ private RedisDataTypeDescription description;
+ private final String hashKey = "wordCount";
+
+ public WordCountStoreMapper() {
+ description = new RedisDataTypeDescription(
+ RedisDataTypeDescription.RedisDataType.HASH, hashKey);
+ }
+
+ @Override
+ public RedisDataTypeDescription getDataTypeDescription() {
+ return description;
+ }
+
+ @Override
+ public String getKeyFromTuple(ITuple tuple) {
+ return tuple.getStringByField("word");
+ }
+
+ @Override
+ public String getValueFromTuple(ITuple tuple) {
+ return tuple.getStringByField("count");
+ }
+}
diff --git a/code/Storm/storm-redis-integration/src/main/resources/assembly.xml b/code/Storm/storm-redis-integration/src/main/resources/assembly.xml
new file mode 100644
index 0000000..3c38fe4
--- /dev/null
+++ b/code/Storm/storm-redis-integration/src/main/resources/assembly.xml
@@ -0,0 +1,25 @@
+
+
+ jar-with-dependencies
+
+
+
+ jar
+
+
+ false
+
+
+ /
+ true
+ true
+ runtime
+
+
+ org.apache.storm:storm-core
+
+
+
+
\ No newline at end of file
diff --git a/notes/installation/Storm单机版本环境搭建.md b/notes/installation/Storm单机版本环境搭建.md
index 33fd993..579b3e2 100644
--- a/notes/installation/Storm单机版本环境搭建.md
+++ b/notes/installation/Storm单机版本环境搭建.md
@@ -58,7 +58,7 @@ export PATH=$STORM_HOME/bin:$PATH
### 4.启动相关进程
-因为要启动多个进程,所以统一采用后台进程的方式启动,采用后台启动时需要进入到`$STORM_HOME/bin`目录下,命令如下:
+因为要启动多个进程,所以统一采用后台进程的方式启动,采用后台启动时需要进入到`${STORM_HOME}/bin`目录下,命令如下:
```shell
# 启动zookeeper
diff --git a/pictures/store-redis-manager.png b/pictures/store-redis-manager.png
new file mode 100644
index 0000000000000000000000000000000000000000..66f8a2e8d8752713fba1612c4bac81382040993d
GIT binary patch
literal 19112
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
literal 0
HcmV?d00001