Storm并行度

storm程序的并行度
 并行度说白了就是同时运行当前topology的子topology的个数----->进程级别来说
 从线程级别来说并行度就是一个work进程中有几个executor来运行---->线程级别
 task任务一个executor线程中有几个task实例---->task级别
worker进程
 每一台supervisor上面运行子topology的进程就是worker,默认一台supervisor可以运行4个worker进程,
 在storm.yaml中的supervisor.slots.ports进行配置(一个端口指定一个worker-->slot)
 同时一个worker进程运行一个topology任务的子topology(因为是分布式的程序,我们可以设置,当前topology被分配到多个worker里面去运行)
executor线程
 每一个worker进程中有一个或者多个executor线程来组成,这些线程就用来运行我们topology任务,默认情况先也是一对一的。
task任务
 task就是用来执行具体代码的一个单元,也可以理解为spout和bolt的实例(就像mr中一个maptask和reducetask),一般情况下,
 executor线程threadNums<=taskNums
 默认情况下,一个supervisor节点最多可以启动4个worker进程,每一个topology默认占用一个worker进程,
每个spout或者bolt会占用1个executor,每个executor启动1个task。

并行度测试
 Worker(slot)
  默认一个从节点上面可以启动4个worker进程,参数是supervisor.slots.ports。在storm配置文件中已经配置过了,默认是在strom-core.jar包中的defaults.yaml中配置的有。
  默认一个topology只使用一个worker进程,可以通过代码来设置使用多个worker进程。
  通过config.setNumWorkers(workers)设置
  通过conf.setNumAckers(0);可以取消acker任务(点击topology页面最下面的show system stats,可以显示系统级别的bolt,可以验证acker线程的存在)
  最好一台机器上的一个topology只使用一个worker,主要原因是减少了worker之间的数据传输
  如果worker使用完的话再提交topology就不会执行,会处于等待状态
  注意:worker之间通信是通过Netty?进行通信的
 Executor
  默认情况下一个executor运行一个task,可以通过在代码中设置
  builder.setSpout(id, spout, parallelism_hint);
  builder.setBolt(id, bolt, parallelism_hint);
 Task
  通过boltDeclarer.setNumTasks(num);来设置实例的个数
  executor的数量会小于等于task的数量(为了rebalance)
 设置workerNums
  Config config = new Config();
  config.setNumWorkers(2);
  在原先代码的基础之上,将topology的worker个数由1提升到2,原先一个worker进程中有3个executor线程,这三个executor线程分别是:
  spout线程,bolt线程,以及系统线程__acker,那么案例说,worker进程变成2之后,executor线程个数应该也是原来2倍?
  是因为咱们当前应用程序比较小,任务只分配到了一个worker中,所以我们看到还是有2个executor来运行spout和bolt,另外两个executor
  就是运行我们的形同线程__acker(默认每一个worker进程,持有一个__acker executor线程),所以最终结果看到了
  有2个worker、4个executor、4个task
 设置ackerNums
  acker,是用来监控storm topology中数据是否被完全消费,也就是类似于db中的事务,默认如果我们没有进行配置topology.acker.executors
  的话,则一个worker进程对应一个acker executor,如果这个参数设置为0的话,则storm topology不会保证数据能被完全消费掉,
  这样的话就大大降低了storm集群的数据的可靠性。
  
  在上述基础上:
  设置的话,通过config.setNumAckers(0);
  ---->2个worker,2个executor、2个task
 设置executor
  设置线程个数就需要在
  topologyBuilder.setSpout(spoutID, new SumNumSpout(), 2);
  topologyBuilder.setBolt(boltID, new SumNumBolt(), 2)
  中的第三个参数,设置当前spout和bolt分别有几个executor来进行运行,
  去掉上述worker和acker的设置的话,则有1个worker、5个executor(1个acker+2个spout+2个bolt)、5个task(一个executor对应一个task)
 设置task
  设置task的个数,实际就是设置参数:topology.tasks的个数
  定义了一个executor中有几个spout和blot的实例个数。一个executor线程中可以运行0个或者多个同名的spout或者blot的实例,
  注意:task的个数一旦topology被部署之后就不能再进行改变了,只能改变executor线程的个数(动态调整并行度)
  topologyBuilder.setSpout(spoutID, new SumNumSpout()).setNumTask(2);--->设置一个executor中可以有两个spout的task实例
  topologyBuilder.setBolt(boltID, new SumNumBolt()).shuffleGrouping(spoutID).setNumTasks(2);-->设置一个executor中可以有两个blot的task实例
 问,一下代码会有几个worker进程,几个executor线程,几个task线程?
 
  topologyBuilder.setSpout(spoutID, new SumNumSpout());
  topologyBuilder.setBolt(boltID, new SumNumBolt(), 2).shuffleGrouping(spoutID).setNumTasks(2);
        StormTopology stormTopology = topologyBuilder.createTopology();

        String topologyName = RemoteParallismSumTopology.class.getSimpleName();
        Config config = new Config();
        config.setNumWorkers(2);
        config.setNumAckers(0);//设置系统executor个数
  
  2 worker进程
  3 executor线程
  3 task任务
  说明,案例说应该有5个task任务,因为当前程序,虽然设置了两个worker进程,但是任务只被分配到了一个worker进程中去运行,
  所以另外一个executor进程中什么都没有运行。

