storm原理介绍

storm原理介绍

@(STORM)[storm, 大数据]

一、原理介绍

Why use Storm?

**Apache Storm is a free and open source distributed realtime computation system. Storm makes it easy to reliably process unbounded streams of data, doing for realtime processing what Hadoop did for batch processing. **Storm is simple, can be used with any programming language, and is a lot of fun to use!

Storm has many use cases: realtime analytics, online machine learning, continuous computation, distributed RPC, ETL, and more. Storm is fast: a benchmark clocked it at over a million tuples processed per second per node. It is scalable, fault-tolerant, guarantees your data will be processed, and is easy to set up and operate.

**Storm integrates with the queueing and database technologies you already use. **A Storm topology consumes streams of data and processes those streams in arbitrarily complex ways, repartitioning the streams between each stage of the computation however needed. Read more in the tutorial.

storm: 分布式实时计算系统。

1、适用场景

流数据处理:Storm可以用来处理源源不断流进来的消息,处理之后将结果写入到某个存储中去。
分布式rpc:由于storm的处理组件是分布式的,而且处理延迟极低,所以可以作为一个通用的分布式rpc框架来使用。当然,其实我们的搜索引擎本身也是一个分布式rpc系统。

2、集群相关概念

(1) Nimbus:负责资源分配和任务调度。
(2)Supervisor:负责接受nimbus分配的任务,启动和停止属于自己管理的worker进程。
(3)Worker:运行具体处理组件逻辑的进程。
(4)Task:worker中每一个spout/bolt的线程称为一个task. 在storm0.8之后,task不再与物理线程对应,同一个spout/bolt的task可能会共享一个物理线程,该线程称为executor。

3、拓扑相关概念

(1) Topology:storm中运行的一个实时应用程序,因为各个组件间的消息流动形成逻辑上的一个拓扑结构。
(2)Spout:在一个topology中产生源数据流的组件。通常情况下spout会从外部数据源中读取数据,然后转换为topology内部的源数据。Spout是一个主动的角色,其接口中有个nextTuple()函数,storm框架会不停地调用此函数,用户只要在其中生成源数据即可。
(3)Bolt:在一个topology中接受数据然后执行处理的组件。Bolt可以执行过滤、函数操作、合并、写数据库等任何操作。Bolt是一个被动的角色,其接口中有个execute(Tuple input)函数,在接受到消息后会调用此函数,用户可以在其中执行自己想要的操作。
(4)Tuple:一次消息传递的基本单元。本来应该是一个key-value的map,但是由于各个组件间传递的tuple的字段名称已经事先定义好,所以tuple中只要按序填入各个value就行了,所以就是一个value list.
(5)Stream:源源不断传递的tuple就组成了stream。

二、配置

完整的默认配置文件见下面defaluts.yaml,若需要修改,则在storm.yaml中修改。重要参数如下:
1、storm.zookeeper.servers:指定使用哪个zookeeper集群

storm.zookeeper.servers:
     - "gdc-nn01-test"
     - "gdc-dn01-test"
     - "gdc-dn02-test”

2、nimbus.host:指定nimbus是哪台机器

nimbus.host: "gdc-nn01-test”

3、指定supervisor在哪个端口上运行worker,每个端口可运行一个worker,因此有多少个配置端口,则每个supervisor有多少个slot(即可运行多少个worker)

supervisor.slots.ports:
     - 6700
    - 6701
    - 6702
    - 6703
    storm.local.dir: "/home/hadoop/storm/data"

4、jvm设置

nimbus.childopts:"-4096m”
supervisor.childopts:"-Xmx4096m"
nimubs.childopts:"-Xmx3072m”

除此外,还有ui.childopts,logviewer.childopts

附完整配置文件:defaults.yaml

########### These all have default values as shown
########### Additional configuration goes into storm.yaml
java.library.path: "/usr/local/lib:/opt/local/lib:/usr/lib"

### storm.* configs are general configurations
# the local dir is where jars are kept
storm.local.dir: "storm-local"
storm.zookeeper.servers:
    - "localhost"
