从事实时计算多年,熟悉jstorm/spark/flink/kafka/rocketMq, 热衷于开源,希望在这里和前辈们一起学习与分享,得到长足的进步!邮箱:hustfxj@gmail.com 我的githup地址是:https://github.com/hustfxj。欢迎和大家一起交流探讨问题。
分类: 大数据
2017-05-27 19:38:28
Jstorm是开源的分布式实时计算系统,相比于storm的优势在于稳定性、容错性和性能等。JStorm通过减少对zookeeper的访问量、增加反序列化线程、优化ACK、增加监控内容及JAVA本身优势等各个方面优化了Storm的性能和稳定性。总之,JStorm比Storm更强大、更稳定、性能更好。这里我们主要介绍jstorm的调度原理及实现,现在的jstorm相较于storm的任务调度更加合理,更加适合大集群,支持用户定制任务调度及动态扩容等高级任务调度功能。在了解调度之前,我们简单介绍下其架构和拓扑模型。如图所示表示的jstorm的系统结构。
整个jstorm系统共存三类不同的进程,分别是nimbus,supervisor和worker。Nimbus主要负责topology提交、向zk写入元信息及任务调度;supervisor根据nimbus任务调度结果启动/停止工作进程worker;worker是jstorm任务执行者,里面的task对应拓扑模型的一个component。下图表示一个拓扑。Spout是jstorm的消息源,用于生成消息,bilt是消息的处理单元,acker是用于保证消息不丢失的component。下图存在的component有1个spout、2个bolt-A、2个bolt-B和1个acker,这些component组成了一个拓扑,消息经过拓扑树传递处理,可以得到用户想用个的结果。
结合拓扑模型以及jstorm系统结构,jstorm任务调度就是在集群中利用合适的资源,在supervisor机子上创建合理数量的worker,并将拓扑的component合理分配到各个worker上去的过程。Jstorm任务调度有以下几种特点:
拓扑一般以参数文件的形成提交,参数文件可以设置worker数量、component并发度和worker的内存和cpu等,如下所示。在nimbus去调度任务之前,需要确定将要分配的worker数量。
Nimbus会根据每台机子的可利用cpu和内存信息,和用户设置的参数worker.memory.size、supervisor.slots.port.cpu.weight。根据getSupervisorPortList计算出每个supervisor的可利用端口数量,以及整个集群的可利用端口数量。所以最后实际的需要调度的worker数量时取集群可利用端口数量、topology.workers和拓扑的并发度总数这三者中最小值。根据每个supervisor机子可利用端口数量,来确定每个supervisor将要启用的worker数量,尽量保证supervisor上启用的worker数量平均。如图所示,黑色代表supervisor机子上已经存在的worker,在这集群上提交拓扑,需要再分配5个worker。则分配算法为红色表示,supervisor-1先分配worker-1,worker分配到supervisor次序如标号所示。
确定了各个supervisor机子上要启动的worker数量后,再确定每一个worker将要分配的task。分配task到特定的worker的原则有:
task选择合适的worker,先按照规则i筛选,如果满足规则i的worker数量不止唯一;再根据规则ii筛选,结果仍然不唯一;再按照规则iii筛选。里我们以topology_nums=1, topology_level=1, workers=24, spout.parallel=10, bolt_0.parallel=18, acker.executors=12,集群数量为6台测试为例。
①以worker为维度,尽量将worker平均分配到各个supervisor上;
②保证同类型task尽量均分到不同worker和supervisor的基础上,其次保证每一个worker和supervisor的task数量均衡,最后保证直接相关的task放到一个进程上去;
Worker被一一分配到supervisor上
Task按规定分配到work上去(共有24端口,先分配12个acker保证能够放到不同的进程且每个supervisor有2个acker;再分配18个bolt-task,其中6个task会与acker在一个进程;最后分配10个spout-task分配,应该和bolt-task在一起)
Jstorm实现了用户自定义调度功能,提供给用户的接口是ConfigExtension.setUserDefineAssignment,用户只要自定义List
文件
Nimbus在任务调度时,其实会把自定义调度优先级设定为最高。