版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
大数据处理框架:Storm:编写第一个Storm应用1大数据处理框架:Storm:编写第一个Storm应用1.1介绍Storm基础1.1.1Storm框架概述Storm是一个免费开源、分布式、容错的实时计算系统。它提供了一种简单而强大的模型来处理无界数据流,特别适合于实时分析、在线机器学习、持续计算、分布式远程过程调用(RPC)和ETL(提取、转换、加载)等场景。Storm的设计灵感来源于Twitter的分布式计算框架,它能够保证每个消息都被处理,并且处理过程是容错的。Storm的核心概念是拓扑(Topology),它是一个有向无环图(DAG),由多个Spout和Bolt组成。Spout是数据源,负责从外部系统读取数据并将其注入到Storm的计算流中。Bolt则是数据处理单元,可以执行各种计算任务,如过滤、聚合、函数应用等。Bolt可以连接到多个Spout或其他Bolt,形成复杂的数据处理流程。1.1.2Storm的工作原理Storm的工作原理基于流处理(StreamProcessing)模型。当一个Storm拓扑被提交到集群中运行时,它会被分解成多个任务(Task),每个任务运行在一个工作线程(WorkerThread)上。这些任务分布在集群中的多个节点上,每个节点运行一个或多个工作进程(WorkerProcess)。每个工作进程负责执行拓扑中的一部分任务,这样就实现了并行处理。Storm使用Zookeeper作为协调服务,确保集群的高可用性和一致性。当数据流通过拓扑时,Storm确保每个消息至少被处理一次,这被称为至少一次语义(At-Least-OnceSemantics)。为了实现更高级别的语义,如恰好一次语义(Exactly-OnceSemantics),Storm提供了确认机制(Acking)和故障恢复机制(FaultTolerance)。示例:编写一个简单的Storm拓扑importorg.apache.storm.Config;
importorg.apache.storm.LocalCluster;
importorg.apache.storm.StormSubmitter;
importorg.apache.storm.topology.TopologyBuilder;
importorg.apache.storm.tuple.Fields;
publicclassSimpleTopology{
publicstaticvoidmain(String[]args)throwsException{
TopologyBuilderbuilder=newTopologyBuilder();
//定义Spout,这里是模拟数据源
builder.setSpout("spout",newRandomSentenceSpout(),5);
//定义Bolt,这里是进行单词分割
builder.setBolt("split",newSplitSentenceBolt(),8)
.shuffleGrouping("spout");
//定义Bolt,这里是进行单词计数
builder.setBolt("count",newWordCountBolt(),12)
.fieldsGrouping("split",newFields("word"));
Configconfig=newConfig();
config.setDebug(true);
if(args!=null&&args.length>0){
config.setNumWorkers(3);
StormSubmitter.submitTopology(args[0],config,builder.createTopology());
}else{
LocalClustercluster=newLocalCluster();
cluster.submitTopology("simple",config,builder.createTopology());
Thread.sleep(10000);
cluster.shutdown();
}
}
}在这个例子中,我们创建了一个拓扑,它包含一个Spout和两个Bolt。Spout生成随机句子,第一个Bolt将句子分割成单词,第二个Bolt对单词进行计数。通过shuffleGrouping和fieldsGrouping,我们定义了数据流如何在Bolt之间传输。1.1.3Storm与Hadoop和Spark的比较Storm与Hadoop和Spark的主要区别在于处理数据的方式和场景。Hadoop主要用于批处理,处理静态的、有界的数据集,而Storm则专注于流处理,处理实时的、无界的数据流。Spark虽然也支持流处理,但它的流处理是基于微批处理的模型,而Storm则是真正的流处理模型,能够提供更低的延迟。处理模型:Storm提供的是实时流处理,而Hadoop和Spark提供的是批处理或基于微批处理的流处理。延迟:Storm的延迟通常在毫秒级,而Hadoop和Spark的延迟可能在秒级或更高。容错性:Storm通过确认机制和故障恢复机制提供了强大的容错性,确保每个消息至少被处理一次。编程模型:Storm的编程模型基于Spout和Bolt,而Hadoop和Spark则分别基于MapReduce和RDD(弹性分布式数据集)或DataFrame。Storm在实时数据处理领域具有独特的优势,特别是在需要低延迟和高吞吐量的场景中。然而,选择哪个框架取决于具体的应用需求和场景。2搭建Storm开发环境2.1安装Java和Maven2.1.1Java安装下载JavaSDK访问Oracle官方网站下载JavaSDK11。根据你的操作系统选择合适的版本进行下载。安装JavaSDK双击下载的.tar.gz或.zip文件进行解压。将解压后的目录移动到你希望安装Java的目录下,例如/usr/lib/jvm。配置环境变量打开终端,编辑~/.bashrc或~/.zshrc文件,添加以下行:exportJAVA_HOME=/path/to/your/jdk
exportPATH=$JAVA_HOME/bin:$PATH保存文件并运行source~/.bashrc或source~/.zshrc使更改生效。2.1.2Maven安装下载Maven访问Maven官方网站下载Maven的.tar.gz或.zip文件。安装Maven解压下载的文件到/usr/local目录下。将解压后的目录重命名为apache-maven。配置环境变量编辑~/.bashrc或~/.zshrc文件,添加以下行:exportM2_HOME=/usr/local/apache-maven
exportPATH=$M2_HOME/bin:$PATH保存文件并运行source~/.bashrc或source~/.zshrc使更改生效。验证安装在终端中运行java-version和mvn-version命令,确认Java和Maven已正确安装。2.2配置Storm环境2.2.1下载Storm访问Storm官网访问ApacheStorm官方网站下载Storm的最新版本。解压Storm将下载的.tar.gz文件解压到/usr/local目录下。2.2.2配置Storm环境变量编辑环境变量在~/.bashrc或~/.zshrc文件中添加以下行:exportSTORM_HOME=/usr/local/apache-storm
exportPATH=$STORM_HOME/bin:$PATH保存文件并运行source~/.bashrc或source~/.zshrc使更改生效。2.2.3配置StormYAML文件编辑Storm配置打开$STORM_HOME/conf/storm.yaml文件,配置Storm的环境参数,例如Nimbus和Supervisor的主机和端口。2.2.4验证Storm安装运行Storm示例Storm自带了一些示例应用,可以通过运行这些示例来验证Storm是否正确安装。在终端中运行以下命令:cd$STORM_HOME
bin/stormjarexamples/storm-starter/storm-starter-topology-*.jarorg.apache.storm.starter.WordCountTopologywordcount观察终端输出,确认WordCount拓扑是否成功运行。2.3验证Storm安装2.3.1运行WordCount示例WordCount拓扑Storm的WordCount示例是一个简单的流处理应用,它接收文本流,将文本分割成单词,然后计算每个单词出现的次数。代码示例下面是一个简化版的WordCount拓扑的Spout和Bolt代码示例://WordSpout.java
publicclassWordSpoutextendsBaseRichSpout{
privatestaticfinallongserialVersionUID=1L;
privateSpoutOutputCollector_collector;
privateRandom_rand=newRandom();
privateList<String>_words=Arrays.asList("hello","world","apache","storm");
publicvoidopen(Mapconf,TopologyContextcontext,SpoutOutputCollectorcollector){
_collector=collector;
}
publicvoidnextTuple(){
Stringword=_words.get(_rand.nextInt(_words.size()));
_collector.emit(newValues(word));
try{
Thread.sleep(100);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
//WordCounterBolt.java
publicclassWordCounterBoltextendsBaseBasicBolt{
privatestaticfinallongserialVersionUID=1L;
privateMap<String,Integer>_counts=newHashMap<>();
publicvoidexecute(BasicInputinput,BasicOutputCollectorcollector){
Stringword=input.getStringByField("word");
Integercount=_counts.get(word);
if(count==null){
count=0;
}
_counts.put(word,count+1);
collector.emit(newValues(word,count+1));
}
publicMap<String,Object>getComponentConfiguration(){
Configconf=newConfig();
conf.setMaxTaskParallelism(1);
returnconf;
}
}运行拓扑将上述代码整合到一个Maven项目中,然后使用以下命令运行WordCount拓扑:mvncompileexec:java-Dexec.mainClass=org.apache.storm.starter.WordCountTopology观察终端输出,确认拓扑是否成功运行并处理数据。通过以上步骤,你已经成功搭建了Storm的开发环境,并验证了安装是否正确。接下来,你可以开始使用Storm进行大数据流处理应用的开发了。3编写第一个Storm应用3.1创建Topology结构在开始编写Storm应用之前,首先需要理解Topology的基本概念。Topology在Storm中是应用的基本单位,它由一组Spout和Bolt组成,这些组件通过流(Stream)连接,形成一个数据处理的网络。Topology一旦提交到Storm集群,就会持续运行,直到被显式停止。3.1.1步骤1:导入必要的库importorg.apache.storm.StormSubmitter;
importorg.apache.storm.config.Config;
importorg.apache.storm.spout.SpoutOutputCollector;
importorg.apache.storm.task.OutputCollector;
importorg.apache.storm.task.TopologyContext;
importorg.apache.storm.topology.OutputFieldsDeclarer;
importorg.apache.storm.topology.TopologyBuilder;
importorg.apache.storm.topology.base.BaseRichBolt;
importorg.apache.storm.topology.base.BaseRichSpout;
importorg.apache.storm.tuple.Fields;
importorg.apache.storm.tuple.Tuple;
importorg.apache.storm.tuple.Values;
importorg.apache.storm.utils.Utils;3.1.2步骤2:定义TopologypublicclassWordCountTopology{
publicstaticvoidmain(String[]args)throwsException{
TopologyBuilderbuilder=newTopologyBuilder();
//定义Spout和Bolt
builder.setSpout("spout",newWordSpout(),5);
builder.setBolt("split",newSplitSentenceBolt(),8)
.shuffleGrouping("spout");
builder.setBolt("count",newWordCounterBolt(),12)
.fieldsGrouping("split",newFields("word"));
//配置Topology
Configconfig=newConfig();
config.setDebug(true);
//提交Topology到Storm集群
StormSubmitter.submitTopology("word-count",config,builder.createTopology());
}
}3.2定义Spout和Bolt3.2.1Spout:数据源Spout是Storm中的数据源,负责生成数据流。在WordCount应用中,我们定义一个简单的Spout,用于生成包含句子的流。publicclassWordSpoutextendsBaseRichSpout{
privateSpoutOutputCollector_collector;
privateint_sentences;
publicvoidopen(Mapconf,TopologyContextcontext,SpoutOutputCollectorcollector){
_collector=collector;
_sentences=0;
}
publicvoidnextTuple(){
String[]sentences=newString[]{
"thecowjumpedoverthemoon",
"anappleadaykeepsthedoctoraway",
"fourscoreandsevenyearsago",
"snowwhiteandthesevendwarfs",
"iamattwowithnature"
};
//发送数据
_collector.emit(newValues(sentences[_sentences%sentences.length]));
_sentences++;
//模拟数据生成的延迟
Utils.sleep(1000);
}
publicvoiddeclareOutputFields(OutputFieldsDeclarerdeclarer){
declarer.declare(newFields("sentence"));
}
}3.2.2Bolt:数据处理单元Bolt是Storm中的数据处理单元,负责接收流中的数据,进行处理,然后将结果发送到下一个Bolt或输出。SplitSentenceBolt:分割句子publicclassSplitSentenceBoltextendsBaseRichBolt{
privateOutputCollector_collector;
publicvoidprepare(MapstormConf,TopologyContextcontext,OutputCollectorcollector){
_collector=collector;
}
publicvoidexecute(Tupleinput){
Stringsentence=input.getStringByField("sentence");
for(Stringword:sentence.split("")){
_collector.emit(newValues(word));
}
_collector.ack(input);
}
publicvoiddeclareOutputFields(OutputFieldsDeclarerdeclarer){
declarer.declare(newFields("word"));
}
}WordCounterBolt:计数单词publicclassWordCounterBoltextendsBaseRichBolt{
privateMap<String,Integer>_counts;
privateOutputCollector_collector;
publicvoidprepare(MapstormConf,TopologyContextcontext,OutputCollectorcollector){
_collector=collector;
_counts=newHashMap<>();
}
publicvoidexecute(Tupleinput){
Stringword=input.getStringByField("word");
Integercount=_counts.get(word);
if(count==null){
count=0;
}
_counts.put(word,count+1);
_collector.ack(input);
}
publicvoiddeclareOutputFields(OutputFieldsDeclarerdeclarer){
//由于WordCounterBolt不发送数据到下一个Bolt,这里不需要声明输出字段
}
}3.3实现WordCount应用WordCount应用的核心是统计流中单词的出现次数。通过定义Spout生成句子流,SplitSentenceBolt将句子分割成单词,WordCounterBolt统计每个单词的出现次数。3.3.1步骤3:处理流在Topology中,Spout生成的流被发送到SplitSentenceBolt,SplitSentenceBolt将每个句子分割成单词,然后将单词流发送到WordCounterBolt进行计数。3.4提交Topology到Storm集群最后一步是将定义好的Topology提交到Storm集群中运行。在WordCountTopology类的main方法中,我们使用StormSubmitter.submitTopology方法提交Topology。StormSubmitter.submitTopology("word-count",config,builder.createTopology());这里的“word-count”是Topology的名称,config是配置信息,builder.createTopology()是创建的Topology实例。通过以上步骤,我们完成了第一个Storm应用的编写和提交。这个应用展示了如何使用Spout和Bolt来处理流数据,以及如何将Topology提交到Storm集群中运行。4深入理解Storm4.1Storm的并行处理机制4.1.1并行处理的重要性在大数据处理中,并行处理是关键。它允许数据在多个处理器或计算节点上同时处理,从而显著提高处理速度和效率。Storm,作为实时流处理框架,通过其独特的并行处理机制,能够高效地处理大量实时数据。4.1.2Storm的并行处理架构Storm的并行处理基于拓扑(Topology)和工作流(Workflow)的概念。一个拓扑定义了数据流的处理逻辑,包括数据源(Spout)、数据处理单元(Bolt)以及它们之间的连接。每个Spout和Bolt都可以在多个线程或进程上并行运行,形成任务(Task)。示例:使用Storm进行并行处理//定义Spout,作为数据源
publicclassMySpoutextendsBaseRichSpout{
privateSpoutOutputCollector_collector;
privateRandom_rand=newRandom();
publicvoidopen(Mapconf,TopologyContextcontext,SpoutOutputCollectorcollector){
this._collector=collector;
}
publicvoidnextTuple(){
Stringsentence="stormisadistributedreal-timecomputationsystem";
_collector.emit(newValues(sentence),_rand.nextInt(1000));
}
}
//定义Bolt,进行数据处理
publicclassMyBoltextendsBaseBasicBolt{
publicvoidexecute(BasicInputinput,BasicOutputCollectorcollector){
Stringsentence=input.get(0).toString();
String[]words=sentence.split("");
for(Stringword:words){
collector.emit(word);
}
}
}
//创建拓扑
TopologyBuilderbuilder=newTopologyBuilder();
builder.setSpout("spout",newMySpout(),5);//5个并行实例
builder.setBolt("bolt",newMyBolt(),8)//8个并行实例
.shuffleGrouping("spout");
//提交拓扑
Configconf=newConfig();
conf.setDebug(false);
StormSubmitter.submitTopology("my-topology",conf,builder.createTopology());在这个例子中,我们定义了一个Spout和一个Bolt。Spout生成数据,Bolt处理数据。通过设置Spout和Bolt的并行实例数,我们可以控制并行处理的粒度。4.2Storm的容错机制4.2.1容错机制的必要性在分布式系统中,容错是必不可少的。Storm通过多种机制确保即使在节点故障的情况下,也能保证数据的正确处理和系统的持续运行。4.2.2Storm的容错机制Storm的容错机制主要依赖于消息确认(MessageAcknowledgement)和故障恢复(FailureRecovery)。消息确认在Storm中,每个Spout发出的数据元组(Tuple)都可以被标记为需要确认。如果下游Bolt处理完元组,它会发送一个确认信号(Ack)回Spout。如果Spout在一定时间内没有收到确认,它会重新发出元组,确保数据被正确处理。故障恢复Storm能够检测到节点故障,并自动重新分配任务。当一个节点失败时,Storm会将该节点上的任务重新分配给集群中的其他节点,从而保证拓扑的持续运行。示例:使用消息确认publicclassMySpoutextendsBaseRichSpout{
privateSpoutOutputCollector_collector;
privateMap<String,Long>_emitted=newHashMap<>();
privateMap<String,Long>_acked=newHashMap<>();
privateMap<String,Long>_failed=newHashMap<>();
publicvoidopen(Mapconf,TopologyContextcontext,SpoutOutputCollectorcollector){
this._collector=collector;
}
publicvoidnextTuple(){
Stringsentence="stormisadistributedreal-timecomputationsystem";
_collector.emit(newValues(sentence),sentence);
}
publicvoidack(ObjectmsgId){
_acked.put((String)msgId,System.currentTimeMillis());
}
publicvoidfail(ObjectmsgId){
_failed.put((String)msgId,System.currentTimeMillis());
}
}在这个Spout示例中,我们使用emit方法发送元组,并传递一个msgId,这允许我们跟踪元组的状态。ack和fail方法用于处理确认和失败的元组。4.3Storm的性能调优4.3.1性能调优的关键点Storm的性能调优涉及多个方面,包括资源分配、并行度调整、网络优化以及数据序列化。4.3.2资源分配合理分配资源是提高Storm性能的关键。这包括CPU、内存和磁盘空间的分配。Storm允许在配置中指定这些资源的分配。4.3.3并行度调整并行度(Parallelism)的调整直接影响处理速度。增加并行度可以提高处理能力,但也会增加资源消耗。通过监控拓扑的性能,可以动态调整并行度。4.3.4网络优化Storm的性能也受到网络延迟的影响。优化网络配置,如使用更高效的网络协议,可以减少数据传输的延迟。4.3.5数据序列化选择合适的数据序列化库可以显著提高数据处理速度。Storm支持多种序列化库,如Kryo和Avro,它们在性能和数据兼容性之间提供了不同的权衡。示例:调整并行度//创建拓扑
TopologyBuilderbuilder=newTopologyBuilder();
builder.setSpout("spout",newMySpout(),10);//增加并行度
builder.setBolt("bolt",newMyBolt(),16)//增加并行度
.shuffleGrouping("spout");
//提交拓扑
Configconf=newConfig();
conf.setDebug(false);
conf.setNumWorkers(4);//设置工作进程数
StormSubmitter.submitTopology("my-topology",conf,builder.createTopology());在这个例子中,我们通过增加Spout和Bolt的并行度以及调整工作进程数(NumWorkers)来优化性能。通过深入理解Storm的并行处理机制、容错机制和性能调优策略,可以更有效地设计和运行实时流处理应用,确保数据的高效处理和系统的高可用性。5Storm应用案例分析5.1实时数据分析5.1.1原理Storm是一个开源的分布式实时计算系统,它能够处理大量流式数据,提供低延迟的实时分析能力。在实时数据分析场景中,Storm通过其独特的拓扑结构(Topology)和可靠的容错机制,确保数据的实时处理和分析。Storm的拓扑结构由多个Spout和Bolt组成,Spout负责接收数据流,而Bolt则负责数据的处理和分析。5.1.2内容示例:实时股票价格分析假设我们有一个实时的股票价格数据流,需要实时分析股票价格的波动情况。以下是一个使用Storm进行实时股票价格分析的示例。//Spout:从数据源接收股票价格数据
publicclassStockPriceSpoutextendsBaseRichSpout{
privatestaticfinallongserialVersionUID=1L;
privateSpoutOutputCollector_collector;
privateRandom_rand=newRandom();
@Override
publicvoidopen(Mapconf,TopologyContextcontext,SpoutOutputCollectorcollector){
_collector=collector;
}
@Override
publicvoidnextTuple(){
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
//生成模拟的股票价格数据
StringstockSymbol="AAPL";
doubleprice=_rand.nextDouble()*100+100;
_collector.emit(newValues(stockSymbol,price));
}
}
//Bolt:分析股票价格波动
publicclassStockPriceAnalyzerBoltextendsBaseBasicBolt{
privatestaticfinallongserialVersionUID=1L;
@Override
publicvoidexecute(Tupleinput,BasicOutputCollectorcollector){
StringstockSymbol=input.getStringByField("stockSymbol");
doubleprice=input.getDoubleByField("price");
//进行价格波动分析
System.out.println(stockSymbol+"的实时价格为:"+price);
//这里可以添加更复杂的分析逻辑,如计算价格变化率等
}
}在这个示例中,StockPriceSpout作为数据源,模拟生成股票价格数据。StockPriceAnalyzerBolt则负责接收这些数据,并进行实时分析,打印出股票的实时价格。在实际应用中,可以添加更多的分析逻辑,如计算价格变化率、预测价格走势等。5.2日志处理5.2.1原理Storm在日志处理中扮演着关键角色,能够实时地从各种数据源(如日志文件、网络流等)中读取日志数据,进行清洗、解析和分析,然后将结果发送到后端存储系统或实时监控系统中。5.2.2内容示例:实时日志分析假设我们需要实时分析来自多个服务器的日志数据,以下是一个使用Storm进行实时日志分析的示例。//Spout:从日志文件读取数据
publicclassLogFileSpoutextendsBaseRichSpout{
privatestaticfinallongserialVersionUID=1L;
privateSpoutOutputCollector_collector;
privateBufferedReader_reader;
@Override
publicvoidopen(Mapconf,TopologyContextcontext,SpoutOutputCollectorcollector){
_collector=collector;
try{
_reader=newBufferedReader(newFileReader("path/to/logfile"));
}catch(FileNotFoundExceptione){
e.printStackTrace();
}
}
@Override
publicvoidnextTuple(){
Stringline;
try{
line=_reader.readLine();
if(line!=null){
_collector.emit(newValues(line));
}
}catch(IOExceptione){
e.printStackTrace();
}
}
}
//Bolt:分析日志数据
publicclassLogAnalyzerBoltextendsBaseBasicBolt{
privatestaticfinallongserialVersionUID=1L;
@Override
publicvoidexecute(Tupleinput,BasicOutputCollectorcollector){
StringlogLine=input.getStringByField("logLine");
//进行日志分析
if(logLine.contains("ERROR")){
System.out.println("检测到错误日志:"+logLine);
//这里可以将错误日志发送到监控系统或存储到数据库中
}
}
}在这个示例中,LogFileSpout从日志文件中读取数据,并将其发送到Storm的拓扑中。LogAnalyzerBolt则负责接收这些日志数据,检查其中是否包含错误信息,并进行相应的处理。5.3社交网络分析5.3.1原理
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年雇佣合同:工作时间与休息安排
- 2024年金融科技支付系统搭建合同
- 2024年中国酱莴苣市场调查研究报告
- 2024年版汽车租赁合同标的及服务细节
- 2024年中国超级增白剂市场调查研究报告
- 二零二五年度保障性住房基本建设工程合同
- 2024年中国螺旋缎档毛巾市场调查研究报告
- 2024年跨境电子商务交易国际合作合同
- 2024年中国自动上料搅拌罐市场调查研究报告
- 2024年版权许可协议:影视作品海外发行
- 监事会年度工作计划
- 2024中国近海生态分区
- 山东省济南市2023-2024学年高一上学期1月期末考试化学试题(解析版)
- 企业节能奖惩管理制度(3篇)
- 统编版2024-2025学年三年级上册语文期末情景试卷 (无答案)
- 2024年时事政治试题【有答案】
- 造价咨询部组织架构及基本工作流程
- 2024年认证行业法律法规及认证基础知识
- MT 285-1992缝管锚杆
- GB 18613-2020 电动机能效限定值及能效等级
- 卡特彼勒生产体系手册(PDF62页)
评论
0/150
提交评论