storm.zookeeper.port: 2181
storm.zookeeper.root: "/storm"
storm.zookeeper.session.timeout: 20000
storm.zookeeper.connection.timeout: 15000
storm.zookeeper.retry.times: 5
storm.zookeeper.retry.interval: 1000
storm.zookeeper.retry.intervalceiling.millis: 30000
storm.cluster.mode: "distributed" # can be distributed or local
storm.local.mode.zmq: false
storm.thrift.transport: "backtype.storm.security.auth.SimpleTransportPlugin"
storm.messaging.transport: "backtype.storm.messaging.netty.Context"
storm.meta.serialization.delegate: "backtype.storm.serialization.DefaultSerializationDelegate"

### nimbus.* configs are for the master
nimbus.host: "localhost"
nimbus.thrift.port: 6627
nimbus.thrift.max_buffer_size: 1048576
nimbus.childopts: "-Xmx1024m"
nimbus.task.timeout.secs: 30
nimbus.supervisor.timeout.secs: 60
nimbus.monitor.freq.secs: 10
nimbus.cleanup.inbox.freq.secs: 600
nimbus.inbox.jar.expiration.secs: 3600
nimbus.task.launch.secs: 120
nimbus.reassign: true
nimbus.file.copy.expiration.secs: 600
nimbus.topology.validator: "backtype.storm.nimbus.DefaultTopologyValidator"

### ui.* configs are for the master
ui.port: 8080
ui.childopts: "-Xmx768m"
logviewer.port: 8000
logviewer.childopts: "-Xmx128m"
logviewer.appender.name: "A1"

drpc.port: 3772
drpc.worker.threads: 64
drpc.queue.size: 128
drpc.invocations.port: 3773
drpc.request.timeout.secs: 600
drpc.childopts: "-Xmx768m"
transactional.zookeeper.root: "/transactional"
transactional.zookeeper.servers: null
transactional.zookeeper.port: null

### supervisor.* configs are for node supervisors
# Define the amount of workers that can be run on this machine. Each worker is assigned a port to use for communication
supervisor.slots.ports:
    - 6700
    - 6701
    - 6702
    - 6703
supervisor.childopts: "-Xmx256m"
#how long supervisor will wait to ensure that a worker process is started
supervisor.worker.start.timeout.secs: 120
#how long between heartbeats until supervisor considers that worker dead and tries to restart it
supervisor.worker.timeout.secs: 30
#how frequently the supervisor checks on the status of the processes it's monitoring and restarts if necessary
supervisor.monitor.frequency.secs: 3
#how frequently the supervisor heartbeats to the cluster state (for nimbus)
supervisor.heartbeat.frequency.secs: 5
supervisor.enable: true
### worker.* configs are for task workers
worker.childopts: "-Xmx768m"
worker.heartbeat.frequency.secs: 1

# control how many worker receiver threads we need per worker
topology.worker.receiver.thread.count: 1
task.heartbeat.frequency.secs: 3
task.refresh.poll.secs: 10
zmq.threads: 1
zmq.linger.millis: 5000
zmq.hwm: 0
storm.messaging.netty.server_worker_threads: 1
storm.messaging.netty.client_worker_threads: 1
storm.messaging.netty.buffer_size: 5242880 #5MB buffer
# Since nimbus.task.launch.secs and supervisor.worker.start.timeout.secs are 120, other workers should also wait at least that long before giving up on connecting to the other worker. The reconnection period need also be bigger than storm.zookeeper.session.timeout(default is 20s), so that we can abort the reconnection when the target worker is dead.
storm.messaging.netty.max_retries: 30
storm.messaging.netty.max_wait_ms: 1000
storm.messaging.netty.min_wait_ms: 100

# If the Netty messaging layer is busy(netty internal buffer not writable), the Netty client will try to batch message as more as possible up to the size of storm.messaging.netty.transfer.batch.size bytes, otherwise it will try to flush message as soon as possible to reduce latency.
storm.messaging.netty.transfer.batch.size: 262144

