Storm模擬分析電話日誌
環境:Storm-1.2.2,ubuntu-16.0.4,Idea2018(Linux版),maven-3.3.9
所有的測試,部署都是在Linux系統上進行。
一、知識點介紹
個人理解為worker中執行程式,程式中執行執行緒,執行緒中執行任務。一個執行緒可以執行多個任務。併發度就等於所有的任務數(Task)之和。
現在用程式碼解釋一下:
TopologyBuilder builder = new TopologyBuilder();
//設定Spout
builder.setSpout("wcspout", new WordCountSpout(),3).setNumTasks(4);
//設定creator-Bolt
builder.setBolt("split-bolt", new SplitBolt(),4).shuffleGrouping("wcspout").setNumTasks(5);
//設定counter-Bolt
builder.setBolt("counter-bolt", new CountBolt(),5).fieldsGrouping("split-bolt", new Fields("word")).setNumTasks(6);
Config conf = new Config();
conf.setNumWorkers(2);
該程式碼開啟了2個worker程式(worker本身不執行Task(任務),它相當於領導,用於產生executor,讓executor去執行任務)。給wcspout分配了3個執行緒4個任務,給split-bolt分配了4個執行緒5個任務,給counter-bolt分配了5個執行緒6個任務。
程式/執行緒/任務都是平均的。因此對於上面的程式碼來說,假如開了1個supervisor,那麼這2個worker就都由這一個supervisor監管,假如開了2個supervisor,那麼每個supervisor管理一個worker。用圖形來表示上述程式碼的任務分配如下:
每一個task執行一個物件例項。。
二、程式碼
1.CallLogSpout類
該類用於模擬產生資料來源
package com.strorm.test;
import org.apache.storm.spout.SpoutOutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.IRichSpout;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Values;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
/**
* @Author zhang
* @Date 18-6-7 下午2:40
* Spout類,負責產生資料流
*/
public class CallLogSpout implements IRichSpout {
//Spout輸出收集器
private SpoutOutputCollector collector;
//是否完成
private boolean completed=false;
//上下文
private TopologyContext context;
//隨機發生器
private Random randomGenerator = new Random();
private Integer idx=0;
public void open(Map map, TopologyContext topologyContext, SpoutOutputCollector spoutOutputCollector) {
this.context=topologyContext;
this.collector=spoutOutputCollector;
}
public void close() {
}
public void activate() {
}
public void deactivate() {
}
/**
* 下一個元組
*/
public void nextTuple() {
if (idx<=1000){
List<String> mobileNumbers=new ArrayList<String>();
mobileNumbers.add("13901645322");
mobileNumbers.add("13805376831");
mobileNumbers.add("13500803713");
mobileNumbers.add("15988321818");
Integer localIndex=0;
while (localIndex++<100 && idx<1000){
//主叫
String caller=mobileNumbers.get(randomGenerator.nextInt(4));
//被叫
String callee=mobileNumbers.get(randomGenerator.nextInt(4));
while (caller==callee){
//主叫與被叫不能相同,重新賦值被叫
callee=mobileNumbers.get(randomGenerator.nextInt(4));
}
//模擬通話時間
Integer callTime=randomGenerator.nextInt(60);
//輸出元組
this.collector.emit(new Values(caller,callee,callTime));
}
}
}
public void ack(Object o) {
}
/**
*
* @param o
*/
public void fail(Object o) {
}
/**
* 定義輸出欄位
* @param outputFieldsDeclarer
*/
public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
//輸出元組中到元素為三個,這也要定義三個欄位
outputFieldsDeclarer.declare(new Fields("from","to","callTime"));
}
public Map<String, Object> getComponentConfiguration() {
return null;
}
}
2.CallLogBolt類
該類用於處理從Spout類傳遞過來的源資料,可以實現多個IRichBolt類進行連續處理。
package com.strorm.test;
import org.apache.storm.task.OutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.IRichBolt;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Tuple;
import org.apache.storm.tuple.Values;
import java.util.Map;
/**
* @Author zhang
* @Date 18-6-7 下午3:19
* 建立Bolt
*/
public class CallLogBolt implements IRichBolt {
private OutputCollector collector;
public void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {
this.collector=outputCollector;
}
public void execute(Tuple tuple) {
//處理通話記錄
String from=tuple.getString(0);
String to=tuple.getString(1);
Integer callTime=tuple.getInteger(2);
collector.emit(new Values(from+" 呼叫 "+to,callTime));
}
public void cleanup() {
}
/**
* 定義輸出欄位
* @param outputFieldsDeclarer
*/
public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
outputFieldsDeclarer.declare(new Fields("call","callTime"));
}
public Map<String, Object> getComponentConfiguration() {
return null;
}
}
3.CallCounterBolt類
該類用於統計之前的Bolt類傳送過來的資料,其功能類似於Hadoop的Reducer。
package com.strorm.test;
import org.apache.storm.task.OutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.IRichBolt;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Tuple;
import java.util.HashMap;
import java.util.Map;
/**
* @Author zhang
* @Date 18-6-7 下午3:29
* 計數器,類似於Reducer
*/
public class CallCounterBolt implements IRichBolt {
Map<String,Integer> counterMap;
OutputCollector collector;
public void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {
this.counterMap=new HashMap<String, Integer>();
collector=outputCollector;
}
public void execute(Tuple tuple) {
String call=tuple.getString(0);
Integer callTime=tuple.getInteger(1);
if (!counterMap.containsKey(call)){
counterMap.put(call,callTime);
}else {
Integer integer=counterMap.get(call)+callTime;
counterMap.put(call,integer);
}
collector.ack(tuple);
}
public void cleanup() {
for (Map.Entry<String,Integer> map : counterMap.entrySet()){
System.out.println(map.getKey()+" :"+map.getValue()+" 分鐘");
}
}
public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
outputFieldsDeclarer.declare(new Fields("call"));
}
public Map<String, Object> getComponentConfiguration() {
return null;
}
}
4.CallLogOutput類
該類用於提交Topology,類似於Hadoop的Job提交。由於Storm不會停止資料流作業,所以在測試環境下要人為停止。這裡的Sleep時間可以根據實際情況設定。如果時間過短,可能看不到輸出結果。
package com.strorm.test;
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.topology.TopologyBuilder;
import org.apache.storm.tuple.Fields;
/**
* @Author zhang
* @Date 18-6-7 下午3:46
*/
public class CallLogOutput {
public static void main(String[] args) throws InterruptedException, InvalidTopologyException, AuthorizationException, AlreadyAliveException {
TopologyBuilder topologyBuilder=new TopologyBuilder();
//設定Spout
topologyBuilder.setSpout("spout",new CallLogSpout());
//設定Bolt
topologyBuilder.setBolt("bolt",new CallLogBolt()).shuffleGrouping("spout");
//設定counterBolt
topologyBuilder.setBolt("counterBolt",new CallCounterBolt()).fieldsGrouping("bolt",new Fields("call"));
Config config=new Config();
config.setDebug(true);
LocalCluster localCluster=new LocalCluster();
localCluster.submitTopology("Log",config,topologyBuilder.createTopology());
Thread.sleep(20000);
localCluster.shutdown();
}
}
5.輸出結果
根據程式碼中的隨機產生4個號碼。再根據排列組合的
可以知道輸出是正確的。
6.叢集部署執行
叢集部署執行需要將localCluster提交改成StormSubmitter.submitTopology提交。並將相關的Module打包成jar包。
以本文的程式碼為例,部署時,執行:
storm jar storm-call-core-1.0-SNAPSHOT.jar com.strorm.test.CallLogOutput
在上圖中,可以看到提交的Topology名字為Log,就是程式碼中設定的Topology名字。
拓撲圖:
可以看到上圖中三個紅色圈中拓撲節點的名字就是程式碼中設定的名字。
然後回到web ui的主頁可以看到Topology已經沒有資料資訊了,表示沒有Topology在執行。
標準的執行格式為:
storm jar jar包名 xxx.類名 [arg1] [arg2] [arg3]...
當在叢集上執行了jar包後,會在某個supervisor的目錄下,產生一個worker.log,這個日誌檔案裡面記錄了輸出結果,但是該檔案一般會非常的大。
原始碼下載:點選下載storm電話日誌分析原始碼
下載原始碼完成後,只需要以匯入maven工程的方式匯入root目錄下的 pom.xml檔案,然後會自動引入所有相關的module。
相關文章
- storm 問題日誌記錄ORM
- 日誌分析-apache日誌分析Apache
- Oracle Redo(重做日誌) 模擬故障和恢復Oracle Redo
- 實時檢視模擬器的日誌輸出
- [日誌分析篇]-利用ELK分析jumpserver日誌-日誌拆分篇Server
- 利用MySQL日誌模擬恢復資料變化軌跡IIMySql
- 模擬線上重做日誌被刪除的情況恢復
- 模擬阻塞會話例項會話
- 玄機-第二章日誌分析-apache日誌分析Apache
- Apche日誌系列(4):日誌分析(轉)
- log4j+kafka+storm+mongodb+mysql 日誌處理KafkaORMMongoDBMySql
- FDOAGENT日誌分析
- crash日誌分析
- awk分析日誌
- pg日誌分析
- 虛擬化網路演進模擬對話
- 家居強電電路模擬程式
- Docker 容器日誌分析Docker
- JAVA GC日誌分析JavaGC
- perl分析apache日誌Apache
- 日誌收集分析-heka
- awstats分析web日誌Web
- mysqldumpslow日誌分析MySql
- LOGMINER日誌分析
- 日誌採集/分析
- ZooKeeper如何模擬會話失效(Session Expired)會話Session
- 日誌分析一例
- mongodb 日誌分析工具mtoolsMongoDB
- IOS 崩潰日誌分析iOS
- 日誌分析如何演變
- CDN日誌實時分析
- ELK日誌分析系統
- net 日誌分析錯誤
- 日誌分析常規操作
- MongoDB 日誌分析工具 mtoolsMongoDB
- 日誌分析工具 Log Parser
- logminer 日誌分析案例
- elk 日誌分析系統