網(wǎng)站建設(shè) 中企動(dòng)力公司搭建網(wǎng)站的步驟和順序
看介紹文檔貌似挺好:
https://github.com/alibaba/jstorm
阿里擁有自己的實(shí)時(shí)計(jì)算引擎
-
類似于hadoop 中的MR
-
開源storm響應(yīng)太慢
-
開源社區(qū)的速度完全跟不上Ali的需求
-
降低未來運(yùn)維成本
-
提供更多技術(shù)支持,加快內(nèi)部業(yè)務(wù)響應(yīng)速度
現(xiàn)有Storm無法滿足一些需求
-
現(xiàn)有storm調(diào)度太簡單粗暴,無法定制化
-
Storm 任務(wù)分配不平衡
-
RPC OOM一直沒有解決
-
監(jiān)控太簡單
-
對(duì)ZK 訪問頻繁
JStorm相比Storm更穩(wěn)定
-
Nimbus 實(shí)現(xiàn)HA:當(dāng)一臺(tái)nimbus掛了,自動(dòng)熱切到備份nimbus
-
原生Storm RPC:Zeromq 使用堆外內(nèi)存,導(dǎo)致OS 內(nèi)存不夠,Netty 導(dǎo)致OOM;JStorm底層RPC 采用netty + disruptor保證發(fā)送速度和接受速度是匹配的
-
新上線的任務(wù)不會(huì)沖擊老的任務(wù):新調(diào)度從cpu,memory,disk,net 四個(gè)角度對(duì)任務(wù)進(jìn)行分配,已經(jīng)分配好的新任務(wù),無需去搶占老任務(wù)的cpu,memory,disk和net
-
Supervisor主線
-
Spout/Bolt 的open/prepar
-
所有IO, 序列化,反序列化
-
減少對(duì)ZK的訪問量:去掉大量無用的watch;task的心跳時(shí)間延長一倍;Task心跳檢測(cè)無需全ZK掃描。
JStorm相比Storm調(diào)度更強(qiáng)大
-
徹底解決了storm 任務(wù)分配不均衡問題
-
從4個(gè)維度進(jìn)行任務(wù)分配:CPU、Memory、Disk、Net
-
默認(rèn)一個(gè)task,一個(gè)cpu slot。當(dāng)task消耗更多的cpu時(shí),可以申請(qǐng)更多cpu slot
-
默認(rèn)一個(gè)task,一個(gè)memory slot。當(dāng)task需要更多內(nèi)存時(shí),可以申請(qǐng)更多內(nèi)存slot
-
默認(rèn)task,不申請(qǐng)disk slot。當(dāng)task 磁盤IO較重時(shí),可以申請(qǐng)disk slot
-
可以強(qiáng)制某個(gè)component的task 運(yùn)行在不同的節(jié)點(diǎn)上
-
可以強(qiáng)制topology運(yùn)行在單獨(dú)一個(gè)節(jié)點(diǎn)上
-
可以自定義任務(wù)分配,提前預(yù)約任務(wù)分配到哪臺(tái)機(jī)器上,哪個(gè)端口,多少個(gè)cpu slot,多少內(nèi)存,是否申請(qǐng)磁盤
-
可以預(yù)約上一次成功運(yùn)行時(shí)的任務(wù)分配,上次task分配了什么資源,這次還是使用這些資源
JStorm相比Storm性能更好
JStorm 0.9.0 性能非常的好,使用netty時(shí)單worker 發(fā)送最大速度為11萬QPS,使用zeromq時(shí),最大速度為12萬QPS。
-
JStorm 0.9.0 在使用Netty的情況下,比Storm 0.9.0 使用netty情況下,快10%, 并且JStorm netty是穩(wěn)定的而Storm 的Netty是不穩(wěn)定的
-
在使用ZeroMQ的情況下, JStorm 0.9.0 比Storm 0.9.0 快30%
性能提升的原因:
-
Zeromq 減少一次內(nèi)存拷貝
-
增加反序列化線程
-
重寫采樣代碼,大幅減少采樣影響
-
優(yōu)化ack代碼
-
優(yōu)化緩沖map性能
-
Java 比clojure更底層
JStorm的其他優(yōu)化點(diǎn)
-
資源隔離。不同部門,使用不同的組名,每個(gè)組有自己的Quato;不同組的資源隔離;采用cgroups 硬隔離
-
Classloader。解決應(yīng)用的類和Jstorm的類發(fā)生沖突,應(yīng)用的類在自己的類空間中
-
Task 內(nèi)部異步化。Worker 內(nèi)部全流水線模式,Spout nextTuple和ack/fail運(yùn)行在不同線程
?具體如何實(shí)現(xiàn),請(qǐng)參考本ID的的博文系列 ?【jstorm-源碼解析】
?
概敘 & 應(yīng)用場(chǎng)景
JStorm 是一個(gè)分布式實(shí)時(shí)計(jì)算引擎。
JStorm 是一個(gè)類似Hadoop MapReduce的系統(tǒng), 用戶按照指定的接口實(shí)現(xiàn)一個(gè)任務(wù),然后將這個(gè)任務(wù)遞交給JStorm系統(tǒng),Jstorm將這個(gè)任務(wù)跑起來,并且按7 * 24小時(shí)運(yùn)行起來,一旦中間一個(gè)worker 發(fā)生意外故障, 調(diào)度器立即分配一個(gè)新的worker替換這個(gè)失效的worker。
因此,從應(yīng)用的角度,JStorm 應(yīng)用是一種遵守某種編程規(guī)范的分布式應(yīng)用。從系統(tǒng)角度, JStorm一套類似MapReduce的調(diào)度系統(tǒng)。 從數(shù)據(jù)的角度, 是一套基于流水線的消息處理機(jī)制。
實(shí)時(shí)計(jì)算現(xiàn)在是大數(shù)據(jù)領(lǐng)域中最火爆的一個(gè)方向,因?yàn)槿藗儗?duì)數(shù)據(jù)的要求越來越高,實(shí)時(shí)性要求也越來越快,傳統(tǒng)的Hadoop Map Reduce,逐漸滿足不了需求,因此在這個(gè)領(lǐng)域需求不斷。
優(yōu)點(diǎn)
在Storm和JStorm出現(xiàn)以前,市面上出現(xiàn)很多實(shí)時(shí)計(jì)算引擎,但自storm和JStorm出現(xiàn)后,基本上可以說一統(tǒng)江湖: 究其優(yōu)點(diǎn):
- 開發(fā)非常迅速, 接口簡單,容易上手,只要遵守Topology,Spout, Bolt的編程規(guī)范即可開發(fā)出一個(gè)擴(kuò)展性極好的應(yīng)用,底層rpc,worker之間冗余,數(shù)據(jù)分流之類的動(dòng)作完全不用考慮。
- 擴(kuò)展性極好, 當(dāng)一級(jí)處理單元速度,直接配置一下并發(fā)數(shù),即可線性擴(kuò)展性能
- 健壯, 當(dāng)worker失效或機(jī)器出現(xiàn)故障時(shí), 自動(dòng)分配新的worker替換失效worker
- 數(shù)據(jù)準(zhǔn)確性, 可以采用Acker機(jī)制,保證數(shù)據(jù)不丟失。 如果對(duì)精度有更多一步要求,采用事務(wù)機(jī)制,保證數(shù)據(jù)準(zhǔn)確。
應(yīng)用場(chǎng)景
JStorm處理數(shù)據(jù)的方式是基于消息的流水線處理, 因此特別適合無狀態(tài)計(jì)算,也就是計(jì)算單元的依賴的數(shù)據(jù)全部在接受的消息中可以找到, 并且最好一個(gè)數(shù)據(jù)流不依賴另外一個(gè)數(shù)據(jù)流。
因此,常常用于
- 日志分析,從日志中分析出特定的數(shù)據(jù),并將分析的結(jié)果存入外部存儲(chǔ)器如數(shù)據(jù)庫。目前,主流日志分析技術(shù)就使用JStorm或Storm
- 管道系統(tǒng), 將一個(gè)數(shù)據(jù)從一個(gè)系統(tǒng)傳輸?shù)搅硗庖粋€(gè)系統(tǒng), 比如將數(shù)據(jù)庫同步到Hadoop
- 消息轉(zhuǎn)化器, 將接受到的消息按照某種格式進(jìn)行轉(zhuǎn)化,存儲(chǔ)到另外一個(gè)系統(tǒng)如消息中間件
- 統(tǒng)計(jì)分析器, 從日志或消息中,提煉出某個(gè)字段,然后做count或sum計(jì)算,最后將統(tǒng)計(jì)值存入外部存儲(chǔ)器。中間處理過程可能更復(fù)雜。
如何安裝
安裝步驟
- 從Downloads下載relase包
- 搭建Zookeeper集群
- 安裝Python 2.6
- 安裝Java
- 安裝zeromq
- 安裝Jzmq
- 配置$JSTORM_HOME/conf/storm.yaml
- 搭建web ui
- 啟動(dòng)JStorm集群
搭建Zookeeper集群
本處不細(xì)描敘Zookeeper安裝步驟
- 安裝步驟麻煩參考?”zookeeper 安裝步驟“
- zookeeper配置麻煩參考?“zookeeper 配置介紹”
搭建JStorm集群
安裝python 2.6
- 如果當(dāng)前系統(tǒng)提供python,可以不用安裝python
- 自己可以參考?python
- 也可以使用https://github.com/utahta/pythonbrew?來安裝python > curl -kLhttp://xrl.us/pythonbrewinstall?| bash
-s $HOME/.pythonbrew/etc/bashrc?&& source $HOME/.pythonbrew/etc/bashrc
pythonbrew install 2.6.7
pythonbrew switch 2.6.7
安裝java
注意,如果當(dāng)前系統(tǒng)是64位系統(tǒng),則需要下載java 64位,如果是32為系統(tǒng),則下載32位java
安裝zeromq(如果不使用zeromq, 可以不安裝zeromq)
wget?http://download.zeromq.org/zeromq-2.1.7.tar.gz
tar zxf zeromq-2.1.7.tar.gz
cd zeromq-2.1.7
./configure
make
sudo make install
sudo ldconfig
如果沒有root權(quán)限,或當(dāng)前用戶無sudo權(quán)限時(shí),執(zhí)行 “ ./configure --prefix=/home/xxxxx” 替換 “./configure”, 其中/home/xxxx 為安裝目標(biāo)目錄
安裝jzmq(如果不使用zeromq, 可以不安裝jzmq)
git clone git://github.com/nathanmarz/jzmq.git
cd jzmq
./autogen.sh
./configure
make
make install
如果沒有root權(quán)限,或當(dāng)前用戶無sudo權(quán)限時(shí),執(zhí)行 “ ./configure --prefix=/home/xxxx --with-zeromq=/home/xxxx” 替換 “./configure”, 其中/home/xxxx 為安裝目標(biāo)目錄
安裝JStorm
假設(shè)以jstorm-0.9.3.zip為例
unzip jstorm-0.9.3.zip
vi ~/.bashrc
export JSTORM_HOME=/XXXXX/XXXX
export PATH=$PATH:$JSTORM_HOME/bin
配置$JSTORM_HOME/conf/storm.yaml
配置項(xiàng):
- storm.zookeeper.servers: 表示zookeeper 的地址,
- nimbus.host: 表示nimbus的地址
- storm.zookeeper.root: 表示jstorm在zookeeper中的根目錄,當(dāng)多個(gè)JStorm共享一個(gè)ZOOKEEPER時(shí),需要設(shè)置該選項(xiàng),默認(rèn)即為“/jstorm”
- storm.local.dir: 表示jstorm臨時(shí)數(shù)據(jù)存放目錄,需要保證jstorm程序?qū)υ撃夸浻袑憴?quán)限
- java.library.path: zeromq 和java zeromq library的安裝目錄,默認(rèn)"/usr/local/lib:/opt/local/lib:/usr/lib"
- supervisor.slots.ports: 表示supervisor 提供的端口slot列表,注意不要和其他端口發(fā)生沖突,默認(rèn)是68xx,而storm的是67xx
- supervisor.disk.slot: 表示提供數(shù)據(jù)目錄,當(dāng)一臺(tái)機(jī)器有多塊磁盤時(shí),可以提供磁盤讀寫slot,方便有重IO操作的應(yīng)用。
- topology.enable.classloader: false, 默認(rèn)關(guān)閉classloader,如果應(yīng)用的jar與jstorm的依賴的jar發(fā)生沖突,比如應(yīng)用使用thrift9,但jstorm使用thrift7時(shí),就需要打開classloader
- nimbus.groupfile.path: 如果需要做資源隔離,比如數(shù)據(jù)倉庫使用多少資源,技術(shù)部使用多少資源,無線部門使用多少資源時(shí),就需要打開分組功能, 設(shè)置一個(gè)配置文件的絕對(duì)路徑,改配置文件如源碼中g(shù)roup_file.ini所示
- storm.local.dir: jstorm使用的本地臨時(shí)目錄,如果一臺(tái)機(jī)器同時(shí)運(yùn)行storm和jstorm的話, 則不要共用一個(gè)目錄,必須將二者分離開
在提交jar的節(jié)點(diǎn)上執(zhí)行:
安裝JStorm web ui
必須使用tomcat 7.0 或以上版本, 注意不要忘記拷貝?~/.jstorm/storm.yaml
web ui 可以和nimbus不在同一個(gè)節(jié)點(diǎn)
mkdir ~/.jstorm
cp -f $JSTORM_HOME/conf/storm.yaml ~/.jstorm
下載tomcat 7.x (以apache-tomcat-7.0.37 為例)
tar -xzf apache-tomcat-7.0.37.tar.gz
cd apache-tomcat-7.0.37
cd webapps
cp $JSTORM_HOME/jstorm-ui-0.9.3.war ./
mv ROOT ROOT.old
ln -s jstorm-ui-0.9.3 ROOT
cd ../bin
./startup.sh
啟動(dòng)JStorm
- 在nimbus 節(jié)點(diǎn)上執(zhí)行 “nohup jstorm nimbus &”, 查看$JSTORM_HOME/logs/nimbus.log檢查有無錯(cuò)誤
- 在supervisor節(jié)點(diǎn)上執(zhí)行 “nohup jstorm supervisor &”, 查看$JSTORM_HOME/logs/supervisor.log檢查有無錯(cuò)誤?
基本概念
流
在JStorm中有對(duì)于流stream的抽象,流是一個(gè)不間斷的無界的連續(xù)tuple,注意JStorm在建模事件流時(shí),把流中的事件抽象為tuple即元組,后面會(huì)解釋JStorm中如何使用tuple。
Spout/Bolt
JStorm認(rèn)為每個(gè)stream都有一個(gè)stream源,也就是原始元組的源頭,所以它將這個(gè)源頭抽象為spout,spout可能是連接消息中間件(如MetaQ, Kafka, TBNotify等),并不斷發(fā)出消息,也可能是從某個(gè)隊(duì)列中不斷讀取隊(duì)列元素并裝配為tuple發(fā)射。
有了源頭即spout也就是有了stream,那么該如何處理stream內(nèi)的tuple呢,同樣的思想JStorm將tuple的中間處理過程抽象為Bolt,bolt可以消費(fèi)任意數(shù)量的輸入流,只要將流方向?qū)蛟揵olt,同時(shí)它也可以發(fā)送新的流給其他bolt使用,這樣一來,只要打開特定的spout(管口)再將spout中流出的tuple導(dǎo)向特定的bolt,又bolt對(duì)導(dǎo)入的流做處理后再導(dǎo)向其他bolt或者目的地。
我們可以認(rèn)為spout就是一個(gè)一個(gè)的水龍頭,并且每個(gè)水龍頭里流出的水是不同的,我們想拿到哪種水就擰開哪個(gè)水龍頭,然后使用管道將水龍頭的水導(dǎo)向到一個(gè)水處理器(bolt),水處理器處理后再使用管道導(dǎo)向另一個(gè)處理器或者存入容器中。
Topology
對(duì)應(yīng)上文的介紹,我們可以很容易的理解這幅圖,這是一張有向無環(huán)圖,JStorm將這個(gè)圖抽象為Topology即拓?fù)?#xff08;的確,拓?fù)浣Y(jié)構(gòu)是有向無環(huán)的),拓?fù)涫荍storm中最高層次的一個(gè)抽象概念,它可以被提交到Jstorm集群執(zhí)行,一個(gè)拓?fù)渚褪且粋€(gè)數(shù)據(jù)流轉(zhuǎn)換圖,圖中每個(gè)節(jié)點(diǎn)是一個(gè)spout或者bolt,圖中的邊表示bolt訂閱了哪些流,當(dāng)spout或者bolt發(fā)送元組到流時(shí),它就發(fā)送元組到每個(gè)訂閱了該流的bolt(這就意味著不需要我們手工拉管道,只要預(yù)先訂閱,spout就會(huì)將流發(fā)到適當(dāng)bolt上)。 插個(gè)位置說下Jstorm的topology實(shí)現(xiàn),為了做實(shí)時(shí)計(jì)算,我們需要設(shè)計(jì)一個(gè)拓?fù)鋱D,并實(shí)現(xiàn)其中的Bolt處理細(xì)節(jié),JStorm中拓?fù)涠x僅僅是一些Thrift結(jié)構(gòu)體,這樣一來我們就可以使用其他語言來創(chuàng)建和提交拓?fù)洹?/p>
Tuple
JStorm將流中數(shù)據(jù)抽象為tuple,一個(gè)tuple就是一個(gè)值列表value list,list中的每個(gè)value都有一個(gè)name,并且該value可以是基本類型,字符類型,字節(jié)數(shù)組等,當(dāng)然也可以是其他可序列化的類型。拓?fù)涞拿總€(gè)節(jié)點(diǎn)都要說明它所發(fā)射出的元組的字段的name,其他節(jié)點(diǎn)只需要訂閱該name就可以接收處理。
Worker/Task
Worker和Task是JStorm中任務(wù)的執(zhí)行單元, 一個(gè)worker表示一個(gè)進(jìn)程,一個(gè)task表示一個(gè)線程, 一個(gè)worker可以運(yùn)行多個(gè)task。
資源slot
在JStorm中,資源類型分為4種, CPU, Memory,Disk, Port, 不再局限于Storm的port。 即一個(gè)supervisor可以提供多少個(gè)CPU slot,多少個(gè)Memory slot, 多少個(gè)Disk slot, 多少個(gè)Port slot
- 一個(gè)worker就消耗一個(gè)Port slot, 默認(rèn)一個(gè)task會(huì)消耗一個(gè)CPU slot和一個(gè)Memory slot
- 當(dāng)task執(zhí)行任務(wù)較重時(shí),可以申請(qǐng)更多的CPU slot,
- 當(dāng)task需要更多內(nèi)存時(shí),可以申請(qǐng)更多的內(nèi)存slot,
- 當(dāng)task 磁盤讀寫較多時(shí),可以申請(qǐng)磁盤slot,則該磁盤slot給該task獨(dú)享。?
應(yīng)用例子
最簡單的JStorm例子分為4個(gè)步驟:
生成Topology
IRichSpout
IRichSpout 為最簡單的Spout接口
其中注意:
- spout對(duì)象必須是繼承Serializable, 因此要求spout內(nèi)所有數(shù)據(jù)結(jié)構(gòu)必須是可序列化的
- spout可以有構(gòu)造函數(shù),但構(gòu)造函數(shù)只執(zhí)行一次,是在提交任務(wù)時(shí),創(chuàng)建spout對(duì)象,因此在task分配到具體worker之前的初始化工作可以在此處完成,一旦完成,初始化的內(nèi)容將攜帶到每一個(gè)task內(nèi)(因?yàn)樘峤蝗蝿?wù)時(shí)將spout序列化到文件中去,在worker起來時(shí)再將spout從文件中反序列化出來)。
- open是當(dāng)task起來后執(zhí)行的初始化動(dòng)作
- close是當(dāng)task被shutdown后執(zhí)行的動(dòng)作
- activate 是當(dāng)task被激活時(shí),觸發(fā)的動(dòng)作
- deactivate 是task被deactive時(shí),觸發(fā)的動(dòng)作
- nextTuple 是spout實(shí)現(xiàn)核心, nextuple完成自己的邏輯,即每一次取消息后,用collector 將消息emit出去。
- ack, 當(dāng)spout收到一條ack消息時(shí),觸發(fā)的動(dòng)作,詳情可以參考?ack機(jī)制
- fail, 當(dāng)spout收到一條fail消息時(shí),觸發(fā)的動(dòng)作,詳情可以參考?ack機(jī)制
- declareOutputFields, 定義spout發(fā)送數(shù)據(jù),每個(gè)字段的含義
- getComponentConfiguration 獲取本spout的component 配置
Bolt
其中注意:
- bolt對(duì)象必須是繼承Serializable, 因此要求spout內(nèi)所有數(shù)據(jù)結(jié)構(gòu)必須是可序列化的
- bolt可以有構(gòu)造函數(shù),但構(gòu)造函數(shù)只執(zhí)行一次,是在提交任務(wù)時(shí),創(chuàng)建bolt對(duì)象,因此在task分配到具體worker之前的初始化工作可以在此處完成,一旦完成,初始化的內(nèi)容將攜帶到每一個(gè)task內(nèi)(因?yàn)樘峤蝗蝿?wù)時(shí)將bolt序列化到文件中去,在worker起來時(shí)再將bolt從文件中反序列化出來)。
- prepare是當(dāng)task起來后執(zhí)行的初始化動(dòng)作
- cleanup是當(dāng)task被shutdown后執(zhí)行的動(dòng)作
- execute是bolt實(shí)現(xiàn)核心, 完成自己的邏輯,即接受每一次取消息后,處理完,有可能用collector 將產(chǎn)生的新消息emit出去。 ** 在executor中,當(dāng)程序處理一條消息時(shí),需要執(zhí)行collector.ack, 詳情可以參考?ack機(jī)制?** 在executor中,當(dāng)程序無法處理一條消息時(shí)或出錯(cuò)時(shí),需要執(zhí)行collector.fail ,詳情可以參考?ack機(jī)制
- declareOutputFields, 定義bolt發(fā)送數(shù)據(jù),每個(gè)字段的含義
- getComponentConfiguration 獲取本bolt的component 配置
編譯
在Maven中配置
如果找不到j(luò)storm-client和jstorm-client-extension包,可以自己下載jstorm源碼進(jìn)行編譯,請(qǐng)參考?源碼編譯
打包時(shí),需要將所有依賴打入到一個(gè)包中
提交jar
JStorm vs Storm vs flume vs S4 選型
jstorm jar xxxxxx.jar com.alibaba.xxxx.xx parameter
- xxxx.jar 為打包后的jar
- com.alibaba.xxxx.xx 為入口類,即提交任務(wù)的類
- parameter即為提交參數(shù)
JStorm VS Storm 請(qǐng)參看?JStorm 0.9.0 介紹.pptx
JStorm 比Storm更穩(wěn)定,更強(qiáng)大,更快, storm上跑的程序,一行代碼不變可以運(yùn)行在jstorm上。
Flume?是一個(gè)成熟的系統(tǒng),主要focus在管道上,將數(shù)據(jù)從一個(gè)數(shù)據(jù)源傳輸?shù)搅硗庖粋€(gè)數(shù)據(jù)源, 系統(tǒng)提供大量現(xiàn)成的插件做管道作用。當(dāng)然也可以做一些計(jì)算和分析,但插件的開發(fā)沒有Jstorm便捷和迅速。
S4?就是一個(gè)半成品,健壯性還可以,但數(shù)據(jù)準(zhǔn)確性較糟糕,無法保證數(shù)據(jù)不丟失,這個(gè)特性讓S4 大受限制,也導(dǎo)致了S4開源很多年,但發(fā)展一直不是很迅速。
AKKA?是一個(gè)actor模型,也是一個(gè)不錯(cuò)的系統(tǒng),在這個(gè)actor模型基本上,你想做任何事情都沒有問題,但問題是你需要做更多的工作,topology怎么生成,怎么序列化。數(shù)據(jù)怎么流(隨機(jī),還是group by)等等。
Spark?是一個(gè)輕量的內(nèi)存MR, 更偏重批量數(shù)據(jù)處理
0.9.0 性能測(cè)試
?JStorm 0.9.0 性能非常的好, 使用netty時(shí)單worker 發(fā)送最大速度為11萬QPS, 使用zeromq時(shí),最大速度為12萬QPS.結(jié)論
- JStorm 0.9.0 在使用Netty的情況下,比Storm 0.9.0 使用netty情況下,快10%, 并且JStorm netty是穩(wěn)定的而Storm 的Netty是不穩(wěn)定的
- 在使用ZeroMQ的情況下, JStorm 0.9.0 比Storm 0.9.0 快30%
原因
- Zeromq 減少一次內(nèi)存拷貝
- 增加反序列化線程
- 重寫采樣代碼,大幅減少采樣影響
- 優(yōu)化ack代碼
- 優(yōu)化緩沖map性能
- Java 比clojure更底層
測(cè)試
測(cè)試樣例
測(cè)試樣例為https://github.com/longdafeng/storm-examples
測(cè)試環(huán)境
5 臺(tái) 16核, 98G 物理機(jī)
測(cè)試結(jié)果
- JStorm with netty, Spout 發(fā)送QPS 為 11萬
- storm with netty, Spout 應(yīng)用發(fā)送QPS 為 10萬 (截圖為上層應(yīng)用的QPS, 沒有包括發(fā)送到ack的QPS, Spout發(fā)送QPS 正好為上層應(yīng)用QPS的2倍)
- JStorm with zeromq, Spout 發(fā)送QPS 為12萬
- Storm with zeromq, Spout 發(fā)送QPS 為9萬(截圖為上層應(yīng)用的QPS, 沒有包括發(fā)送到ack的QPS, Spout發(fā)送QPS 正好為上層應(yīng)用QPS的2倍)
資源硬隔離
cgroups是control groups的縮寫,是Linux內(nèi)核提供的一種可以限制, 記錄, 隔離進(jìn)程組(process groups)所使用的物理資源(如:cpu,memory,IO 等等)的機(jī)制。
在Jstorm中,我們使用cgroup進(jìn)行cpu硬件資源的管理。使用前,需要做如下檢查和配置。
- 檢查/etc/passwd 文件中當(dāng)前用戶的uid和gid, 假設(shè)當(dāng)前用戶是admin, 則看/etc/passwd文件中admin的uid和gid是多少
-
cgroup功能在當(dāng)前系統(tǒng)的內(nèi)核版本是否支持
檢查/etc/cgconfig.conf是否存在。如果不存在, 請(qǐng)“yum install libcgroup”,如果存在,設(shè)置cpu子系統(tǒng)的掛載目錄位置, 以及修改該配置文件中相應(yīng)的uid/gid為啟動(dòng)jstorm用戶的uid/gid, 本例子中以500為例, 注意是根據(jù)第一步來進(jìn)行設(shè)置的。
- 然后啟動(dòng)cgroup服務(wù)
Note: cgconfig.conf只能在root模式下修改。
或者直接執(zhí)行命令
這是一個(gè)cgconfig.conf配置文件例子。比如jstorm的啟動(dòng)用戶為admin,admin在當(dāng)前 系統(tǒng)的uid/gid為500(查看/etc/passwd 可以查看到uid和gid),那么相對(duì)應(yīng)cpu子系統(tǒng)的jstorm目錄uid/gid也需要設(shè)置為相同的值。 以便jstorm有相應(yīng)權(quán)限可以在這個(gè)目錄下為jstorm的每個(gè)需要進(jìn)行資源隔離的進(jìn)程創(chuàng)建對(duì)應(yīng) 的目錄和進(jìn)行相關(guān)設(shè)置。
. 在jstorm配置文件中打開cgroup, 配置storm.yaml
?? supervisor.enable.cgroup: true
常見問題
性能問題
參考性能優(yōu)化
資源不夠
當(dāng)報(bào)告 ”No supervisor resource is enough for component “, 則意味著資源不夠 如果是僅僅是測(cè)試環(huán)境,可以將supervisor的cpu 和memory slot設(shè)置大,
在jstorm中, 一個(gè)task默認(rèn)會(huì)消耗一個(gè)cpu slot和一個(gè)memory slot, 而一臺(tái)機(jī)器上默認(rèn)的cpu slot是(cpu 核數(shù) -1), memory slot數(shù)(物理內(nèi)存大小 * 75%/1g), 如果一個(gè)worker上運(yùn)行task比較多時(shí),需要將memory slot size設(shè)小(默認(rèn)是1G), 比如512M, memory.slot.per.size: 535298048
序列化問題
所有spout,bolt,configuration, 發(fā)送的消息(Tuple)都必須實(shí)現(xiàn)Serializable, 否則就會(huì)出現(xiàn)序列化錯(cuò)誤.
如果是spout或bolt的成員變量沒有實(shí)現(xiàn)Serializable時(shí),但又必須使用時(shí), 可以對(duì)該變量申明時(shí),增加transient 修飾符, 然后在open或prepare時(shí),進(jìn)行實(shí)例化
Log4j 沖突
0.9.0 開始,JStorm依舊使用Log4J,但storm使用Logbak,因此應(yīng)用程序如果有依賴log4j-over-slf4j.jar, 則需要exclude 所有l(wèi)og4j-over-slf4j.jar依賴,下個(gè)版本將自定義classloader,就不用擔(dān)心這個(gè)問題。
類沖突
如果應(yīng)用程序使用和JStorm相同的jar 但版本不一樣時(shí),建議打開classloader, 修改配置文件
topology.enable.classloader: true
或者
ConfigExtension.setEnableTopologyClassLoader(conf, true);
JStorm默認(rèn)是關(guān)掉classloader,因此JStorm會(huì)強(qiáng)制使用JStorm依賴的jar
提交任務(wù)后,等待幾分鐘后,web ui始終沒有顯示對(duì)應(yīng)的task
有3種情況:
用戶程序初始化太慢
如果有用戶程序的日志輸出,則表明是用戶的初始化太慢或者出錯(cuò),查看日志即可。 另外對(duì)于MetaQ 1.x的應(yīng)用程序,Spout會(huì)recover ~/.meta_recover/目錄下文件,可以直接刪除這些消費(fèi)失敗的問題,加速啟動(dòng)。
通常是用戶jar沖突或初始化發(fā)生問題
打開supervisor 日志,找出啟動(dòng)worker命令,單獨(dú)執(zhí)行,然后檢查是否有問題。類似下圖:
檢查是不是storm和jstorm使用相同的本地目錄
檢查配置項(xiàng) ”storm.local.dir“, 是不是storm和jstorm使用相同的本地目錄,如果相同,則將二者分開
提示端口被綁定
有2種情況:
多個(gè)worker搶占一個(gè)端口
假設(shè)是6800 端口被占, 可以執(zhí)行命令 “ps -ef|grep 6800” 檢查是否有多個(gè)進(jìn)程, 如果有多個(gè)進(jìn)程,則手動(dòng)殺死他們
系統(tǒng)打開太多的connection
Linux對(duì)外連接端口數(shù)限制,TCP client對(duì)外發(fā)起連接數(shù)達(dá)到28000左右時(shí),就開始大量拋異常,需要
# echo "10000 65535" > /proc/sys/net/ipv4/ip_local_port_range