# We check with this interval that whether the Netty channel is writable and try to write pending messages if it is.
storm.messaging.netty.flush.check.interval.ms: 10
### topology.* configs are for specific executing storms
topology.enable.message.timeouts: true
topology.debug: false
topology.workers: 1
topology.acker.executors: null
topology.tasks: null
# maximum amount of time a message has to complete before it's considered failed
topology.message.timeout.secs: 30
topology.multilang.serializer: "backtype.storm.multilang.JsonSerializer"
topology.skip.missing.kryo.registrations: false
topology.max.task.parallelism: null
topology.max.spout.pending: null
topology.state.synchronization.timeout.secs: 60
topology.stats.sample.rate: 0.05
topology.builtin.metrics.bucket.size.secs: 60
topology.fall.back.on.java.serialization: true
topology.worker.childopts: null
topology.executor.receive.buffer.size: 1024 #batched
topology.executor.send.buffer.size: 1024 #individual messages
topology.receiver.buffer.size: 8 # setting it too high causes a lot of problems (heartbeat thread gets starved, throughput plummets)
topology.transfer.buffer.size: 1024 # batched
topology.tick.tuple.freq.secs: null
topology.worker.shared.thread.pool.size: 4
topology.disruptor.wait.strategy: "com.lmax.disruptor.BlockingWaitStrategy"
topology.spout.wait.strategy: "backtype.storm.spout.SleepSpoutWaitStrategy"
topology.sleep.spout.wait.strategy.time.ms: 1
topology.error.throttle.interval.secs: 10
topology.max.error.report.per.interval: 5
topology.kryo.factory: "backtype.storm.serialization.DefaultKryoFactory"
topology.tuple.serializer: "backtype.storm.serialization.types.ListDelegateSerializer"
topology.trident.batch.emit.interval.millis: 500
topology.classpath: null
topology.environment: null
dev.zookeeper.path: "/tmp/dev-storm-zookeeper"</span>

三、并行度

(一)storm拓扑的并行度可以从以下4个维度进行设置:

1、node(服务器):指一个storm集群中的supervisor服务器数量。
2、worker(jvm进程):指整个拓扑中worker进程的总数量,这些数量会随机的平均分配到各个node。
3、executor(线程):指某个spout或者bolt的总线程数量,这些线程会被随机平均的分配到各个worker。
4、task(spout/bolt实例):task是spout和bolt的实例,它们的nextTuple()和execute()方法会被executors线程调用。除非明确指定,storm会给每个executor分配一个task。如果设置了多个task,即一个线程持有了多个spout/bolt实例.
注意:以上设置的都是总数量,这些数量会被平均分配到各自的宿主上,而不是设置每个宿主进行多少个进程/线程。详见下面的例子。
关于executor/task的进一步说明:
The number of tasks is the number of spout objects that get created, that each have their own distinct sets of tuples that are emitted, need to be acked, etc. The number of executors is the number of OS threads (potentially across more than 1 machine) that get created to service these spout objects. Usually there is 1 executor for each task, but you may want to create more tasks than executors if you think you will want to rebalance in the future.

(二)并行度的设置方法

1、node:买机器吧,然后加入集群中……
2、worker:Config#setNumWorkers() 或者配置项 TOPOLOGY_WORKERS
3、executor:Topology.setSpout()/.setBolt()的最后一个参数
4、task:ComponentConfigurationDeclarer#setNumWorker()

(三)示例

// 创建topology  
TopologyBuilder builder = new TopologyBuilder();  
builder.setSpout("kafka-reader", new KafkaSpout(spoutConf), 5);//设置executor数量为5  
builder.setBolt("filter-bolt", new FilterBolt(), 3).shuffleGrouping(  
        "kafka-reader");//设置executor数量为3  
builder.setBolt("log-splitter", new LogSplitterBolt(), 3)  
        .shuffleGrouping("filter-bolt");//设置executor数量为5  
builder.setBolt("hdfs-bolt", hdfsBolt, 2).shuffleGrouping(  
        "log-splitter");//设置executor数量为2  

