Storm學習筆記總結
Storm概述
離線計算是什么
離線計算:批量獲取數(shù)據、批量傳輸數(shù)據、周期性批量計算數(shù)據、數(shù)據展示
代表技術:Sqoop批量導入數(shù)據、HDFS批量存儲數(shù)據、MapReduce批量計算數(shù)據、Hive批量計算數(shù)據
流式計算是什么
流式計算:數(shù)據實時產生、數(shù)據實時傳輸、數(shù)據實時計算、實時展示
代表技術:Flume實時獲取數(shù)據、Kafka實時數(shù)據存儲、Storm/JStorm實時數(shù)據計算、Redis實時結果緩存、持久化存儲(mysql)。
離線計算與實時計算最大的區(qū)別:實時收集、實時計算、實時展示
Storm是什么
Storm是一個分布式計算框架,主要使用Clojure與Java語言編寫,最初是由Nathan Marz帶領Backtype公司團隊創(chuàng)建,在Backtype公司被Twitter公司收購后進行開源。最初的版本是在2011年9月17日發(fā)行,版本號0.5.0。
2013年9月,Apache基金會開始接管并孵化Storm項目。Apache Storm是在Eclipse Public License下進行開發(fā)的,它提供給大多數(shù)企業(yè)使用。經過1年多時間,2014年9月,Storm項目成為Apache的頂級項目。目前,Storm的最新版本1.1.0。
Storm是一個免費開源的分布式實時計算系統(tǒng)。Storm能輕松可靠地處理無界的數(shù)據流,就像Hadoop對數(shù)據進行批處理;
Storm與Hadoop的區(qū)別
- Storm用于實時計算,Hadoop用于離線計算。
- Storm處理的數(shù)據保存在內存中,源源不斷;Hadoop處理的數(shù)據保存在文件系統(tǒng)中,一批一批處理。
- Storm的數(shù)據通過網絡傳輸進來;Hadoop的數(shù)據保存在磁盤中。
- Storm與Hadoop的編程模型相似
Storm | hadoop | |
---|---|---|
角色 | Nimbus | JobTracker |
Supervisor | TaskTracker | |
Worker | Child | |
應用名稱 | Topology | Job |
編程接口 | Spout/Bolt | Mapper/Reducer |
hadoop的相關名稱
- Job:任務名稱
- JobTracker:項目經理(JobTracker對應于NameNode;JobTracker是一個master服務,軟件啟動之后JobTracker接收Job,負責調度Job的每一個子任務task運行于TaskTracker上,并監(jiān)控它們,如果發(fā)現(xiàn)有失敗的task就重新運行它。)
- TaskTracker:開發(fā)組長(TaskTracker對應于DataNode;TaskTracker是運行在多個節(jié)點上的slaver服務。TaskTracker主動與JobTracker通信,接收作業(yè),并負責直接執(zhí)行每一個任務。)
- Child:負責開發(fā)的人員
- Mapper/Reduce:開發(fā)人員中的兩種角色,一種是服務器開發(fā)、一種是客戶端開發(fā)
storm相關名稱
- Topology:任務名稱
- Nimbus:項目經理
- Supervisor:開組長
- Worker:開人員
- Spout/Bolt:開人員中的兩種角色,一種是服務器開發(fā)、一種是客戶端開發(fā)
Storm應用場景
Storm用來實時計算源源不斷產生的數(shù)據,如同流水線生產,Storm能用到很多場景中,包括:實時分析、在線機器學習、連續(xù)計算等。
- 推薦系統(tǒng):實時推薦,根據下單或加入購物車推薦相關商品
- 金融系統(tǒng):實時分析股票信息數(shù)據
- 預警系統(tǒng):根據實時采集數(shù)據,判斷是否到了預警閾值。
- 網站統(tǒng)計:實時銷量、流量統(tǒng)計,如淘寶雙11效果圖
Sotrm特點
-
適用場景廣泛
:Storm可以適用實時處理消息、更新數(shù)據庫、持續(xù)計算等場景。 -
可伸縮性高
:Storm的可伸縮性可以讓Storm每秒處理的消息量達到很高。擴展一個實時計算任務,你所需要做的就是加機器并且提高這個計算任務的并行度。Storm使用Zookeeper來協(xié)調機器內的各種配置使得Storm的集群可以很容易的擴展。 -
保證無數(shù)據丟失
:Storm保證所有的數(shù)據都被處理。 -
異常健壯
:Storm集群非常容易管理,輪流重啟節(jié)點不影響應用。 -
容錯性好
:在消息處理過程中出現(xiàn)異常,Storm會進行重試。
Storm基礎理論
Storm編程模型
元組(Tuple)
元組(Tuple),是消息傳遞的基本單元,是一個命名的值列表,元組中的字段可以是任何類型的對象。Storm使用元組作為其數(shù)據模型,元組支持所有的基本類型、字符串和字節(jié)數(shù)組作為字段值,只要實現(xiàn)類型的序列化接口就可以使用該類型的對象。元組本來應該是一個key-value的Map,但是由于各個組件間傳遞的元組的字段名稱已經事先定義好,所以只要按序把元組填入各個value即可,所以元組是一個value的List。
流(Stream)
流是Storm的核心抽象,是一個無界的元組系列,源源不斷傳遞的元組就組成了流,在分布式環(huán)境中并行地進行創(chuàng)建和處理
水龍頭(Spout)
Spout是拓撲的流的來源,是一個拓撲中產生源數(shù)據流的組件。通常情況下,Spout會從外部數(shù)據源中讀取數(shù)據,然后轉換為拓撲內部的源數(shù)據。
- Spout可以是可靠的,也可以是不可靠的。如果Storm處理元組失敗,可靠的Spout能夠重新發(fā)射,而不可靠的Spout就盡快忘記發(fā)出的元組。
- Spout可以發(fā)出超過一個流。
- Spout的主要方法是nextTuple()。NextTuple()會發(fā)出一個新的Tuple到拓撲,如果沒有新的元組發(fā)出,則簡單返回。
- Spout的其他方法是ack()和fail()。當Storm檢測到一個元組從Spout發(fā)出時,ack()和fail()會被調用,要么成功完成通過拓撲,要么未能完成。Ack()和fail()僅被可靠的Spout調用。IRichSpout是Spout必須實現(xiàn)的接口。
轉接頭(Bolt)
在拓撲中所有處理都在Bolt中完成,Bolt是流的處理節(jié)點,從一個拓撲接收數(shù)據,然后執(zhí)行進行處理的組件。Bolt可以完成過濾、業(yè)務處理、連接運算、連接與訪問數(shù)據庫等任何操作。
- Bolt是一個被動的角色,七接口中有一個execute()方法,在接收到消息后會調用此方法,用戶可以在其中執(zhí)行自己希望的操作。
- Bolt可以完成簡單的流的轉換,而完成復雜的流的轉換通常需要多個步驟,因此需要多個Bolt。
- Bolt可以發(fā)出超過一個的流。
拓撲(Topology)
拓撲(Topology)是Storm中運行的一個實時應用程序,因為各個組件間的消息流動而形成邏輯上的拓撲結構。
把實時應用程序的運行邏輯打成jar包后提交到Storm的拓撲(Topology)。Storm的拓撲類似于MapReduce的作業(yè)(Job)。其主要的區(qū)別是,MapReduce的作業(yè)最終會完成,而一個拓撲永遠都在運行直到它被殺死。一個拓撲是一個圖的Spout和Bolt的連接流分組。
Storm核心組件
nimbus是整個集群的控管核心,負責topology的提交、運行狀態(tài)監(jiān)控、任務重新分配等工作。
zk就是一個管理者,監(jiān)控者。
總體描述:nimbus下命令(分配任務),zk監(jiān)督執(zhí)行(心跳監(jiān)控,worker、supurvisor的心跳都歸它管),supervisor領旨(下載代碼),招募人馬(創(chuàng)建worker和線程等),worker、executor就給我干活!task就是具體要干的活。
主控節(jié)點與工作節(jié)點
Storm集群中有兩類節(jié)點:主控節(jié)點(Master Node)和工作節(jié)點(Worker Node)。其中,主控節(jié)點只有一個,而工作節(jié)點可以有多個。
Nimbus進程與Supervisor進程
主控節(jié)點運行一個稱為Nimbus的守護進程類似于Hadoop的JobTracker。Nimbus負責在集群中分發(fā)代碼,對節(jié)點分配任務,并監(jiān)視主機故障。
每個工作節(jié)點運行一個稱為Supervisor的守護進程。Supervisor監(jiān)聽其主機上已經分配的主機的作業(yè),啟動和停止Nimbus已經分配的工作進程。
流分組(Stream grouping)
流分組,是拓撲定義中的一部分,為每個Bolt指定應該接收哪個流作為輸入。流分組定義了流/元組如何在Bolt的任務之間進行分發(fā)。Storm內置了8種流分組方式。
工作進程(Worker)
Worker是Spout/Bolt中運行具體處理邏輯的進程。一個worker就是一個進程,進程里面包含一個或多個線程。
執(zhí)行器(Executor)
一個線程就是一個executor,一個線程會處理一個或多個任務。
任務(Task)
一個任務就是一個task。
實時計算常用架構圖
后臺系統(tǒng) -->Flume集群-->Kafka集群-->Storm集群-->Redis集群
- Flume獲取數(shù)據。
- Kafka臨時保存數(shù)據。
- Strom計算數(shù)據。
- Redis是個內存數(shù)據庫,用來保存數(shù)據。
Storm集群搭建
環(huán)境準備
jar包下載
安裝集群步驟:http://storm.apache.org/releases/1.1.2/Setting-up-a-Storm-cluster.html
虛擬機準備
- 準備3臺虛擬機
- 配置ip地址
1.在終端命令窗口中輸入
[root@hadoop101 /]#vim /etc/udev/rules.d/70-persistent-net.rules
刪除eth0該行;將eth1修改為eth0,同時復制物理ip地址
2.修改IP地址
[root@hadoop101 /]#vim /etc/sysconfig/network-scripts/ifcfg-eth0
需要修改的內容有5項:
IPADDR=192.168.1.101
GATEWAY=192.168.1.2
ONBOOT=yes
BOOTPROTO=static
DNS1=192.168.1.2
:wq 保存退出
3.執(zhí)行service network restart
4.如果報錯,reboot,重啟虛擬機
- 配置主機名稱
- 3臺主機分別關閉防火墻
[root@hadoop102 luo]# chkconfig iptables off
[root@hadoop103 luo]# chkconfig iptables off
[root@hadoop104 luo]# chkconfig iptables off
安裝Jdk
卸載現(xiàn)有jdk
- 查詢是否安裝java軟件:
rpm -qa|grep java
- 如果安裝的版本低于1.7,卸載該jdk:
rpm -e 軟件包
用filezilla工具將jdk、Hadoop-2.7.2.tar.gz導入到opt目錄下面的software文件夾下面
在linux系統(tǒng)下的opt目錄中查看軟件包是否導入成功
[root@hadoop101opt]# cd software/
[root@hadoop101software]# ls
jdk-7u79-linux-x64.gz hadoop-2.7.2.tar.gz
解壓jdk到/opt/module目錄下
tar -zxf jdk-7u79-linux-x64.gz -C /opt/module/
配置jdk環(huán)境變量
1.先獲取jdk路徑:
[root@hadoop101 jdk1.7.0_79]# pwd /opt/module/jdk1.7.0_79
2.打開/etc/profile文件:
[root@hadoop101 jdk1.7.0_79]# vi /etc/profile
在profie文件末尾添加jdk路徑:
##JAVA_HOME
export JAVA_HOME=/opt/module/jdk1.7.0_79
export PATH=$PATH:$JAVA_HOME/bin
3.保存后退出:
:wq
4.讓修改后的文件生效:
[root@hadoop101 jdk1.7.0_79]# source /etc/profile
5.重啟(如果java –version可以用就不用重啟):
[root@hadoop101 jdk1.7.0_79]# sync
[root@hadoop101 jdk1.7.0_79]# reboot
6.測試jdk安裝成功
[root@hadoop101 jdk1.7.0_79]# java -version
java version "1.7.0_79"
安裝Zookeeper
集群規(guī)劃
在hadoop102、hadoop103和hadoop104三個節(jié)點上部署Zookeeper
解壓安裝
解壓zookeeper安裝包到/opt/module/目錄下l
[luo@hadoop102 software]$ tar -zxvf zookeeper-3.4.10.tar.gz -C /opt/module/
在/opt/module/zookeeper-3.4.10/這個目錄下創(chuàng)建zkDatae
mkdir -p zkData
重命名/opt/module/zookeeper-3.4.10/conf這個目錄下的zoo_sample.cfg為zoo.cfg
mv zoo_sample.cfg zoo.cfg
配置zoo.cfg文件
具體配置
dataDir=/opt/module/zookeeper-3.4.10/zkData
增加如下配置
#######################cluster##########################
server.2=hadoop102:2888:3888
server.3=hadoop103:2888:3888
server.4=hadoop104:2888:3888
配置參數(shù)說明
Server.A=B:C:D
A是一個數(shù)字,表示這個是第幾號服務器;
B是這個服務器的ip地址;
C是這個服務器與集群中的Leader服務器交換信息的端口;
D是萬一集群中的Leader服務器掛了,需要一個端口來重新進行選舉,
選出一個新的Leader,而這個端口就是用來執(zhí)行選舉時服務器相互通信的端口
集群模式下配置一個文件myid,這個文件在dataDir目錄下,這個文件里面有一個數(shù)據就是A的值,Zookeeper啟動時讀取此文件,拿到里面的數(shù)據與zoo.cfg里面的配置信息比較從而判斷到底是哪個server。
集群操作
在/opt/module/zookeeper-3.4.10/zkData目錄下創(chuàng)建一個myid的文件
touch myid
添加myid文件,注意一定要在linux里面創(chuàng)建,在notepad++里面很可能亂碼
編輯myid文件
vi myid
在文件中添加與server對應的編號:如2
拷貝配置好的zookeeper到其他機器上
scp -r zookeeper-3.4.10/ root@hadoop103.luo.com:/opt/app/
scp -r zookeeper-3.4.10/ root@hadoop104.luo.com:/opt/app/
并分別修改myid文件中內容為3、4
分別啟動zookeeper
[root@hadoop102 zookeeper-3.4.10]# bin/zkServer.sh start
[root@hadoop103 zookeeper-3.4.10]# bin/zkServer.sh start
[root@hadoop104 zookeeper-3.4.10]# bin/zkServer.sh start
查看狀態(tài)
[root@hadoop102 zookeeper-3.4.10]# bin/zkServer.sh status
JMX enabled by default
Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode: follower
[root@hadoop103 zookeeper-3.4.10]# bin/zkServer.sh status
JMX enabled by default
Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode: leader
[root@hadoop104 zookeeper-3.4.5]# bin/zkServer.sh status
JMX enabled by default
Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode: follower
Storm集群部署
配置集群
- 拷貝jar包到hadoop102的/opt/software目錄下
- 解壓jar包到/opt/module目錄下:
[luo@hadoop102 software]$ tar -zxvf apache-storm-1.1.0.tar.gz -C /opt/module/
- 修改解壓后的apache-storm-1.1.0.tar.gz文件名稱為storm:
[luo@hadoop102 module]$ mv apache-storm-1.1.0/ storm
- 在/opt/module/storm/目錄下創(chuàng)建data文件夾:
[luo@hadoop102 storm]$ mkdir data
- 修改配置文件
[luo@hadoop102 conf]$ pwd /opt/module/storm/conf
[luo@hadoop102 conf]$ vi storm.yaml
# 設置Zookeeper的主機名稱
storm.zookeeper.servers:
- "hadoop102"
- "hadoop103"
- "hadoop104"
# 設置主節(jié)點的主機名稱
nimbus.seeds: ["hadoop102"]
# 設置Storm的數(shù)據存儲路徑
storm.local.dir: "/opt/module/storm/data"
# 設置Worker的端口號
supervisor.slots.ports:
- 6700
- 6701
- 6702
- 6703
- 配置環(huán)境變量
[root@hadoop102 storm]# vi /etc/profile #STORM_HOME
export STORM_HOME=/opt/module/storm
export PATH=$PATH:$STORM_HOME/bin
[root@hadoop102 storm]# source /etc/profile
分發(fā)配置好的Storm安裝包:
[luo@hadoop102 storm]$ xsync storm/
-
啟動集群
- 后臺啟動nimbus
[luo@hadoop102 storm]$ bin/storm nimbus & [luo@hadoop103 storm]$ bin/storm nimbus & [luo@hadoop104 storm]$ bin/storm nimbus &
- 后臺啟動supervisor
[luo@hadoop102 storm]$ bin/storm supervisor & [luo@hadoop103 storm]$ bin/storm supervisor & [luo@hadoop104 storm]$ bin/storm supervisor &
- 啟動Storm ui
[luo@hadoop102 storm]$ bin/storm ui
通過瀏覽器查看集群狀態(tài):http://hadoop102:8080/index.html
Storm日志信息查看
查看nimbus的日志信息
在nimbus的服務器上
cd /opt/module/storm/logs
tail -100f /opt/module/storm/logs/nimbus.log
查看ui運行日志信息
在ui的服務器上,一般和nimbus一個服務器
cd /opt/module/storm/logs
tail -100f /opt/module/storm/logs/ui.log
查看supervisor運行日志信息
在supervisor服務上
cd /opt/module/storm/logs
tail -100f /opt/module/storm/logs/supervisor.log
查看supervisor上worker運行日志信息
在supervisor服務上
cd /opt/module/storm/logs
tail -100f /opt/module/storm/logs/worker-6702.log
logviewer,可以在web頁面點擊相應的端口號即可查看日志
分別在supervisor節(jié)點上執(zhí)行:
[luo@hadoop102 storm]$ bin/storm logviewer &
[luo@hadoop103 storm]$ bin/storm logviewer &
[luo@hadoop104 storm]$ bin/storm logviewer &
Storm命令行操作
- nimbus:啟動nimbus守護進程:
storm nimbus
- supervisor:啟動supervisor守護進程:
storm supervisor
- ui:啟動UI守護進程:
storm ui
- list:列出正在運行的拓撲及其狀態(tài):
storm list
- logviewer:Logviewer提供一個web接口查看Storm日志文件:
storm logviewer
- jar:storm jar 【jar路徑】 【拓撲包名.拓撲類名】 【拓撲名稱】
- kill:殺死名為Topology-name的拓撲:
storm kill topology-name [-w wait-time-secs]-w:等待多久后殺死拓撲
- active:激活指定的拓撲spout:
storm activate topology-name
- deactivate:禁用指定的拓撲Spout:
storm deactivate topology-name
- help:打印一條幫助消息或者可用命令的列表:
storm help
和storm help <command>
常用API
API簡介
Component組件
基本接口
- IComponent接口
- ISpout接口
- IRichSpout接口
- IStateSpout接口
- IRichStateSpout接口
- IBolt接口
- IRichBolt接口
- IBasicBolt接口
基本抽象類
- BaseComponent抽象類
- BaseRichSpout抽象類
- BaseRichBolt抽象類
- BaseTransactionalBolt抽象類
- BaseBasicBolt抽象類
spout水龍頭
Spout的最頂層抽象是ISpout接口
-
Open()
:初始化方法 -
close()
:該spout關閉前執(zhí)行,但是并不能得到保證其一定被執(zhí)行,kill -9時不執(zhí)行,Storm kill {topoName} 時執(zhí)行 -
activate()
:當Spout已經從失效模式中激活時被調用。該Spout的nextTuple()方法很快就會被調用 -
deactivate
:當Spout已經失效時被調用。在Spout失效期間,nextTuple不會被調用。Spout將來可能會也可能不會被重新激活 -
nextTuple()
:當調用nextTuple()方法時,Storm要求Spout發(fā)射元組到輸出收集器(OutputCollecctor)。NextTuple方法應該是非阻塞的,所以,如果Spout沒有元組可以發(fā)射,該方法應該返回。nextTuple()、ack()和fail()方法都在Spout任務的單一線程內緊密循環(huán)被調用。當沒有元組可以發(fā)射時,可以讓nextTuple去sleep很短的時間,例如1毫秒,這樣就不會浪費太多的CPU資源 -
ask()
:成功處理tuple
回調方法 -
fail()
:處理失敗tuole
回調方法
bolt轉接頭
bolt的最頂層抽象是IBolt接口
prepare()
:prepare ()方法在集群的工作進程內被初始化時被調用,提供了Bolt執(zhí)行所需要的環(huán)境。
execute()
:接受一個tuple進行處理,也可emit數(shù)據到下一級組件。
cleanup()
:Cleanup方法當一個IBolt即將關閉時被調用。不能保證cleanup()方法一定會被調用,因為Supervisor可以對集群的工作進程使用kill -9命令強制殺死進程命令。
如果在本地模式下運行Storm,當拓撲被殺死的時候,可以保證cleanup()方法一定會被調用。
實現(xiàn)一個Bolt,可以實現(xiàn)IRichBolt接口或繼承BaseRichBolt,如果不想自己處理結果反饋,可以實現(xiàn) IBasicBolt接口或繼承BaseBasicBolt,它實際上相當于自動做了prepare方法和collector.emit.ack(inputTuple)。
spout的tail特性
Storm可以實時監(jiān)測文件數(shù)據,當文件數(shù)據變化時,Storm自動讀取。
分組策略和并發(fā)度
讀取文件路徑和方法
- spout數(shù)據源:數(shù)據庫、文件、MQ(比如:Kafka)
- 數(shù)據源是數(shù)據庫:只適合讀取數(shù)據庫的配置文件
- 數(shù)據源是文件:只適合測試、講課用(因為集群是分布式集群)
- 企業(yè)產生的log文件處理步驟:(1)讀出內容寫入MQ(2)Storm再處理
分組策略(Stream Grouping)
stream grouping用來定義一個stream應該如何分配給Bolts上面的多個Executors(多線程
、多并發(fā)
)。
Storm里面有7種類型的stream grouping
-
Shuffle Grouping: 隨機分組
,輪詢,平均分配。隨機派發(fā)stream里面的tuple,保證每個bolt接收到的tuple數(shù)目大致相同。 -
Fields Grouping:按字段分組
,比如按userid來分組,具有同樣userid的tuple會被分到相同的Bolts里的一個task,而不同的userid則會被分配到不同的bolts里的task。 -
All Grouping:廣播發(fā)送
,對于每一個tuple,所有的bolts都會收到。 -
Global Grouping:全局分組
,這個tuple被分配到storm中的一個bolt的其中一個task。再具體一點就是分配給id值最低的那個task。 -
Non Grouping:不分組
,這stream grouping個分組的意思是說stream不關心到底誰會收到它的tuple。目前這種分組和Shuffle grouping是一樣的效果。在多線程情況下不平均分配
。 -
Direct Grouping:直接分組
,這是一種比較特別的分組方法,用這種分組意味著消息的發(fā)送者指定由消息接收者的哪個task處理這個消息。只有被聲明為Direct Stream的消息流可以聲明這種分組方法。而且這種消息tuple必須使用emitDirect方法來發(fā)射。消息處理者可以通過TopologyContext來獲取處理它的消息的task的id (OutputCollector.emit方法也會返回task的id)。 - Local or shuffle grouping:如果目標bolt有一個或者多個task在同一個工作進程中,tuple將會被隨機發(fā)送給這些tasks。否則,和普通的Shuffle Grouping行為一致。
并發(fā)度
并發(fā)度場景
- 單線程下:加減乘除、全局匯總
- 多線程下:局部加減乘除、持久化DB等
并發(fā)度
并發(fā)度:用戶指定一個任務,可以被多個線程執(zhí)行,并發(fā)度的數(shù)量等于線程executor的數(shù)量。
Task就是具體的處理邏輯對象,一個executor線程可以執(zhí)行一個或多個tasks,但一般默認每個executor只執(zhí)行一個task,所以我們往往認為task就是執(zhí)行線程,其實不是。
Task代表最大并發(fā)度
,一個component的task數(shù)是不會改變的,但是一個componet的executer數(shù)目是會發(fā)生變化的(storm rebalance命令),task數(shù)>=executor數(shù),executor數(shù)代表實際并發(fā)數(shù)。