动态调整并行度----弹性计算
 通过UI调整
   不推荐使用
 通过代码调整
    topologyBuilder.setBolt("green-bolt", new GreenBolt(),2)
 .setNumTasks(4).shuffleGrouping("blue-spout);
 通过shell调整
   # 10秒之后开始调整
   # Reconfigure the topology "mytopology" to use 5 worker processes,
   # the spout "blue-spout" to use 3 executors and
   # the bolt "yellow-bolt" to use 10 executors.
   storm rebalance topologyName -w 10 -n 5 -e spout_id=3 -e id_bolt=10
 注意:acker数目运行时是不会变化的,所以多指定几个worker进程,acker线程数也不会增加。
   -w:表示超时时间,rebalance首先会在一个超时时间内注销掉拓扑,然后在整个集群中重新分配 worker。
 问题:-e spout_id=3 -e id_bolt=10 有时不会增加并发度
 原因:You can only increase the parallelism (number of executors) to the number of tasks. So if your component is having for example (number of executors: 50, number of tasks: 50) then you can not increase the parallelism, however you can decrease it.
    就是说spout和bolt的并行数,最多可以调整到它的taskNum,默认情况下,taskNum是和你设置的paralismNum相同的。#threads<=#tasks
======================================================================================================
流分组
 数据是如何从spout到bolt中的呢,如果bolt是多个情况呢?
 这就是我们所说的流分组,也就是在Spout与Bolt、Bolt与Bolt之间传递Tuple的方式,我们称之为流分组storm grouping。
stream grouping分类
 Shuffle Grouping:
  随机分组,随机派发stream里面的tuple, 保证每个excutor中的每个任务[bolt]接收到的tuple数目相同.(它能实现较好的负载均衡)
  具体设置,见代码ShuffleGroupingSumTopology
 Fields Grouping:
  按字段分组,比如按userid来分组,具有同样userid的tuple会被分到同一bolt任务, 而不同的userid则会被分配到不同的任务
  具体设置,见代码FieldsGroupingSumTopology,需要在fieldsGrouping第二个参数设置分组字段
 All Grouping:
  广播发送,对于每一个tuple,Bolts中的所有bolt任务都会收到.
  具体设置,见代码AllGroupingSumTopology,这种方式会使得所有的bolt都处理相同数据,未免有点浪费资源,不建议大家使用。
 Global Grouping:
  全局分组,这个tuple被分配到storm中的一个bolt的其中一个task.再具体一点就是分配给id值最低的那个task.
  见代码GlobalGroupingSumTopology
 Non Grouping:
  随机分派,意思是说stream不关心到底谁会收到它的tuple.目前他和Shuffle grouping是一样的效果,
  减NoGroupingSumTopology
 Direct Grouping:
  直接分组,这是一种比较特别的分组方法,用这种分组意味着消息的发送者具体由消息接收者的哪个task处理这个消息.只有被声明为Direct Stream的消息流可以声明这种分组方法.而且这种消息tuple必须使用emitDirect方法来发射.消息处理者可以通过TopologyContext来或者处理它的消息的taskid (OutputCollector.emit方法也会返回taskid)
 localOrShuffleGrouping
 CustomStreamGrouping
======================================================================================================
worker进程死掉
    worker进程挂掉,storm集群会在重新启动一个worker进程。
supervisor进程死掉
   supervisor进程挂掉,不会影响之前已经提交的topology,只是后期不能向这个节点分配任务,因为这个节点已经不是集群的一员了。
nimbus进程死掉(存在HA的问题)快速失败
   nimbus进程挂掉,也不会影响之前已经提交的topology,只是后期不能向集群再提交新的topology了。1.0以下的版本存在HA的问题,1.0之后已经修复了这个问题,可以有多个备选nimbus。
节点宕机
 ack/fail消息确认机制(确保一个tuple被完全处理)
 在spout中发射tuple的时候需要同时发送messageid,这样才相当于开启了消息确认机制
 如果你的topology里面的tuple比较多的话, 那么把acker的数量设置多一点,效率会高一点。
 通过config.setNumAckers(num)来设置一个topology里面的acker的数量,默认值是1。
 注意: acker用了特殊的算法,使得对于追踪每个spout tuple的状态所需要的内存量是恒定的(20 bytes)
 注意:如果一个tuple在指定的timeout(Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS默认值为30秒)时间内没有被成功处理,那么这个tuple会被认为处理失败了。
完全处理tuple
    在storm里面一个tuple被完全处理的意思是: 这个tuple以及由这个tuple所衍生的所有的tuple都被成功处理。
 代码见LocalAckerSumTopology
======================================================================================================
Storm定时器 
 一般的业务数据存储,最终还是要落地,存储到RDBMS,但是RDBMS无法达到高访问量,能力达不到实时处理,或者说处理能力是有限的,会造成连接中断等问题,为了数据落地,我们可以采取迂回方式,可以采用比如说先缓存到高速内存数据库(如redis),然后再将内存数据库中的数据定时同步到rdbms中,而且可以定期定时来做。
 可以每隔指定的时间将数据整合一次存入数据库。
 或者每隔指定的时间执行一些
 1:在main中设置
    conf.put(Config.TOPOLOGY_TICK_TUPLE_FREQ_SECS, 10);
   // 设置多久发送一个系统的tuple定时发射数据
   但是我们一般都会对特定的bolt设置定时任务,而没有必要对全局每一个bolt都发送系统的tuple,这样非常的耗费资源,所以就有了局部定时任务,也是我们常用的。 2:在bolt中使用下面代码判断是否是触发用的bolt
 tuple.getSourceComponent().equals(Constants.SYSTEM_COMPONENT_ID)
 如果为true,则执行定时任务需要执行的代码,最后return,如果为false,则执行正常的tuple处理的业务逻辑
 具体案例见代码com.uplooking.bigdata.storm.test.TimerSchedulerSumTopology
======================================================================================================
StormUI参数的介绍
 deactive:
  未激活(暂停)
 emitted:
  emitted tuple数
 transferred:
  transferred tuple数
  emitted的区别:如果一个task,emitted一个tuple到2个task中,则 transferred tuple数是emitted tuple数的两倍
 complete latency:
  spout emitting 一个tuple到spout ack这个tuple的平均时间(可以认为是tuple以及该tuple树的整个处理时间)
 process latency:
  bolt收到一个tuple到bolt ack这个tuple的平均时间,如果没有启动acker机制,那么值为0
 execute latency:
  bolt处理一个tuple的平均时间,不包含acker操作,单位是毫秒(也就是bolt 执行 execute 方法的平均时间)
 capacity:
  这个值越接近1,说明bolt或者spout基本一直在调用execute方法,说明并行度不够,需要扩展这个组件的executor数量。
  总结:execute latency和proces latnecy是处理消息的时效性,而capacity则表示处理能力是否已经饱和,从这3个参数可以知道topology的瓶颈所在。


   
  
  
  
  
  
  
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值