// 启动topology  
Config conf = new Config();  
conf.put(Config.NIMBUS_HOST, nimbusHost);  
conf.setNumWorkers(3);      //设置worker数量  
StormSubmitter.submitTopologyWithProgressBar(topologyName, conf,  
        builder.createTopology());  

1、通过config.setNumWorkers(3)将worker进程数量设置为3,假设集群中有3个node,则每个node会运行一个worker。
2、executor的数量分别为:
spout:5
filter-bolt:3
log-splitter:3
hdfs-bolt:2
总共为13个executor,这13个executor会被随机分配到各个worker中去。
注:这段代码是从kafka中读取消息源的,而这个topic在kafka中的分区数量设置为5,因此这里spout的线程ovtn为5.
3、这个示例都没有单独设置task的数量,即使用每个executor一个task的默认配置。若需要设置,可以:

    builder.setBolt("log-splitter", new LogSplitterBolt(), 3)
            .shuffleGrouping("filter-bolt").setNumTasks(5);

来进行设置,这5个task会被分配到3个executor中。

(四)并行度的动态调整
对storm拓扑的并行度进行调整有2种方法:
1、kill topo—>修改代码—>编译—>提交拓扑
2、动态调整
第1种方法太不方便了,有时候topo不能说kill就kill,另外,如果加几台机器,难道要把所有topo kill掉还要修改代码?
因此storm提供了动态调整的方法,动态调整有2种方法:
1、ui方式:进入某个topo的页面,点击rebalance即可,此时可以看到topo的状态是rebalancing。但此方法只是把进程、线程在各个机器上重新分配,即适用于增加机器,或者减少机器的情形,不能调整worker数量、executor数量等
2、cli方式:storm rebalance
举个例子

storm rebalance toponame -n 7 -e filter-bolt=6 -e hdfs-bolt=8

将topo的worker数量设置为7,并将filter-bolt与hdfs-bolt的executor数量分别设置为6、8.
此时,查看topo的状态是rebalancing,调整完成后,可以看到3台机器中的worker数量分别为3、2、2

四、分组

Storm通过分组来指定数据的流向,主要指定了每个bolt消费哪个流,以及如何消费。
storm内置了7个分组方式,并提供了CustomStreamGrouping来创建自定义的分组方式。
1、随机分组 shuffleGrouping
这种方式会随机分发tuple给bolt的各个task,每个task接到到相同数量的tuple。

2、字段分组 fieldGrouping
按照指定字段进行分组,该字段具有相同组的会被发送到同一个task,具体不同值的可能会被发送到不同的task。

3、全复制分组 allGrouping(或者叫广播分组)
每一个tuple都会发送给所有的task,必须小心使用。

4、全局分组 globlaGrouping
将所有tuple均发送到唯一的task,会选取task ID最小的task。这种分组下,设置task的并行度是没有意义的。另外,这种方式很有可能引起瓶颈。

5、不分组 noneGrouping
留作以后使用,目前也随机分组相同。

6、指向型分组 directGrouping(或者叫直接分组)
数据源会调用emitDirect()方法来判断一个tuple应该由哪个storm组件来接收,只能在声明了是指向型的数据流上使用。

7、本地或随机分组 localOrShuffleGrouping
如果接收bolt在同一个进程中存在一个或者多个task,tuple会优先发送给这个task。否则和随机分组一样。相对于随机分组,此方式可以减少网络传输,从而提高性能。

五、可靠性

可靠性:spout发送的消息会被拓扑树上的所有节点ack,否则会一直重发。
导致重发的原因有2个:
(1)fail()被调用
(2)超时无响应。
完整的可靠性示例请参考storm blueprint的chapter1 v4代码,或者P22,或者参考从零开始学storm P102页的例子。
关键步骤如下:

(一)spout

1、创建一个map,用于记录已经发送的tuple的id与内容,此为待确认的tuple列表。

private ConcurrentHashMap<UUID,Values> pending;

2、发送tuple时,加上一个参数用于指明该tuple的id。同时,将此tuple加入map中,等待确认。

