![大數(shù)據(jù)處理框架:Storm:Storm架構(gòu)與原理_第1頁](http://file4.renrendoc.com/view12/M00/3D/33/wKhkGWbqByGAXrQeAALOfs5vCCk778.jpg)
![大數(shù)據(jù)處理框架:Storm:Storm架構(gòu)與原理_第2頁](http://file4.renrendoc.com/view12/M00/3D/33/wKhkGWbqByGAXrQeAALOfs5vCCk7782.jpg)
![大數(shù)據(jù)處理框架:Storm:Storm架構(gòu)與原理_第3頁](http://file4.renrendoc.com/view12/M00/3D/33/wKhkGWbqByGAXrQeAALOfs5vCCk7783.jpg)
![大數(shù)據(jù)處理框架:Storm:Storm架構(gòu)與原理_第4頁](http://file4.renrendoc.com/view12/M00/3D/33/wKhkGWbqByGAXrQeAALOfs5vCCk7784.jpg)
![大數(shù)據(jù)處理框架:Storm:Storm架構(gòu)與原理_第5頁](http://file4.renrendoc.com/view12/M00/3D/33/wKhkGWbqByGAXrQeAALOfs5vCCk7785.jpg)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
大數(shù)據(jù)處理框架:Storm:Storm架構(gòu)與原理1Storm簡介1.1Storm的發(fā)展歷史Storm是一個(gè)開源的分布式實(shí)時(shí)計(jì)算系統(tǒng),由NathanMarz和BackType團(tuán)隊(duì)在2010年開發(fā)。最初,Storm是為了處理Twitter的實(shí)時(shí)數(shù)據(jù)流而設(shè)計(jì)的,它能夠以容錯(cuò)的方式處理大量數(shù)據(jù),提供了一種類似于HadoopMapReduce的數(shù)據(jù)處理模型,但更適用于實(shí)時(shí)數(shù)據(jù)流的處理。2011年,BackType被Twitter收購,Storm項(xiàng)目也隨之被Twitter接管。然而,為了保持Storm的開放性和獨(dú)立性,Twitter在2014年將Storm項(xiàng)目捐贈(zèng)給了Apache軟件基金會(huì),使其成為Apache的頂級(jí)項(xiàng)目。自那時(shí)起,Storm社區(qū)持續(xù)發(fā)展,不斷優(yōu)化和擴(kuò)展其功能,使其成為實(shí)時(shí)大數(shù)據(jù)處理領(lǐng)域的一個(gè)重要工具。1.2Storm的應(yīng)用場景Storm的應(yīng)用場景廣泛,主要集中在實(shí)時(shí)數(shù)據(jù)處理和流處理領(lǐng)域。以下是一些典型的應(yīng)用場景:實(shí)時(shí)分析:Storm可以實(shí)時(shí)處理數(shù)據(jù)流,進(jìn)行實(shí)時(shí)分析,如實(shí)時(shí)監(jiān)控網(wǎng)站流量、用戶行為分析等。在線機(jī)器學(xué)習(xí):Storm支持在線機(jī)器學(xué)習(xí)算法的實(shí)時(shí)訓(xùn)練和預(yù)測,如實(shí)時(shí)推薦系統(tǒng)、實(shí)時(shí)廣告投放優(yōu)化等。持續(xù)計(jì)算:Storm可以持續(xù)處理數(shù)據(jù)流,進(jìn)行持續(xù)計(jì)算,如實(shí)時(shí)計(jì)算股票價(jià)格變動(dòng)、實(shí)時(shí)天氣預(yù)報(bào)等。分布式RPC:Storm可以作為分布式遠(yuǎn)程過程調(diào)用(RPC)的平臺(tái),實(shí)現(xiàn)服務(wù)的分布式調(diào)用和處理。數(shù)據(jù)流處理:Storm可以處理各種數(shù)據(jù)流,如社交媒體數(shù)據(jù)、傳感器數(shù)據(jù)、日志數(shù)據(jù)等,進(jìn)行實(shí)時(shí)的數(shù)據(jù)清洗、轉(zhuǎn)換和加載。1.2.1示例:使用Storm進(jìn)行實(shí)時(shí)數(shù)據(jù)處理假設(shè)我們有一個(gè)實(shí)時(shí)的Twitter數(shù)據(jù)流,我們想要實(shí)時(shí)統(tǒng)計(jì)每分鐘內(nèi)出現(xiàn)次數(shù)最多的詞匯。以下是一個(gè)使用Storm的簡單示例://導(dǎo)入必要的Storm庫
importorg.apache.storm.Config;
importorg.apache.storm.LocalCluster;
importorg.apache.storm.StormSubmitter;
importorg.apache.storm.topology.TopologyBuilder;
importorg.apache.storm.tuple.Fields;
importorg.apache.storm.tuple.Values;
importorg.apache.storm.spout.SpoutOutputCollector;
importorg.apache.storm.task.TopologyContext;
importorg.apache.storm.spout.BaseRichSpout;
importorg.apache.storm.bolt.BaseBasicBolt;
importorg.apache.storm.bolt.OutputCollector;
importorg.apache.storm.task.TaskId;
importorg.apache.storm.task.TaskOutputCollector;
importorg.apache.storm.bolt.ReducingBolt;
importorg.apache.storm.bolt.SplitSentenceBolt;
importorg.apache.storm.bolt.WordCountBolt;
importorg.apache.storm.bolt.PrintBolt;
importorg.apache.storm.bolt.CountBolt;
importorg.apache.storm.bolt.CountWordBolt;
importorg.apache.storm.bolt.CountWordReducer;
importorg.apache.storm.bolt.CountWordReducerBolt;
importorg.apache.storm.bolt.CountWordReducerBolt.CountWordReducer;
importorg.apache.storm.bolt.CountWordReducerBolt.CountWordReducer.CountWordReducerState;
importorg.apache.storm.bolt.CountWordReducerBolt.CountWordReducer.CountWordReducerState.CountWordReducerStateBuilder;
importorg.apache.storm.bolt.CountWordReducerBolt.CountWordReducer.CountWordReducerState.CountWordReducerStateBuilder.CountWordReducerStateBuilderImpl;
importorg.apache.storm.bolt.CountWordReducerBolt.CountWordReducer.CountWordReducerState.CountWordReducerStateBuilder.CountWordReducerStateBuilderImpl.CountWordReducerStateBuilderImplImpl;
importorg.apache.storm.bolt.CountWordReducerBolt.CountWordReducer.CountWordReducerState.CountWordReducerStateBuilder.CountWordReducerStateBuilderImpl.CountWordReducerStateBuilderImplImpl.CountWordReducerStateBuilderImplImplImpl;
//定義一個(gè)Spout,用于生成數(shù)據(jù)
publicclassTweetSpoutextendsBaseRichSpout{
privateSpoutOutputCollector_collector;
privateint_sequence;
publicvoidopen(Mapconf,TopologyContextcontext,SpoutOutputCollectorcollector){
_collector=collector;
_sequence=0;
}
publicvoidnextTuple(){
//模擬生成Twitter數(shù)據(jù)
Stringtweet="Sampletweetnumber"+_sequence;
_collector.emit(newValues(tweet));
_sequence++;
try{
Thread.sleep(1000);//每秒生成一條數(shù)據(jù)
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
//定義一個(gè)Bolt,用于處理數(shù)據(jù)
publicclassWordCountBoltextendsBaseBasicBolt{
privateOutputCollector_collector;
publicvoidprepare(MapstormConf,TopologyContextcontext,OutputCollectorcollector){
_collector=collector;
}
publicvoidexecute(Tupleinput){
//獲取輸入的tweet
Stringsentence=input.getStringByField("tweet");
//分割句子為單詞
String[]words=sentence.split("");
//發(fā)射單詞到下一個(gè)Bolt
for(Stringword:words){
_collector.emit(newValues(word));
}
_collector.ack(input);//確認(rèn)處理完成
}
}
//定義一個(gè)Bolt,用于統(tǒng)計(jì)單詞
publicclassCountWordBoltextendsBaseBasicBolt{
privateMap<String,Integer>_counts=newHashMap<>();
privateOutputCollector_collector;
publicvoidprepare(MapstormConf,TopologyContextcontext,OutputCollectorcollector){
_collector=collector;
}
publicvoidexecute(Tupleinput){
//獲取輸入的單詞
Stringword=input.getStringByField("word");
//更新單詞計(jì)數(shù)
Integercount=_counts.get(word);
if(count==null){
count=0;
}
_counts.put(word,count+1);
//發(fā)射更新后的計(jì)數(shù)
_collector.emit(newValues(word,count+1));
_collector.ack(input);//確認(rèn)處理完成
}
}
//定義一個(gè)Bolt,用于打印結(jié)果
publicclassPrintBoltextendsBaseBasicBolt{
privateOutputCollector_collector;
publicvoidprepare(MapstormConf,TopologyContextcontext,OutputCollectorcollector){
_collector=collector;
}
publicvoidexecute(Tupleinput){
//獲取輸入的單詞和計(jì)數(shù)
Stringword=input.getStringByField("word");
Integercount=input.getIntegerByField("count");
//打印結(jié)果
System.out.println(word+":"+count);
_collector.ack(input);//確認(rèn)處理完成
}
}
//構(gòu)建Storm拓?fù)?/p>
publicclassWordCountTopology{
publicstaticvoidmain(String[]args)throwsException{
TopologyBuilderbuilder=newTopologyBuilder();
builder.setSpout("tweet-spout",newTweetSpout(),5);
builder.setBolt("split-bolt",newSplitSentenceBolt(),8)
.shuffleGrouping("tweet-spout");
builder.setBolt("count-bolt",newCountWordBolt(),12)
.fieldsGrouping("split-bolt",newFields("word"));
builder.setBolt("print-bolt",newPrintBolt(),10)
.globalGrouping("count-bolt");
Configconfig=newConfig();
config.setDebug(true);
if(args!=null&&args.length>0){
config.setNumWorkers(3);
StormSubmitter.submitTopology(args[0],config,builder.createTopology());
}else{
config.setMaxTaskParallelism(3);
LocalClustercluster=newLocalCluster();
cluster.submitTopology("word-count",config,builder.createTopology());
Thread.sleep(10000);
cluster.shutdown();
}
}
}在這個(gè)示例中,我們首先定義了一個(gè)TweetSpout,用于模擬生成Twitter數(shù)據(jù)流。然后,我們定義了一個(gè)WordCountBolt,用于將每條tweet分割成單詞。接著,我們定義了一個(gè)CountWordBolt,用于統(tǒng)計(jì)每個(gè)單詞的出現(xiàn)次數(shù)。最后,我們定義了一個(gè)PrintBolt,用于打印統(tǒng)計(jì)結(jié)果。通過這些組件,我們構(gòu)建了一個(gè)Storm拓?fù)?,用于?shí)時(shí)處理Twitter數(shù)據(jù)流,統(tǒng)計(jì)每分鐘內(nèi)出現(xiàn)次數(shù)最多的詞匯。1.2.2解釋Spout:在Storm中,Spout是數(shù)據(jù)流的源頭,負(fù)責(zé)生成數(shù)據(jù)。在上述示例中,TweetSpout模擬生成Twitter數(shù)據(jù)流。Bolt:在Storm中,Bolt是數(shù)據(jù)流的處理單元,負(fù)責(zé)處理數(shù)據(jù)。在上述示例中,WordCountBolt負(fù)責(zé)將tweet分割成單詞,CountWordBolt負(fù)責(zé)統(tǒng)計(jì)單詞出現(xiàn)次數(shù),PrintBolt負(fù)責(zé)打印統(tǒng)計(jì)結(jié)果。Topology:在Storm中,Topology是由Spout和Bolt組成的數(shù)據(jù)流處理流程。在上述示例中,我們構(gòu)建了一個(gè)包含TweetSpout、WordCountBolt、CountWordBolt和PrintBolt的拓?fù)?,用于?shí)時(shí)處理Twitter數(shù)據(jù)流,統(tǒng)計(jì)每分鐘內(nèi)出現(xiàn)次數(shù)最多的詞匯。Grouping:在Storm中,Grouping是Bolt之間的數(shù)據(jù)分發(fā)策略。在上述示例中,我們使用了shuffleGrouping、fieldsGrouping和globalGrouping三種Grouping策略,分別用于將數(shù)據(jù)隨機(jī)分發(fā)到Bolt、根據(jù)字段分發(fā)數(shù)據(jù)到Bolt和將所有數(shù)據(jù)分發(fā)到同一個(gè)Bolt。通過這個(gè)示例,我們可以看到Storm如何處理實(shí)時(shí)數(shù)據(jù)流,以及如何構(gòu)建和運(yùn)行Storm拓?fù)洹?Storm架構(gòu)解析2.1集群架構(gòu)概述Storm是一個(gè)分布式實(shí)時(shí)計(jì)算系統(tǒng),其架構(gòu)設(shè)計(jì)旨在處理大規(guī)模的流數(shù)據(jù)。Storm的集群架構(gòu)主要包括以下幾個(gè)核心組件:Nimbus:類似于Hadoop中的JobTracker,負(fù)責(zé)整個(gè)集群的資源管理和任務(wù)調(diào)度。Supervisor:運(yùn)行在每個(gè)節(jié)點(diǎn)上,接收Nimbus分配的任務(wù),并在本地機(jī)器上啟動(dòng)和監(jiān)控Worker進(jìn)程。Worker:Supervisor啟動(dòng)的進(jìn)程,每個(gè)Worker運(yùn)行一個(gè)或多個(gè)Task,執(zhí)行具體的計(jì)算任務(wù)。Task:Storm中最小的計(jì)算單元,每個(gè)Task執(zhí)行一個(gè)Spout或Bolt的實(shí)例。Spout:數(shù)據(jù)源,負(fù)責(zé)從外部系統(tǒng)讀取數(shù)據(jù)并將其發(fā)送到Storm集群中。Bolt:數(shù)據(jù)處理單元,負(fù)責(zé)接收Spout或其它Bolt發(fā)送的數(shù)據(jù),進(jìn)行處理后,可以將結(jié)果發(fā)送到另一個(gè)Bolt或輸出。2.2Nimbus和Supervisor的角色2.2.1NimbusNimbus是Storm集群的主節(jié)點(diǎn),負(fù)責(zé)以下任務(wù):任務(wù)分配:Nimbus接收用戶提交的Topology,并將其分解為多個(gè)任務(wù),然后將這些任務(wù)分配給集群中的各個(gè)Supervisor。集群監(jiān)控:Nimbus監(jiān)控集群的健康狀態(tài),包括Worker的運(yùn)行情況和任務(wù)的執(zhí)行狀態(tài)。配置管理:Nimbus管理集群的配置信息,確保所有節(jié)點(diǎn)都能訪問到最新的配置。2.2.2SupervisorSupervisor是運(yùn)行在每個(gè)節(jié)點(diǎn)上的服務(wù),其主要職責(zé)包括:任務(wù)執(zhí)行:接收Nimbus分配的任務(wù),并在本地啟動(dòng)Worker進(jìn)程來執(zhí)行這些任務(wù)。資源管理:管理本地節(jié)點(diǎn)的資源,確保Worker進(jìn)程有足夠的資源運(yùn)行。故障恢復(fù):如果本地的Worker進(jìn)程失敗,Supervisor會(huì)自動(dòng)重啟Worker,以確保任務(wù)的連續(xù)執(zhí)行。2.3Worker進(jìn)程詳解Worker進(jìn)程是Storm集群中的執(zhí)行單元,由Supervisor在每個(gè)節(jié)點(diǎn)上啟動(dòng)。每個(gè)Worker進(jìn)程可以運(yùn)行一個(gè)或多個(gè)Task,具體取決于Topology的配置。Worker進(jìn)程的生命周期由Supervisor管理,當(dāng)Topology被提交到集群時(shí),Supervisor會(huì)根據(jù)Nimbus的指令啟動(dòng)Worker進(jìn)程;當(dāng)Topology被關(guān)閉或集群資源緊張時(shí),Supervisor會(huì)關(guān)閉Worker進(jìn)程。在Worker進(jìn)程中,每個(gè)Task都有自己的線程,這意味著Task之間的執(zhí)行是并行的。這種設(shè)計(jì)使得Storm能夠高效地處理大規(guī)模的流數(shù)據(jù)。2.4Task和Spout的運(yùn)作機(jī)制2.4.1SpoutSpout是Storm中的數(shù)據(jù)源,負(fù)責(zé)從外部系統(tǒng)讀取數(shù)據(jù)并將其發(fā)送到Storm集群中。Spout通過實(shí)現(xiàn)ISpout接口來定義數(shù)據(jù)的讀取和發(fā)送邏輯。以下是一個(gè)簡單的Spout示例,它模擬從網(wǎng)絡(luò)中讀取數(shù)據(jù):publicclassNetworkSpoutimplementsIRichSpout{
privateSpoutOutputCollector_collector;
privateboolean_isRunning=true;
publicvoidopen(Mapconf,TopologyContextcontext,SpoutOutputCollectorcollector){
_collector=collector;
}
publicvoidnextTuple(){
if(_isRunning){
Stringdata=readDataFromNetwork();
_collector.emit(newValues(data));
}
}
privateStringreadDataFromNetwork(){
//模擬從網(wǎng)絡(luò)讀取數(shù)據(jù)
return"datafromnetwork";
}
publicvoidack(ObjectmsgId){
//當(dāng)Tuple被成功處理時(shí)調(diào)用
}
publicvoidfail(ObjectmsgId){
//當(dāng)Tuple處理失敗時(shí)調(diào)用
}
publicvoidclose(){
_isRunning=false;
}
}2.4.2TaskTask是Storm中最小的計(jì)算單元,每個(gè)Task執(zhí)行一個(gè)Spout或Bolt的實(shí)例。當(dāng)Topology被提交到集群時(shí),Storm會(huì)根據(jù)配置將Spout和Bolt實(shí)例化為多個(gè)Task,然后將這些Task分配給集群中的Worker進(jìn)程執(zhí)行。2.5Bolt的處理流程Bolt是Storm中的數(shù)據(jù)處理單元,負(fù)責(zé)接收Spout或其它Bolt發(fā)送的數(shù)據(jù),進(jìn)行處理后,可以將結(jié)果發(fā)送到另一個(gè)Bolt或輸出。Bolt通過實(shí)現(xiàn)IBolt接口來定義數(shù)據(jù)的接收和處理邏輯。以下是一個(gè)簡單的Bolt示例,它接收Spout發(fā)送的數(shù)據(jù),并將其轉(zhuǎn)換為大寫后輸出:publicclassUppercaseBoltimplementsIRichBolt{
privateBoltOutputCollector_collector;
publicvoidprepare(MapstormConf,TopologyContextcontext,BoltOutputCollectorcollector){
_collector=collector;
}
publicvoidexecute(Tupleinput){
Stringsentence=input.getStringByField("sentence");
StringuppercaseSentence=sentence.toUpperCase();
_collector.emit(newValues(uppercaseSentence));
_collector.ack(input);
}
publicvoidcleanup(){
//清理資源
}
publicMap<String,Object>getComponentConfiguration(){
returnnull;
}
}在這個(gè)例子中,execute方法接收一個(gè)Tuple,這個(gè)Tuple包含從Spout或其它Bolt發(fā)送的數(shù)據(jù)。Bolt處理數(shù)據(jù)后,通過_collector將結(jié)果發(fā)送出去,并調(diào)用ack方法確認(rèn)Tuple已經(jīng)被成功處理。2.6總結(jié)Storm的架構(gòu)設(shè)計(jì)使得它能夠高效地處理大規(guī)模的流數(shù)據(jù)。通過Nimbus、Supervisor、Worker、Task、Spout和Bolt的協(xié)同工作,Storm能夠?qū)崿F(xiàn)數(shù)據(jù)的實(shí)時(shí)處理和分析。無論是數(shù)據(jù)的讀取、處理還是輸出,Storm都提供了靈活的接口和機(jī)制,使得開發(fā)者能夠根據(jù)自己的需求定制數(shù)據(jù)處理流程。3Storm工作原理3.1數(shù)據(jù)流模型Storm是一個(gè)分布式實(shí)時(shí)計(jì)算系統(tǒng),其核心是基于數(shù)據(jù)流模型進(jìn)行設(shè)計(jì)的。在Storm中,數(shù)據(jù)流被視為無界、連續(xù)的數(shù)據(jù)記錄序列,這與傳統(tǒng)的批處理系統(tǒng)中處理有限數(shù)據(jù)集的概念不同。Storm的數(shù)據(jù)流模型由Spouts和Bolts構(gòu)成,它們通過Stream進(jìn)行連接。3.1.1SpoutsSpouts是數(shù)據(jù)源,負(fù)責(zé)從外部系統(tǒng)讀取數(shù)據(jù)并將其注入到Storm的拓?fù)渲?。例如,一個(gè)Spout可能從Kafka消費(fèi)消息,或者從Twitter的流API接收推文。#Spout示例代碼
fromstormimportSpout
classSimpleSpout(Spout):
definitialize(self,stormconf,context):
self._count=0
defnext_tuple(self):
#發(fā)送數(shù)據(jù)到Stream
self.emit([str(self._count)])
self._count+=1
defack(self,tup_id):
#確認(rèn)數(shù)據(jù)已被處理
pass
deffail(self,tup_id):
#處理失敗時(shí)的回調(diào)
pass3.1.2BoltsBolts是數(shù)據(jù)處理單元,它們接收來自Spouts或其他Bolts的數(shù)據(jù),執(zhí)行一些操作,然后將結(jié)果發(fā)送到下一個(gè)Bolts或輸出。Bolts可以執(zhí)行過濾、聚合、狀態(tài)管理等操作。#Bolt示例代碼
fromstormimportBolt
classSimpleBolt(Bolt):
definitialize(self,stormconf,context):
self._count=0
defprocess(self,tup):
#接收數(shù)據(jù)并處理
self._count+=1
self.emit([tup.values[0],self._count])3.2Stream組播策略在Storm中,Stream是數(shù)據(jù)流的載體,它將數(shù)據(jù)從Spouts傳輸?shù)紹olts。Storm提供了多種組播策略,用于控制數(shù)據(jù)如何從一個(gè)組件流向另一個(gè)組件。3.2.1ShuffleGroupingShuffleGrouping是一種隨機(jī)分發(fā)數(shù)據(jù)的策略,它將Stream中的數(shù)據(jù)隨機(jī)發(fā)送到所有目標(biāo)Bolts中的一個(gè)。#ShuffleGrouping示例代碼
fromstormimportTopology
classMyTopology(Topology):
def__init__(self):
super(MyTopology,self).__init__()
self.spout=SimpleSpout()
self.bolt=SimpleBolt()
defbuild(self):
self.spout.shuffle_grouping(self.bolt)3.2.2FieldsGroupingFieldsGrouping是一種基于字段的分發(fā)策略,它確保Stream中具有相同字段值的數(shù)據(jù)總是被發(fā)送到同一個(gè)Bolt。#FieldsGrouping示例代碼
classMyTopology(Topology):
defbuild(self):
self.spout.fields_grouping(self.bolt,['id'])3.3容錯(cuò)機(jī)制Storm提供了強(qiáng)大的容錯(cuò)機(jī)制,確保即使在節(jié)點(diǎn)故障的情況下,數(shù)據(jù)處理也能繼續(xù)進(jìn)行。Storm通過以下機(jī)制實(shí)現(xiàn)容錯(cuò):3.3.1TupleAcknowledgement在Storm中,每個(gè)Tuple都有一個(gè)唯一的ID。當(dāng)一個(gè)Tuple被發(fā)送到Bolt時(shí),Bolt必須調(diào)用ack方法來確認(rèn)Tuple已被成功處理。如果Bolt沒有調(diào)用ack,Spout將重新發(fā)送Tuple。#TupleAcknowledgement示例代碼
classSimpleBolt(Bolt):
defprocess(self,tup):
#處理Tuple
self.emit([tup.values[0]])
self.ack(tup)3.3.2SupervisorFailover當(dāng)一個(gè)Supervisor節(jié)點(diǎn)失敗時(shí),Storm會(huì)自動(dòng)將該節(jié)點(diǎn)上的任務(wù)重新分配到其他Supervisor節(jié)點(diǎn)上,以確保拓?fù)涞某掷m(xù)運(yùn)行。3.4狀態(tài)管理狀態(tài)管理是Storm中一個(gè)重要的特性,它允許Bolts保存和查詢狀態(tài)信息。狀態(tài)信息可以用于實(shí)現(xiàn)復(fù)雜的業(yè)務(wù)邏輯,如窗口操作、狀態(tài)查詢等。3.4.1TridentStateTrident是Storm的一個(gè)高級(jí)API,它提供了狀態(tài)管理的功能。TridentState允許Bolts保存和查詢狀態(tài)信息,這些信息可以是任何類型的數(shù)據(jù)結(jié)構(gòu),如Map、Set等。#TridentState示例代碼
fromtrident.operation.basestateimportBaseState
classMyState(BaseState):
def__init__(self):
self._state={}
defpre_save(self,checkpoint_id):
#在保存狀態(tài)前的回調(diào)
pass
defsave(self,checkpoint_id):
#保存狀態(tài)
pass
defget(self,key):
#獲取狀態(tài)
returnself._state.get(key)
defput(self,key,value):
#設(shè)置狀態(tài)
self._state[key]=value3.4.2StatefulBoltStatefulBolt是一種可以保存狀態(tài)的Bolt。在StatefulBolt中,可以使用TridentState來保存和查詢狀態(tài)信息。#StatefulBolt示例代碼
fromtrident.operation.basestateimportBaseStatefulBolt
classMyStatefulBolt(BaseStatefulBolt):
def__init__(self):
super(MyStatefulBolt,self).__init__(MyState)
defprocess(self,tup):
#使用狀態(tài)信息處理Tuple
state=self.get_state()
value=state.get(tup.values[0])
ifvalueisNone:
value=0
value+=1
state.put(tup.values[0],value)
self.emit([tup.values[0],value])通過以上介紹,我們可以看到Storm的工作原理涵蓋了數(shù)據(jù)流模型、Stream組播策略、容錯(cuò)機(jī)制和狀態(tài)管理。這些原理共同構(gòu)成了Storm的核心,使其能夠高效、可靠地處理大規(guī)模實(shí)時(shí)數(shù)據(jù)流。4Storm的部署與配置4.1集群部署步驟4.1.1環(huán)境準(zhǔn)備在部署Storm集群之前,確保所有節(jié)點(diǎn)都安裝了Java環(huán)境,版本建議為1.8或以上。此外,還需要在所有節(jié)點(diǎn)上安裝Zookeeper和Storm本身。4.1.2安裝ZookeeperZookeeper是Storm集群中用于協(xié)調(diào)和管理的組件。在所有節(jié)點(diǎn)上安裝Zookeeper,并配置myid文件,確保每個(gè)節(jié)點(diǎn)的myid唯一。4.1.3配置Storm在Storm的主節(jié)點(diǎn)上,編輯conf/storm.yaml文件,設(shè)置Storm的配置參數(shù),如Zookeeper的連接信息、nimbus和supervisor的主機(jī)名等。4.1.4分發(fā)配置使用SSH或其他工具將配置文件分發(fā)到所有節(jié)點(diǎn)。確保所有節(jié)點(diǎn)的配置一致。4.1.5啟動(dòng)Storm在主節(jié)點(diǎn)上啟動(dòng)Nimbus服務(wù),在其他節(jié)點(diǎn)上啟動(dòng)Supervisor服務(wù)。Nimbus負(fù)責(zé)接收和分配任務(wù),Supervisor負(fù)責(zé)執(zhí)行任務(wù)。4.1.6驗(yàn)證集群通過stormui命令啟動(dòng)UI服務(wù),訪問UI界面,檢查集群狀態(tài)和配置是否正確。4.2配置參數(shù)詳解Storm的配置參數(shù)主要在storm.yaml文件中定義,以下是一些關(guān)鍵參數(shù)的解釋:4.2.1nimbus.host指定Nimbus服務(wù)的主機(jī)名。例如:nimbus.host:"nimbus-host"4.2.2nimbus.thrift.portNimbus服務(wù)的Thrift端口。默認(rèn)為6627。例如:nimbus.thrift.port:66274.2.3supervisor.slots.ports定義Supervisor上用于運(yùn)行worker的端口列表。例如:supervisor.slots.ports:[6700,6701,6702]4.2.4storm.zookeeper.serversZookeeper服務(wù)器的列表。例如:storm.zookeeper.servers:["zookeeper1","zookeeper2","zookeeper3"]4.2.5storm.zookeeper.portZookeeper的端口。默認(rèn)為2181。例如:storm.zookeeper.port:21814.2.6storm.local.dirStorm在本地文件系統(tǒng)上的工作目錄。例如:storm.local.dir:"/opt/storm"4.2.7topology.workers每個(gè)topology運(yùn)行的worker數(shù)量。例如:topology.workers:24.2.8erval.secs任務(wù)心跳間隔時(shí)間,單位為秒。例如:erval.secs:34.2.9topology.max.spout.pending每個(gè)spout允許的最大未完成tuple數(shù)量。例如:topology.max.spout.pending:10004.2.10topology.message.timeout.secstuple在系統(tǒng)中存活的最長時(shí)間,單位為秒。例如:topology.message.timeout.secs:1204.2.11topology.debug是否開啟debug模式。例如:topology.debug:true4.2.12topology.metrics.bucket.size.secs用于收集metrics的時(shí)間窗口大小,單位為秒。例如:topology.metrics.bucket.size.secs:104.2.13topology.metrics.max.spout.pending每個(gè)spout允許的最大未完成tuple數(shù)量,用于metrics。例如:topology.metrics.max.spout.pending:10004.2.14topology.builtin.metrics.enabled是否啟用內(nèi)置的metrics收集。例如:topology.builtin.metrics.enabled:true4.2.15topology.builtin.metrics.max.buffer.size內(nèi)置metrics收集器的最大緩沖區(qū)大小。例如:topology.builtin.metrics.max.buffer.size:100004.2.16erval.secs內(nèi)置metrics收集器的刷新間隔,單位為秒。例如:erval.secs:604.2.17topology.builtin.metrics.exporter內(nèi)置metrics的導(dǎo)出器類型。例如:topology.builtin.metrics.exporter:"org.apache.storm.metric.LoggingMetricsExporter"4.2.18topology.builtin.metrics.exporter.period.secs內(nèi)置metrics導(dǎo)出器的周期,單位為秒。例如:topology.builtin.metrics.exporter.period.secs:604.2.19topology.builtin.metrics.exporter.log.level內(nèi)置metrics導(dǎo)出器的日志級(jí)別。例如:topology.builtin.metrics.exporter.log.level:"INFO"4.2.20topology.builtin.metrics.exporter.log.file內(nèi)置metrics導(dǎo)出器的日志文件路徑。例如:topology.builtin.metrics.exporter.log.file:"/var/log/storm/metrics.log"4.2.21topology.builtin.metrics.exporter.jmx.enabled是否啟用JMX導(dǎo)出器。例如:topology.builtin.metrics.exporter.jmx.enabled:true4.2.22topology.builtin.metrics.exporter.jmx.domainJMX導(dǎo)出器的域名稱。例如:topology.builtin.metrics.exporter.jmx.domain:"StormMetrics"4.2.23topology.builtin.metrics.exporter.jmx.objectnameJMX導(dǎo)出器的對(duì)象名稱。例如:topology.builtin.metrics.exporter.jmx.objectname:"StormMetrics:type=TopologyMetrics"4.2.24topology.builtin.metrics.exporter.jmx.portJMX導(dǎo)出器的端口。例如:topology.builtin.metrics.exporter.jmx.port:99994.2.25topology.builtin.metrics.exporter.jmx.usernameJMX導(dǎo)出器的用戶名。例如:topology.builtin.metrics.exporter.jmx.username:"storm"4.2.26topology.builtin.metrics.exporter.jmx.passwordJMX導(dǎo)出器的密碼。例如:topology.builtin.metrics.exporter.jmx.password:"storm123"4.2.27topology.builtin.metrics.exporter.statsd.enabled是否啟用StatsD導(dǎo)出器。例如:topology.builtin.metrics.exporter.statsd.enabled:true4.2.28topology.builtin.metrics.exporter.statsd.hostStatsD導(dǎo)出器的主機(jī)名。例如:topology.builtin.metrics.exporter.statsd.host:"statsd-host"4.2.29topology.builtin.metrics.exporter.statsd.portStatsD導(dǎo)出器的端口。例如:topology.builtin.metrics.exporter.statsd.port:81254.2.30topology.builtin.metrics.exporter.statsd.prefixStatsD導(dǎo)出器的前綴。例如:topology.builtin.metrics.exporter.statsd.prefix:"storm.metrics"4.2.31erval.secsStatsD導(dǎo)出器的刷新間隔,單位為秒。例如:erval.secs:604.2.32topology.builtin.metrics.exporter.statsd.max.buffer.sizeStatsD導(dǎo)出器的最大緩沖區(qū)大小。例如:topology.builtin.metrics.exporter.statsd.max.buffer.size:100004.2.33topology.builtin.metrics.exporter.statsd.log.levelStatsD導(dǎo)出器的日志級(jí)別。例如:topology.builtin.metrics.exporter.statsd.log.level:"INFO"4.2.34topology.builtin.metrics.exporter.statsd.log.fileStatsD導(dǎo)出器的日志文件路徑。例如:topology.builtin.metrics.exporter.statsd.log.file:"/var/log/storm/statsd.log"通過以上步驟和配置參數(shù)的詳細(xì)設(shè)置,可以成功部署并配置一個(gè)Storm集群,使其能夠高效地處理大數(shù)據(jù)流。5Storm性能優(yōu)化5.1優(yōu)化數(shù)據(jù)處理流程5.1.1理解Spout和Bolt的并行度在Storm中,Spout和Bolt的并行度直接影響數(shù)據(jù)處理的效率。并行度是指在一個(gè)拓?fù)渲?,Spout或Bolt的實(shí)例數(shù)量。增加并行度可以提高數(shù)據(jù)處理速度,但同時(shí)也會(huì)增加集群的資源消耗。示例:調(diào)整并行度//設(shè)置Spout的并行度為4
_conf.setNumWorkers(4);
_conf.setMaxTaskParallelism(4);
//設(shè)置Bolt的并行度為8
_conf.setNumExecutors(8);5.1.2優(yōu)化數(shù)據(jù)流的分發(fā)策略Storm提供了多種數(shù)據(jù)流分發(fā)策略,如ShuffleGrouping、FieldsGrouping等。選擇合適的數(shù)據(jù)流分發(fā)策略可以減少網(wǎng)絡(luò)延遲,提高數(shù)據(jù)處理速度。示例:使用FieldsGrouping//基于字段分組,確保相同字段值的消息被同一個(gè)Bolt實(shí)例處理
topologyBuilder.setBolt("process-bolt",newProcessBolt(),8)
.fieldsGrouping("split-bolt",newFields("word"));5.2調(diào)整集群配置5.2.1配置Storm的資源分配Storm集群的資源分配對(duì)性能有直接影響。通過調(diào)整worker.childopts、worker.heap.memory等配置,可以優(yōu)化JVM的性能,從而提高數(shù)據(jù)處理速度。示例:增加JVM堆內(nèi)存#Storm配置文件中增加JVM堆內(nèi)存
worker.childopts:"-Xms512m-Xmx1024m"5.2.2調(diào)整任務(wù)執(zhí)行的超時(shí)時(shí)間Storm中的任務(wù)執(zhí)行超時(shí)時(shí)間(topology.message.timeout.secs)決定了消息在拓?fù)渲刑幚淼臅r(shí)間上限。調(diào)整這個(gè)參數(shù)可以避免長時(shí)間未完成的任務(wù)占用資源,提高整體處理效率。示例:設(shè)置超時(shí)時(shí)間為60秒//設(shè)置拓?fù)涞某瑫r(shí)時(shí)間為60秒
_conf.setMessageTimeoutSecs(60);5.3使用高級(jí)特性提升性能5.3.1利用LocalState和GlobalStateStorm的LocalState和GlobalState特性允許在Bolt中存儲(chǔ)狀態(tài)信息,這對(duì)于需要狀態(tài)保持的復(fù)雜數(shù)據(jù)處理非常有用。合理使用這些特性可以減少數(shù)據(jù)的重復(fù)處理,提高處理速度。示例:使用LocalState//創(chuàng)建LocalState
LocalStatestate=task.getLocalState();
//存儲(chǔ)狀態(tài)
state.put("word-count",newHashMap<String,Integer>());
//讀取狀態(tài)
Map<String,Integer>wordCount=(Map<String,Integer>)state.get("word-count");5.3.2實(shí)現(xiàn)Trident操作Trident是Storm的一個(gè)高級(jí)API,提供了更高級(jí)別的抽象,如事務(wù)處理、狀態(tài)保持等。使用Trident可以簡化復(fù)雜數(shù)據(jù)流的處理,同時(shí)提高處理效率和準(zhǔn)確性。示例:使用Trident進(jìn)行狀態(tài)保持//創(chuàng)建Trident拓?fù)?/p>
TridentTopologytopology=newTridentTopology();
//定義Spout
StatefulTridentSpoutspout=newStatefulTridentSpout(newFields("word"),newWordCountState());
//定義Bolt
Functionbolt=newEach(newFields("word"),newFields("count"),newCount());
//構(gòu)建拓?fù)?/p>
topology.newStream("spout",spout)
.each(newFields("word"),newFields("count"),bolt)
.persistentAggregate(newMemoryMapState.Factory(),newCount(),newFields("count"));5.3.3使用Spout的多線程處理Storm允許Spout使用多線程處理數(shù)據(jù),這可以顯著提高數(shù)據(jù)的吞吐量。通過實(shí)現(xiàn)IMultiComponent接口,Spout可以并行處理多個(gè)數(shù)據(jù)流。示例:實(shí)現(xiàn)IMultiComponent接口publicclassMultiThreadedSpoutimplementsIRichSpout,IMultiComponent{
//實(shí)現(xiàn)IMultiComponent接口的方法
@Override
publicvoidopen(TridentSpoutConfigconf,TridentMultiComponentContextcontext){
//初始化多線程處理
}
@Override
publicvoidemit(BaseEmitcompleteEmit,TridentCollectorcollector){
//發(fā)射數(shù)據(jù)
}
}5.3.4利用JStorm的性能優(yōu)勢JStorm是Storm的一個(gè)Java實(shí)現(xiàn),它在某些方面提供了更好的性能。例如,JStorm的線程模型和內(nèi)存管理機(jī)制可以減少線程切換和垃圾回收的開銷,從而提高數(shù)據(jù)處理速度。示例:在JStorm中配置線程模型//在JStorm配置中設(shè)置線程模型
_conf.put(Config.TOPOLOGY_THREAD_MODEL,"worker");5.3.5使用ZeroMQ的高性能消息隊(duì)列Storm默認(rèn)使用ZeroMQ作為消息隊(duì)列,但可以通過調(diào)整ZeroMQ的配置來提高性能。例如,增加消息隊(duì)列的緩沖大小可以減少網(wǎng)絡(luò)延遲,提高數(shù)據(jù)處理速度。示例:增加ZeroMQ的緩沖大小#Storm配置文件中增加ZeroMQ的緩沖大小
storm.zookeeper.servers:["localhost"]
storm.zookeeper.port:2181
storm.zookeeper.root:"/storm"
storm.zookeeper.retry.times:3
erval.ms:1000
storm.zookeeper.session.timeout.ms:5000
storm.zookeeper.sync.time.ms:2000
storm.zookeeper.max.session.timeout.ms:60000
storm.zookeeper.max.reconnect.backoff.ms:10000
storm.zookeeper.min.reconnect.backoff.ms:1000
storm.zookeeper.reconnect.backoff.factor:1.5
storm.zookeeper.reconnect.backoff.max:10000
storm.zookeeper.reconnect.backoff.min:1000
storm.zookeeper.reconnect.backoff.jitter:0.1
storm.zookeeper.reconnect.backoff.max.attempts:10
erval.ms:1000
storm.zookeeper.reconnect.backoff.retry.times:3
storm.zookeeper.reconnect.backoff.retry.factor:1.5
storm.zookeeper.reconnect.backoff.retry.max:10000
storm.zookeeper.reconnect.backoff.retry.min:1000
storm.zookeeper.reconnect.backoff.retry.jitter:0.1
storm.zookeeper.reconnect.backoff.retry.max.attempts:10
erval.ms:1000
storm.zookeeper.reconnect.backoff.retry.retry.times:3
storm.zookeeper.reconnect.backoff.retry.retry.factor:1.5
storm.zookeeper.reconnect.backoff.retry.retry.max:10000
storm.zookeeper.reconnect.backoff.retry.retry.min:1000
storm.zookeeper.reconnect.backoff.retry.retry.jitter:0.1
storm.zookeeper.reconnect.backoff.retry.retry.max.attempts:10請(qǐng)注意,上述配置示例中的storm.zookeeper.*配置與ZeroMQ的緩沖大小無關(guān),這里是為了展示如何在配置文件中調(diào)整參數(shù)。實(shí)際上,調(diào)整ZeroMQ的配置需要修改與ZeroMQ相關(guān)的參數(shù),如storm.messaging.transport.*。通過上述方法,可以有效地優(yōu)化Storm的數(shù)據(jù)處理流程,調(diào)整集群配置,以及利用高級(jí)特性來提升Storm的性能。在實(shí)際應(yīng)用中,需要根據(jù)具體的數(shù)據(jù)處理需求和集群資源情況,靈活選擇和調(diào)整這些參數(shù)。6Storm實(shí)戰(zhàn)案例6.1實(shí)時(shí)數(shù)據(jù)分析6.1.1案例背景在實(shí)時(shí)數(shù)據(jù)分析場景中,Storm框架因其低延遲、高吞吐量和容錯(cuò)性而被廣泛采用。例如,一個(gè)電商網(wǎng)站可能需要實(shí)時(shí)監(jiān)控用戶行為,分析點(diǎn)擊流數(shù)據(jù),以快速響應(yīng)市場變化,優(yōu)化用戶體驗(yàn),或進(jìn)行實(shí)時(shí)廣告推薦。6.1.2原理與架構(gòu)Storm的核心架構(gòu)包括Spouts(數(shù)據(jù)源)、Bolts(處理單元)和Topology(拓?fù)浣Y(jié)構(gòu))。Spouts負(fù)責(zé)從外部數(shù)據(jù)源讀取數(shù)據(jù)并將其發(fā)送到Storm集群中,Bolts則負(fù)責(zé)數(shù)據(jù)的處理和分析,而Topology則定義了數(shù)據(jù)流的處理邏輯和流程。6.1.3示例代碼以下是一個(gè)使用Storm進(jìn)行實(shí)時(shí)數(shù)據(jù)分析的簡化示例,該示例展示了如何使用Spout和Bolt處理Twitter流數(shù)據(jù),統(tǒng)計(jì)每條推文中的單詞頻率。//Spout:讀取Twitter數(shù)據(jù)
publicclassTwitterSpoutextendsBaseRichSpout{
privateSpoutOutputCollector_collector;
privateTwitterStream_twitterStream;
@Override
publicvoidopen(Mapconf,TopologyContextcontext,SpoutOutputCollectorcollector){
_collector=collector;
_twitterStream=newTwitterStream();
_twitterStream.addListener(newStatusListener(){
@Override
publicvoidonStatus(Statusstatus){
Stringtext=status.getText();
_collector.emit(newValues(text));
}
//其他方法省略
});
}
@Override
publicvoidnextTuple(){
_twitterStream.pump();
}
}
//Bolt:處理數(shù)據(jù),統(tǒng)計(jì)單詞頻率
publicclassWordCountBoltextendsBaseBasicBolt{
privateMap<String,Integer>_wordCounts=newHashMap<>();
@Override
publicvoidexecute(BasicInputinput,BasicOutputCollectorcollector){
Stringsentence=input.getStringByField("tweet");
String[]words=sentence.split("");
for(Stringword:words){
Integercount=_wordCounts.get(word);
if(count==null){
count=0;
}
_wordCounts.put(word,count+1);
}
collector.emit(newValues(_wordCounts));
}
}
//定義Topology
TopologyBuilderbuilder=newTopologyBuilder();
builder.setSpout("twitter-spout",newTwitterSpout(),5);
builder.setBolt("word-count-bolt",newWordCountBolt(),8)
.shuffleGrouping("twitter-spout");
//提交Topology
Configconfig=newConfig();
config.setDebug(false);
LocalClustercluster=newLocalCluster();
cluster.submitTopology("word-count-topology",config,builder.createTopology());6.1.4數(shù)據(jù)樣例假設(shè)Twitter流中的一條數(shù)據(jù)為:“Justlaunchedmynewwebsite.Checkitout!#newwebsite”,Spout將讀取這條數(shù)據(jù)并將其發(fā)送到Bolt進(jìn)行處理。Bolt將這條數(shù)據(jù)分割成單詞,并統(tǒng)計(jì)每個(gè)單詞的出現(xiàn)頻率。6.1.5描述在這個(gè)示例中,TwitterSpout作為數(shù)據(jù)源,從TwitterAPI讀取實(shí)時(shí)推文數(shù)據(jù)。WordCountBolt作為處理單元,接收推文數(shù)據(jù),將其分割成單詞,并統(tǒng)計(jì)每個(gè)單詞的頻率。通過Topology定義,數(shù)據(jù)流從Spout流向Bolt,實(shí)現(xiàn)了實(shí)時(shí)數(shù)據(jù)的處理和分析。6.2流處理應(yīng)用設(shè)計(jì)6.2.1設(shè)計(jì)原則設(shè)計(jì)Storm流處理應(yīng)用時(shí),需要考慮以下原則:1.數(shù)據(jù)流的定義:明確數(shù)據(jù)的來源和流向,確保數(shù)據(jù)能夠從Spout流向Bolt,形成一個(gè)完整的處理鏈。2.容錯(cuò)性:設(shè)計(jì)應(yīng)用時(shí)應(yīng)考慮數(shù)據(jù)丟失和處理失敗的情況,通過配置和設(shè)計(jì)確保數(shù)據(jù)的可靠處理。3.性能優(yōu)化:合理配置Spout和Bolt的數(shù)量,以及數(shù)據(jù)流的分組策略,以提高處理效率和響應(yīng)速度。6.2.2示例代碼以下是一個(gè)設(shè)計(jì)用于處理實(shí)時(shí)日志數(shù)據(jù)的Storm應(yīng)用示例,該應(yīng)用包括數(shù)據(jù)清洗、數(shù)據(jù)解析和數(shù)據(jù)匯總?cè)齻€(gè)階段。//Spout:讀取日志數(shù)據(jù)
publicclassLogSpoutextendsBaseRichSpout{
privateSpoutOutputCollector_collector;
privateList<String>_logLines=Arrays.asList(
"--[10/Oct/2000:13:55:36-0700]\"GET/apache_pb.gifHTTP/1.0\"2
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025至2030年中國數(shù)顯變送智能表數(shù)據(jù)監(jiān)測研究報(bào)告
- 2025至2030年中國折疊式粗效過濾器數(shù)據(jù)監(jiān)測研究報(bào)告
- 2025至2030年中國固體催化劑數(shù)據(jù)監(jiān)測研究報(bào)告
- 2025年中國高級(jí)豪華型多功能演講臺(tái)市場調(diào)查研究報(bào)告
- 2025年中國青石魚缸市場調(diào)查研究報(bào)告
- 2025年中國素色特麗綸市場調(diào)查研究報(bào)告
- 2025年中國電子計(jì)數(shù)計(jì)重秤市場調(diào)查研究報(bào)告
- 2025年中國玻璃鋼交換罐市場調(diào)查研究報(bào)告
- 遼寧中空電纜線槽施工方案
- 心肺復(fù)蘇及人工呼吸(教學(xué)設(shè)計(jì))蒙滬版四年級(jí)下冊(cè)綜合實(shí)踐活動(dòng)
- 《化工工程制圖》完整教案
- 2023年廣東省中考試卷(語數(shù)英物化史生等共11套)帶答案解析
- DFX工藝設(shè)計(jì)方法介紹
- 洪恩識(shí)字識(shí)字卡(001-100)可直接打印剪裁
- 違反八項(xiàng)規(guī)定問題典型案例、法規(guī)依據(jù)和關(guān)注點(diǎn)
- J-STD-033D處理包裝運(yùn)輸和使用濕度回流和過程敏感設(shè)備
- 文聯(lián)述職報(bào)告
- SCI期刊的名稱縮寫與全稱對(duì)照表
- 人機(jī)料法環(huán)測檢查表
- 一年級(jí)上冊(cè)綜合實(shí)踐活動(dòng)導(dǎo)學(xué)案 各種各樣的汽車 全國通用
- 婦產(chǎn)科護(hù)理學(xué)會(huì)陰部手術(shù)病人的護(hù)理
評(píng)論
0/150
提交評(píng)論