版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
大數(shù)據(jù)處理框架:Storm:Storm的實時計算特性1大數(shù)據(jù)處理框架:Storm:實時計算特性1.1簡介1.1.1Storm框架概述Storm是一個開源的分布式實時計算系統(tǒng),由NathanMarz和BackType開發(fā),后來被Twitter收購。Storm被設(shè)計用于處理大量實時數(shù)據(jù)流,它能夠保證每個消息都被處理,并且處理過程是容錯的。Storm的核心是一個流處理引擎,它能夠?qū)?shù)據(jù)流分解成一系列的微任務(wù),然后在集群中并行執(zhí)行這些任務(wù)。Storm的架構(gòu)類似于MapReduce,但是它是為實時處理而設(shè)計的,因此它能夠處理無限的數(shù)據(jù)流,而不是有限的數(shù)據(jù)集。Storm的工作原理基于一個簡單的模型:Topology。Topology是一個有向無環(huán)圖(DAG),其中的節(jié)點是Spouts和Bolts。Spouts是數(shù)據(jù)源,負責(zé)從外部系統(tǒng)讀取數(shù)據(jù)并將其發(fā)送到Storm集群。Bolts是數(shù)據(jù)處理器,負責(zé)處理Spouts發(fā)送的數(shù)據(jù),并將處理后的數(shù)據(jù)發(fā)送到下一個Bolt或者輸出到外部系統(tǒng)。Storm通過在集群中并行執(zhí)行多個Spout和Bolt實例,實現(xiàn)了數(shù)據(jù)的實時處理和分析。1.1.2實時計算的重要性在大數(shù)據(jù)時代,實時計算變得越來越重要。傳統(tǒng)的批處理系統(tǒng),如HadoopMapReduce,雖然能夠處理大量的歷史數(shù)據(jù),但是它們的處理速度較慢,無法滿足實時處理的需求。實時計算系統(tǒng),如Storm,能夠處理無限的數(shù)據(jù)流,實時地分析和處理數(shù)據(jù),這對于許多場景來說是至關(guān)重要的。例如,在金融領(lǐng)域,實時計算可以用于實時監(jiān)測市場動態(tài),及時發(fā)現(xiàn)異常交易,防止金融欺詐。在社交媒體領(lǐng)域,實時計算可以用于實時分析用戶行為,提供個性化的推薦服務(wù)。在物聯(lián)網(wǎng)領(lǐng)域,實時計算可以用于實時監(jiān)測設(shè)備狀態(tài),及時發(fā)現(xiàn)設(shè)備故障,提高設(shè)備的可用性和可靠性。1.2實時計算特性詳解1.2.1數(shù)據(jù)流處理Storm的數(shù)據(jù)流處理是其核心特性。在Storm中,數(shù)據(jù)流被表示為一個無限的、連續(xù)的、有序的事件序列。每個事件可以是一個簡單的數(shù)據(jù)項,也可以是一個復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。Storm的數(shù)據(jù)流處理模型基于一個簡單的原則:事件驅(qū)動。當(dāng)一個新的事件到達時,Storm會將其發(fā)送到相應(yīng)的Spout或Bolt,然后Spout或Bolt會處理這個事件,并將處理后的結(jié)果發(fā)送到下一個Bolt或者輸出到外部系統(tǒng)。示例代碼下面是一個簡單的StormTopology示例,它使用了一個Spout和兩個Bolt來處理數(shù)據(jù)流:importbacktype.storm.topology.TopologyBuilder;
importbacktype.storm.tuple.Fields;
importbacktype.storm.spout.SchemeAsSpout;
importbacktype.storm.scheme.IScheme;
importbacktype.storm.scheme.StringScheme;
importbacktype.storm.StormSubmitter;
importbacktype.storm.Config;
importbacktype.storm.tuple.Values;
importbacktype.storm.task.OutputCollector;
importbacktype.storm.task.TopologyContext;
importbacktype.storm.topology.IRichBolt;
importbacktype.storm.topology.OutputFieldsDeclarer;
importbacktype.storm.topology.base.BaseRichBolt;
importbacktype.storm.topology.base.BaseRichSpout;
importbacktype.storm.utils.Utils;
importjava.util.Map;
//定義Spout
publicclassMySpoutextendsBaseRichSpout{
privateOutputCollector_collector;
privateint_sequence;
@Override
publicvoidopen(Mapconf,TopologyContextcontext,OutputCollectorcollector){
_collector=collector;
_sequence=0;
}
@Override
publicvoidnextTuple(){
_collector.emit(newValues("HelloStorm"+_sequence++));
Utils.sleep(1000);
}
@Override
publicvoiddeclareOutputFields(OutputFieldsDeclarerdeclarer){
declarer.declare(newFields("word"));
}
}
//定義Bolt
publicclassMyBoltextendsBaseRichBolt{
privateOutputCollector_collector;
@Override
publicvoidprepare(MapstormConf,TopologyContextcontext,OutputCollectorcollector){
_collector=collector;
}
@Override
publicvoidexecute(Tupleinput){
Stringword=input.getStringByField("word");
_collector.emit(newValues(word,word.length()));
}
@Override
publicvoiddeclareOutputFields(OutputFieldsDeclarerdeclarer){
declarer.declare(newFields("word","length"));
}
}
//創(chuàng)建Topology
publicclassMyTopology{
publicstaticvoidmain(String[]args)throwsException{
TopologyBuilderbuilder=newTopologyBuilder();
builder.setSpout("spout",newSchemeAsSpout<String>(newStringScheme()),5);
builder.setBolt("split",newMyBolt(),8)
.shuffleGrouping("spout");
Configconf=newConfig();
conf.setDebug(true);
StormSubmitter.submitTopology("my-topology",conf,builder.createTopology());
}
}在這個示例中,MySpout從外部系統(tǒng)讀取數(shù)據(jù),并將其發(fā)送到Storm集群。MyBolt接收MySpout發(fā)送的數(shù)據(jù),并將其長度計算出來,然后將結(jié)果發(fā)送到下一個Bolt或者輸出到外部系統(tǒng)。1.2.2容錯性Storm的另一個重要特性是其容錯性。Storm通過在集群中并行執(zhí)行多個Spout和Bolt實例,實現(xiàn)了數(shù)據(jù)處理的容錯性。當(dāng)一個Spout或Bolt實例發(fā)生故障時,Storm會自動將這個實例的數(shù)據(jù)重新分配到其他實例,從而保證了數(shù)據(jù)處理的連續(xù)性和可靠性。1.2.3可擴展性Storm的可擴展性也是其重要特性之一。Storm的Topology可以在集群中并行執(zhí)行,因此它可以處理大量的數(shù)據(jù)流。當(dāng)數(shù)據(jù)流的規(guī)模增加時,只需要增加Storm集群的規(guī)模,就可以保證數(shù)據(jù)處理的效率和性能。1.3結(jié)論Storm是一個強大的實時計算框架,它能夠處理大量的實時數(shù)據(jù)流,實時地分析和處理數(shù)據(jù)。Storm的數(shù)據(jù)流處理模型基于事件驅(qū)動,其實時計算特性基于容錯性和可擴展性。Storm的這些特性使其成為大數(shù)據(jù)實時處理的理想選擇。2大數(shù)據(jù)處理框架:Storm:安裝與配置2.1Storm的安裝步驟2.1.1環(huán)境準備在開始安裝Storm之前,確保你的系統(tǒng)滿足以下條件:操作系統(tǒng):推薦使用Linux發(fā)行版,如Ubuntu或CentOS。JDK:安裝JDK1.8或更高版本。Zookeeper:Storm依賴于Zookeeper進行協(xié)調(diào)和管理,確保Zookeeper已安裝并運行。Nimbus和Supervisor:選擇一臺機器作為Nimbus(集群的主節(jié)點),其他機器作為Supervisor(工作節(jié)點)。2.1.2下載Storm訪問Storm的官方網(wǎng)站或GitHub倉庫下載最新版本的Storm。解壓下載的文件到一個目錄,例如/opt/storm。2.1.3配置環(huán)境變量在你的~/.bashrc或~/.profile文件中添加以下行:exportSTORM_HOME=/opt/storm
exportPATH=$PATH:$STORM_HOME/bin然后運行source~/.bashrc或source~/.profile使更改生效。2.1.4啟動Storm在Nimbus和Supervisor節(jié)點上,分別啟動Nimbus和Supervisor服務(wù):#在Nimbus節(jié)點上
$STORM_HOME/bin/stormnimbus
#在Supervisor節(jié)點上
$STORM_HOME/bin/stormsupervisor2.1.5驗證安裝運行以下命令檢查Storm是否正確安裝:$STORM_HOME/bin/storm如果安裝成功,你應(yīng)該能看到Storm的命令行界面。2.2配置Storm集群2.2.1配置storm.yamlStorm集群的核心配置文件是storm.yaml。你需要在Nimbus和Supervisor節(jié)點上分別配置這個文件。Nimbus節(jié)點配置在Nimbus節(jié)點的storm.yaml中,你需要指定以下配置:nimbus.host:Nimbus節(jié)點的主機名或IP地址。supervisor.slots.ports:Supervisor節(jié)點上用于接收任務(wù)的端口列表。storm.local.dir:Storm在本地文件系統(tǒng)上的工作目錄。示例配置:nimbus.host:"nimbus-hostname"
supervisor.slots.ports:[6700,6701,6702,6703]
storm.local.dir:"/var/lib/storm"Supervisor節(jié)點配置在Supervisor節(jié)點的storm.yaml中,除了上述Nimbus節(jié)點的配置,你還需要指定:supervisor.host:Supervisor節(jié)點的主機名或IP地址。supervisor.slots.ports:與Nimbus節(jié)點配置相同,但確保端口不沖突。示例配置:nimbus.host:"nimbus-hostname"
supervisor.host:"supervisor-hostname"
supervisor.slots.ports:[6704,6705,6706,6707]
storm.local.dir:"/var/lib/storm"2.2.2配置ZookeeperStorm使用Zookeeper進行集群協(xié)調(diào)。確保Zookeeper的配置文件zoo.cfg中包含以下內(nèi)容:server.id=hostname:port:對于每個Zookeeper節(jié)點,配置其主機名和端口。示例配置:server.1=n1:2888:3888
server.2=n2:2888:3888
server.3=n3:2888:38882.2.3配置Nimbus和Supervisor在Nimbus和Supervisor節(jié)點上,確保storm.yaml中的nimbus.seeds和supervisor.hosts字段正確配置,指向集群中的所有Nimbus和Supervisor節(jié)點。示例配置:nimbus.seeds:["nimbus-hostname"]
supervisor.hosts:["supervisor-hostname1","supervisor-hostname2"]2.2.4配置日志和監(jiān)控為了便于管理和監(jiān)控,配置Storm的日志和監(jiān)控系統(tǒng)。這通常包括設(shè)置日志級別、日志文件位置以及集成監(jiān)控工具如Ganglia或Nagios。2.2.5配置安全如果集群在生產(chǎn)環(huán)境中運行,確保配置Storm的安全特性,如SSL加密和身份驗證。2.2.6配置性能根據(jù)你的工作負載,調(diào)整Storm的性能配置,如worker.childopts和topology.max.task.parallelism。2.2.7配置數(shù)據(jù)存儲Storm支持多種數(shù)據(jù)存儲選項,如HDFS、Cassandra或Riak。根據(jù)你的需求,配置數(shù)據(jù)存儲的詳細信息。2.2.8配置網(wǎng)絡(luò)確保所有節(jié)點之間的網(wǎng)絡(luò)通信暢通無阻,配置防火墻規(guī)則以允許必要的端口通信。2.2.9配置任務(wù)調(diào)度Storm允許你配置任務(wù)調(diào)度策略,如topology.scheduler.backpressure和topology.scheduler.strategy。2.2.10配置資源管理配置Storm的資源管理,如內(nèi)存和CPU使用,以優(yōu)化集群性能。2.2.11配置故障恢復(fù)設(shè)置Storm的故障恢復(fù)策略,如topology.message.timeout.secs和topology.worker.childopts,以確保集群的高可用性。2.2.12配置用戶權(quán)限如果需要,配置Storm的用戶權(quán)限和訪問控制,以限制對集群的訪問。2.2.13配置數(shù)據(jù)流Storm的數(shù)據(jù)流配置包括topology.builtin.metrics.enabled和topology.metrics.bucket.size.secs,用于監(jiān)控和優(yōu)化數(shù)據(jù)流。2.2.14配置數(shù)據(jù)源和目標(biāo)根據(jù)你的數(shù)據(jù)處理需求,配置數(shù)據(jù)源(如Kafka)和目標(biāo)(如HBase或Elasticsearch)的連接信息。2.2.15配置數(shù)據(jù)處理策略Storm允許你配置數(shù)據(jù)處理策略,如topology.task.max.failures和topology.spout.max.pending,以優(yōu)化數(shù)據(jù)處理效率。2.2.16配置數(shù)據(jù)流拓撲在storm.yaml中,你可以配置數(shù)據(jù)流拓撲的詳細信息,如topology.workers和topology.executors。2.2.17配置數(shù)據(jù)流組件配置數(shù)據(jù)流組件,如Spouts和Bolts的參數(shù),以優(yōu)化數(shù)據(jù)處理邏輯。2.2.18配置數(shù)據(jù)流任務(wù)設(shè)置數(shù)據(jù)流任務(wù)的配置,如topology.topology-class-name和topology.topology-id,以確保任務(wù)的正確執(zhí)行。2.2.19配置數(shù)據(jù)流監(jiān)控配置數(shù)據(jù)流的監(jiān)控,如topology.metrics.enabled和topology.metrics.sample.rate,以實時監(jiān)控數(shù)據(jù)流狀態(tài)。2.2.20配置數(shù)據(jù)流優(yōu)化根據(jù)你的數(shù)據(jù)流特性,配置優(yōu)化策略,如topology.message.timeout.secs和topology.spout.wait.strategy。2.2.21配置數(shù)據(jù)流容錯設(shè)置數(shù)據(jù)流的容錯配置,如topology.task.max.failures和topology.spout.max.pending,以增強數(shù)據(jù)流的魯棒性。2.2.22配置數(shù)據(jù)流擴展性為了支持大規(guī)模數(shù)據(jù)處理,配置數(shù)據(jù)流的擴展性,如topology.workers和topology.executors。2.2.23配置數(shù)據(jù)流性能根據(jù)你的性能需求,調(diào)整數(shù)據(jù)流的性能配置,如topology.worker.childopts和topology.worker.max.heap.size。2.2.24配置數(shù)據(jù)流安全如果需要,配置數(shù)據(jù)流的安全特性,如SSL加密和身份驗證。2.2.25配置數(shù)據(jù)流日志設(shè)置數(shù)據(jù)流的日志配置,如日志級別和日志文件位置,以方便調(diào)試和監(jiān)控。2.2.26配置數(shù)據(jù)流監(jiān)控工具集成監(jiān)控工具,如Ganglia或Nagios,以實時監(jiān)控數(shù)據(jù)流的健康狀態(tài)。2.2.27配置數(shù)據(jù)流資源管理配置數(shù)據(jù)流的資源管理,如內(nèi)存和CPU使用,以優(yōu)化集群資源分配。2.2.28配置數(shù)據(jù)流故障恢復(fù)設(shè)置數(shù)據(jù)流的故障恢復(fù)策略,如topology.message.timeout.secs和topology.worker.childopts,以確保數(shù)據(jù)流的連續(xù)性和可靠性。2.2.29配置數(shù)據(jù)流用戶權(quán)限如果需要,配置數(shù)據(jù)流的用戶權(quán)限和訪問控制,以限制對數(shù)據(jù)流的訪問。2.2.30配置數(shù)據(jù)流數(shù)據(jù)存儲根據(jù)你的數(shù)據(jù)存儲需求,配置數(shù)據(jù)流的數(shù)據(jù)存儲選項,如HDFS、Cassandra或Riak。2.2.31配置數(shù)據(jù)流網(wǎng)絡(luò)確保數(shù)據(jù)流組件之間的網(wǎng)絡(luò)通信暢通無阻,配置防火墻規(guī)則以允許必要的端口通信。2.2.32配置數(shù)據(jù)流任務(wù)調(diào)度設(shè)置數(shù)據(jù)流任務(wù)的調(diào)度策略,如topology.scheduler.backpressure和topology.scheduler.strategy,以優(yōu)化任務(wù)執(zhí)行。2.2.33配置數(shù)據(jù)流數(shù)據(jù)源和目標(biāo)配置數(shù)據(jù)流的數(shù)據(jù)源和目標(biāo)連接信息,如Kafka和HBase,以支持數(shù)據(jù)的輸入和輸出。2.2.34配置數(shù)據(jù)流數(shù)據(jù)處理策略根據(jù)你的數(shù)據(jù)處理需求,配置數(shù)據(jù)流的數(shù)據(jù)處理策略,如topology.task.max.failures和topology.spout.max.pending,以優(yōu)化數(shù)據(jù)處理邏輯。2.2.35配置數(shù)據(jù)流數(shù)據(jù)流拓撲在storm.yaml中,配置數(shù)據(jù)流拓撲的詳細信息,如topology.workers和topology.executors,以支持大規(guī)模數(shù)據(jù)處理。2.2.36配置數(shù)據(jù)流數(shù)據(jù)流組件配置數(shù)據(jù)流組件,如Spouts和Bolts的參數(shù),以優(yōu)化數(shù)據(jù)處理性能。2.2.37配置數(shù)據(jù)流數(shù)據(jù)流任務(wù)設(shè)置數(shù)據(jù)流任務(wù)的配置,如topology.topology-class-name和topology.topology-id,以確保數(shù)據(jù)流任務(wù)的正確執(zhí)行。2.2.38配置數(shù)據(jù)流數(shù)據(jù)流監(jiān)控配置數(shù)據(jù)流的監(jiān)控,如topology.metrics.enabled和topology.metrics.sample.rate,以實時監(jiān)控數(shù)據(jù)流狀態(tài)。2.2.39配置數(shù)據(jù)流數(shù)據(jù)流優(yōu)化根據(jù)你的數(shù)據(jù)流特性,配置優(yōu)化策略,如topology.message.timeout.secs和topology.spout.wait.strategy。2.2.40配置數(shù)據(jù)流數(shù)據(jù)流容錯設(shè)置數(shù)據(jù)流的容錯配置,如topology.task.max.failures和topology.spout.max.pending,以增強數(shù)據(jù)流的魯棒性。2.2.41配置數(shù)據(jù)流數(shù)據(jù)流擴展性為了支持大規(guī)模數(shù)據(jù)處理,配置數(shù)據(jù)流的擴展性,如topology.workers和topology.executors。2.2.42配置數(shù)據(jù)流數(shù)據(jù)流性能根據(jù)你的性能需求,調(diào)整數(shù)據(jù)流的性能配置,如`top3Storm的基本架構(gòu)3.1拓撲結(jié)構(gòu)解析在Storm中,拓撲(Topology)是數(shù)據(jù)流處理的基本單元,它由一組Spout和Bolt組成,通過定義它們之間的連接來構(gòu)建數(shù)據(jù)處理流程。拓撲結(jié)構(gòu)的設(shè)計靈活性和可擴展性是Storm實時計算特性的重要體現(xiàn)。3.1.1SpoutSpout是數(shù)據(jù)流的源頭,負責(zé)從外部數(shù)據(jù)源(如Kafka、RabbitMQ或數(shù)據(jù)庫)讀取數(shù)據(jù),并將其發(fā)送到Storm集群中進行處理。Spout可以是可靠的或不可靠的,這取決于數(shù)據(jù)處理的語義需求。示例:KafkaSpout//導(dǎo)入必要的庫
importorg.apache.storm.kafka.bolt.KafkaBolt;
importorg.apache.storm.kafka.spout.KafkaSpout;
importorg.apache.storm.kafka.spout.KafkaSpoutConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutStreamType;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentStateMapper;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapper;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilder;
importorg.apache.storm.kafka.spout.KafkaSpoutTridentTupleMapperBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfigBuilderConfig;
//創(chuàng)建KafkaSpout配置
KafkaSpoutConfig<String,String>spoutConfig=KafkaSpoutConfig.builder("localhost:9092","test-topic")
.setSpoutStreamType(KafkaSpoutStreamType.NOT_SERIALIZED)
.setGroupId("storm-group")
.build();
//創(chuàng)建KafkaSpout
KafkaSpout<String,String>kafkaSpout=newKafkaSpout<>(spoutConfig);在上述代碼中,我們首先創(chuàng)建了一個KafkaSpoutConfig對象,指定了Kafka的Broker地址和主題名稱。然后,我們使用這個配置對象來實例化一個KafkaSpout,這將作為數(shù)據(jù)流的源頭。3.1.2BoltBolt是數(shù)據(jù)流處理的處理單元,它接收來自Spout或其他Bolt的數(shù)據(jù),執(zhí)行處理邏輯,并將結(jié)果發(fā)送到下一個Bolt或輸出到外部系統(tǒng)。Bolt可以實現(xiàn)復(fù)雜的數(shù)據(jù)處理邏輯,如過濾、聚合、連接等。示例:WordCountBolt//導(dǎo)入必要的庫
importorg.apache.storm.task.OutputCollector;
importorg.apache.storm.task.TopologyContext;
importorg.apache.storm.topology.OutputFieldsDeclarer;
importorg.apache.storm.topology.base.BaseRichBolt;
importorg.apache.storm.tuple.Fields;
importorg.apache.storm.tuple.Tuple;
importorg.apache.storm.tuple.Values;
importjava.util.Map;
//定義WordCountBolt
publicclassWordCountBoltextendsBaseRichBolt{
privateOutputCollectorcollector;
privateMap<String,Integer>wordCounts;
@Override
publicvoidprepare(MapstormConf,TopologyContextcontext,OutputCollectorcollector){
this.collector=collector;
this.wordCounts=newHashMap<>();
}
@Override
publicvoidexecute(Tupleinput){
Stringword=input.getStringByField("word");
Integercount=wordCounts.get(word);
if(count==null){
count=0;
}
wordCounts.put(word,count+1);
collector.emit(newValues(word,count+1));
}
@Override
publicvoiddeclareOutputFields(OutputFieldsDeclarerdeclarer){
declarer.declare(newFields("word","count"));
}
}在上述代碼中,我們定義了一個WordCountBolt類,它繼承自BaseRichBolt。在prepare方法中,我們初始化了一個OutputCollector和一個Map來存儲單詞計數(shù)。execute方法接收一個Tuple,從中提取單詞,并更新計數(shù)。最后,我們通過collector將結(jié)果發(fā)送出去。declareOutputFields方法用于聲明Bolt輸出的字段。3.2Spout與Bolt詳解Spout和Bolt是Storm中數(shù)據(jù)流處理的兩個核心組件,它們通過定義數(shù)據(jù)流的源頭和處理邏輯,共同構(gòu)建了Storm的實時計算能力。3.2.1SpoutSpout負責(zé)從外部數(shù)據(jù)源讀取數(shù)據(jù),并將其轉(zhuǎn)換為Storm可以處理的格式。Spout可以是可靠的,這意味著Storm會確保每條數(shù)據(jù)至少被處理一次,即使在系統(tǒng)故障的情況下也是如此。不可靠的Spout則不提供這樣的保證,數(shù)據(jù)可能會在故障時丟失。3.2.2BoltBolt是數(shù)據(jù)流處理的執(zhí)行單元,它接收數(shù)據(jù),執(zhí)行處理邏輯,并將結(jié)果發(fā)送到下一個Bolt或輸出到外部系統(tǒng)。Bolt可以實現(xiàn)各種數(shù)據(jù)處理邏輯,如過濾、聚合、連接等。Bolt的處理邏輯是通過execute方法實現(xiàn)的,該方法接收一個Tuple作為輸入,并通過OutputCollector將結(jié)果發(fā)送出去。3.2.3連接Spout和Bolt之間的連接是通過定義數(shù)據(jù)流的流向來實現(xiàn)的。在Storm中,數(shù)據(jù)流的流向是通過拓撲結(jié)構(gòu)中的箭頭來表示的。例如,如果一個Bolt需要接收來自一個Spout的數(shù)據(jù),我們可以在拓撲結(jié)構(gòu)中定義一個從Spout到Bolt的箭頭。3.2.4示例:構(gòu)建拓撲//導(dǎo)入必要的庫
importorg.apache.storm.Config;
importorg.apache.storm.LocalCluster;
importorg.apache.storm.StormSubmitter;
importorg.apache.storm.topology.TopologyBuilder;
importorg.apache.storm.tuple.Fields;
//創(chuàng)建拓撲構(gòu)建器
TopologyBuilderbuilder=newTopologyBuilder();
//添加Spout
builder.setSpout("kafka-spout",kafkaSpout,1);
//添加Bolt
builder.setBolt("word-count-bolt",newWordCountBolt(),2)
.shuffleGrouping("kafka-spout");
//創(chuàng)建配置
Configconf=newConfig();
conf.setDebug(false);
//提交拓撲
try{
StormSubmitter.submitTopology("word-count-topology",conf,builder.createTopology());
}catch(Exceptione){
e.printStackTrace();
}在上述代碼中,我們首先創(chuàng)建了一個TopologyBuilder對象。然后,我們添加了一個KafkaSpout和一個WordCountBolt,并定義了它們之間的連接。最后,我們創(chuàng)建了一個配置對象,并使用StormSubmitter提交拓撲到Storm集群中。通過上述示例,我們可以看到Storm如何通過Spout和Bolt構(gòu)建實時數(shù)據(jù)處理流程,以及如何定義它們之間的連接。這種靈活的架構(gòu)使得Storm能夠處理各種實時數(shù)據(jù)流場景,從簡單的數(shù)據(jù)過濾到復(fù)雜的事件處理和流式計算。4實時數(shù)據(jù)流處理4.1數(shù)據(jù)流處理模型在大數(shù)據(jù)處理領(lǐng)域,數(shù)據(jù)流處理模型是處理實時數(shù)據(jù)的關(guān)鍵。不同于批處理,數(shù)據(jù)流處理需要系統(tǒng)能夠持續(xù)地接收、處理和響應(yīng)數(shù)據(jù),而這些數(shù)據(jù)通常是以高速、連續(xù)的方式產(chǎn)生的。Storm,作為一款開源的分布式實時計算系統(tǒng),提供了強大的數(shù)據(jù)流處理能力,其核心模型基于“流”和“拓撲”。4.1.1流(Stream)在Storm中,流是數(shù)據(jù)的連續(xù)序列,可以看作是無限的數(shù)據(jù)集。流中的數(shù)據(jù)以元組(tuple)的形式存在,每個元組包含一組字段,這些字段可以是任何類型的數(shù)據(jù)。流可以來源于各種數(shù)據(jù)源,如消息隊列、數(shù)據(jù)庫、傳感器等,也可以是Storm內(nèi)部組件生成的數(shù)據(jù)。4.1.2拓撲(Topology)拓撲是Storm中數(shù)據(jù)流處理的基本單元,它定義了數(shù)據(jù)流的處理邏輯和數(shù)據(jù)流的流向。一個拓撲由多個Bolt和Spout組成,通過定義它們之間的連接,形成一個有向無環(huán)圖(DAG)。Spout是數(shù)據(jù)流的源頭,負責(zé)從外部數(shù)據(jù)源讀取數(shù)據(jù)并將其發(fā)送到Storm集群中。Bolt則是數(shù)據(jù)流的處理器,它可以接收來自一個或多個Spout或Bolt的數(shù)據(jù),進行處理后,再將數(shù)據(jù)發(fā)送到下一個Bolt或輸出到外部系統(tǒng)。4.1.3示例:使用Storm進行實時數(shù)據(jù)流處理假設(shè)我們有一個實時日志數(shù)據(jù)流,需要對日志中的關(guān)鍵詞進行實時計數(shù)。下面是一個使用Storm實現(xiàn)的簡單示例://Spout:讀取實時日志數(shù)據(jù)
publicclassLogSpoutextendsBaseRichSpout{
privateSpoutOutputCollector_collector;
privateRandom_rand=newRandom();
publicvoidopen(Mapconf,TopologyContextcontext,SpoutOutputCollectorcollector){
this._collector=collector;
}
publicvoidnextTuple(){
String[]keywords={"error","warning","info"};
Stringkeyword=keywords[_rand.nextInt(keywords.length)];
_collector.emit(newValues(keyword));
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
//Bolt:對關(guān)鍵詞進行計數(shù)
publicclassKeywordCounterBoltextendsBaseBasicBolt{
privateMap<String,Integer>_counts=newHashMap<>();
publicvoidexecute(BasicInputinput,BasicOutputCollectorcollector){
Stringkeyword=input.getStringByField("keyword");
Integercount=_counts.get(keyword);
if(count==null){
count=0;
}
_counts.put(keyword,count+1);
collector.emit(newValues(keyword,count+1));
}
}
//定義拓撲
TopologyBuilderbuilder=newTopologyBuilder();
builder.setSpout("log-spout",newLogSpout(),5);
builder.setBolt("counter-bolt",newKeywordCounterBolt(),8)
.shuffleGrouping("log-spout");
//提交拓撲
Configconfig=newConfig();
LocalClustercluster=newLocalCluster();
cluster.submitTopology("log-counter",config,builder.createTopology());在這個示例中,LogSpout模擬了一個實時日志數(shù)據(jù)源,每秒生成一個隨機關(guān)鍵詞。KeywordCounterBolt則負責(zé)接收這些關(guān)鍵詞,并進行計數(shù)。拓撲定義了數(shù)據(jù)流的流向,即從LogSpout到KeywordCounterBolt。4.2窗口與滑動窗口應(yīng)用在實時數(shù)據(jù)流處理中,窗口是一個重要的概念,它允許系統(tǒng)在一段時間內(nèi)或一定數(shù)量的數(shù)據(jù)上進行聚合操作。窗口可以分為時間窗口和滑動窗口。4.2.1時間窗口時間窗口定義了一個固定的時間段,在這個時間段內(nèi)的數(shù)據(jù)將被聚合處理。例如,可以定義一個1分鐘的時間窗口,對過去1分鐘內(nèi)的數(shù)據(jù)進行匯總。4.2.2滑動窗口滑動窗口則是在時間窗口的基礎(chǔ)上,定義了一個窗口的滑動步長。例如,定義一個1分鐘的時間窗口和30秒的滑動步長,意味著每30秒,系統(tǒng)將對過去1分鐘內(nèi)的數(shù)據(jù)進行一次匯總,然后窗口向前滑動30秒,繼續(xù)對新的1分鐘內(nèi)的數(shù)據(jù)進行匯總。4.2.3示例:使用滑動窗口進行實時數(shù)據(jù)流處理假設(shè)我們需要對實時日志數(shù)據(jù)流中的關(guān)鍵詞進行每分鐘的滑動窗口計數(shù),窗口滑動步長為30秒。下面是一個使用Storm實現(xiàn)的示例://定義滑動窗口Bolt
publicclassSlidingWindowBoltextendsBaseRichBolt{
privateSlidingWindow_window=newSlidingWindow(60,30);//1分鐘窗口,30秒滑動步長
privateMap<String,Integer>_counts=newHashMap<>();
publicvoidprepare(MapstormConf,TopologyContextcontext,OutputCollectorcollector){
this.collector=collector;
}
publicvoidexecute(Tupleinput){
Stringkeyword=input.getStringByField("keyword");
_windo
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度會展中心場地租賃及配套服務(wù)補充協(xié)議3篇
- 2025年個人承包文化創(chuàng)意產(chǎn)業(yè)合同(創(chuàng)意設(shè)計)2篇
- 2024版支付擔(dān)保合同范本
- 2024生物質(zhì)鍋爐燃料供應(yīng)及銷售合同3篇
- 2024石膏板供應(yīng)商戰(zhàn)略合作采購合同模板3篇
- 2025年度專業(yè)廚師團隊廚房服務(wù)承包協(xié)議3篇
- 2024綠化土地租賃與生態(tài)補償及綠化管理合同3篇
- 2024鐵路貨運車輛安全檢測及維護服務(wù)合同實施細則3篇
- 多媒體應(yīng)用基礎(chǔ)知到智慧樹章節(jié)測試課后答案2024年秋安徽大學(xué)
- 2025年充電樁充電站運營維護及升級改造合同3篇
- 2024年秋季新統(tǒng)編版七年級上冊道德與法治全冊教案
- 20以內(nèi)的加法口算練習(xí)題4000題 210
- 2024年涉密人員考試試題庫保密基本知識試題附答案(考試直接用)
- 2024年桂林中考物理試卷
- 儲能投資方案計劃書
- HG∕T 4286-2017 搪玻璃換熱管
- 二年級上冊100道口算題大全(全冊完整版18份每份100道)
- HJ212-2017污染物在線監(jiān)控(監(jiān)測)系統(tǒng)數(shù)據(jù)傳輸標(biāo)準
- 電力外線施工方案
- 基于Android平臺人臉識別系統(tǒng)的設(shè)計與實現(xiàn)
- 【供應(yīng)鏈視角下的光明乳業(yè)存貨管理問題研究9700字】
評論
0/150
提交評論