UUID msgId = UUID.randomUUID();
this.pending.put(msgId,values);
this.collector.emit(values,msgId);

3、定义ack方法与fail方法。
ack方法将tuple从map中取出

this.pending.remove(msgId);

fail方法将tuple重新发送

this.collector.emit(this.pending.get(msgId),msgId);

对于没回复的tuple,会定时重新发送。

(二)bolt

处理该tuple的每个bolt均需要增加以下内容:
1、emit时,增加一个参数anchor,指定响应的tuple

collector.emit(tuple,new Values(word));

2、确认接收到的tuple已经处理

this.collector.ack(tuple);
### 回答1: Storm32BGC是一种用于相机云台的稳定器控制板。它的原理图是用于显示硬件电路和部件连接的图纸。原理图显示了Storm32BGC内部的电路板设计和各个元件之间的连接方式。它是电子工程师在设计和制造Storm32BGC时所使用的参考图纸。 原理图通常包括电源部分、控制电路部分和传感器部分。电源部分显示如何提供所需的电源电压和电流给整个系统。控制电路部分描述了如何实现稳定器控制功能,包括控制电机的速度和位置。传感器部分显示了如何使用各种传感器来检测相机云台的倾斜角度和角速度。 在原理图中,不同的电路和元件使用符号和线路来表示。符号表示电子元件,如电位器、电容器、电感器等。线路则表示不同元件之间的连接方式,例如电源线、信号线和地线。 通过查看Storm32BGC的原理图,电子工程师可以了解到如何将电路板组装起来,并将不同的元件正确连接在一起。在需要维修或修改Storm32BGC时,原理图也提供了重要的参考资料。 总之,Storm32BGC的原理图是一份重要的参考图纸,用于展示它内部电路的设计和元件的连接方式,对于电子工程师来说具有重要意义。 ### 回答2: storm32bgc是一种用于摄像机云台稳定器的开源硬件和软件平台。它主要用于保持相机稳定并减少震动,以便在运动中拍摄平滑的视频。 Storm32bgc的原理图是指设计师绘制的电路图,显示了该设备的电子元件之间的连接和电路连接方式。这个原理图是为了帮助工程师和技术人员理解storm32bgc的内部结构和工作原理,以便进行相关操作和维护工作。 在原理图中,可以看到各种电子元件的连接方式,比如电路板上的电阻、电容、电感、晶体管等等。通过电阻、电容等元器件的串联、并联或者并串联等方式,形成各种电路结构,实现storm32bgc的各项功能。 此外,原理图还显示了各个元件之间的连接线路,以及与其他外界设备的连接方式。例如,摄像机、电池、控制器之间的连接线路。这些线路连接的正确性和稳定性,对于确保storm32bgc的正常工作至关重要。 总之,通过阅读storm32bgc的原理图,技术人员可以更好地理解设备的内部结构和工作原理,进而进行相应的操作和维护工作。这对于确保摄像机云台稳定器的良好性能和长期使用具有重要作用。 ### 回答3: Storm32bgc是一种用于稳定云台控制的开源硬件。它通过使用传感器和电机来实现云台的稳定,并允许用户对其进行控制和配置。在Storm32bgc的原理图中,主要包含以下几个关键部分: 1. MPU6050加速度计和陀螺仪模块:这个模块用于检测云台的倾角和角速度。通过检测这些数据,系统可以进行实时校准和调整以保持云台的稳定性。 2. MOSFET驱动器:这个模块用于控制云台的电机。通过根据用户输入的指令来改变电机的转速和方向,从而实现云台的平稳移动。 3. 固态电容:这个组件用于消除电机产生的噪声和干扰,从而提高信号的质量。 4. 控制接口:原理图中还包含各种连接接口,例如UART,I2C和PWM接口,用于连接其他设备,例如遥控器或计算机,以实现云台的远程控制和配置。 总的来说,Storm32bgc的原理图包含了控制云台稳定的关键部件和连接接口。通过在这些模块之间传递信号和数据,系统能够实时监测云台的状态并进行相应的调整,从而实现云台的稳定控制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值