Strom如何保证消息发送与接收

本文介绍了Apache Storm的基本架构,包括其核心组件nimus、supervisor和ui的作用,并深入探讨了topology、worker、executor和task之间的关系。此外,还详细解析了Storm内部消息发送与接收的机制,以及如何确保消息传递的可靠性。
摘要由CSDN通过智能技术生成

在谈Strom内部消息之前,先大致了解一下storm的结构。整体氛围3个组件,ui, supervisor, nimus.  nimus是主控制组件,用来分发代码,监控作业等等,supervisor是具体工作的节点,ui就是一个前端展示,提供了相应JOB信息。

以上组件属于物理上的,能够看得到,摸得到,逻辑概念又包含,topology spout, bolt , worker, executor, task. spout ,bolt不说了,一个获取消息再发消息,一个处理消息,再存入结果。

我们更加关注的是topology, worker, executor, task ,  topology表示整个拓扑,可以设置一些参数,比如max_pending, 主要的工作全部在worker, worker是一个具体的JVM进程,我们假设整个topology只有1个worker, 那么再分配executor, 它是在worker里分配的一个线程,用来处理TASK的。 默认一个exector对应一个task, 

conf.setNumWorkers(3); 设置worker数量

builder.setBolt("Handler2001Bolt", new HandlerBolt(fieldNameList), 3)  设置并发数量

setNumTasks(3) 设置TASK数量

关系清楚了吗? worker里分配executor,然后去执行TASK, 就是这么简单的关系。 如果你只有一个worker, 内存分配了1个G(配置:worker.childopts: "-Xmx1024m") ,

然后你有6个TASK,默认如果你不是设置exector,那么exector对应TASK也是6个,然后一个worker跑了6个exector去跑对应的TASK。

假设你的task和exector设置数量不同,很显然,storm会为你分配,假设我设置并发数量为3,但是task设置了6,那么1个exector就跑2个task.

在生产环境,到底1个worker跑几个executor ?  以及TASK又到底分几个合理呢?这个在storm性能方面做具体介绍。下面我们先说说storm内部的一些发送消息及接受消息的原理。

Storm从发送消息spout 到 接收消息bolt , 怎么样才认为消息已经发送成功了. Storm把spout, bolt 形成一个tree用来跟踪, spout发送消息后,会给每个message分配一个ID,这个ID是唯一的,用于跟踪消息,消息传送到bolt之后,然后处理,bolt通过ack,然后告诉spout,这条消息已经处理完成, spout然后把消息pop., 整个流程就结束了。

根据官网的介绍,storm获取一条消息是先open, 然后把消息置于pending状态,随后发送给bolt, 一旦spout收到bolt的ack,那么消息将会pop, 所谓pop就拿走,已经不需要了。

在这期间如果发生比如连接断开,或者出了网络问题等等,那么消息会从pending状态返回初始状态,等待再次送。


要保证上面的流程,有几个必要条件:

1. 必须手设置message id, 这个唯一ID是用来跟踪消息的

2. 必须设置TOPOLOGY_ACKERS大于0    ( Storm defaults TOPOLOGY_ACKERS to one task per worker.  默认是够了,如果你发现ack慢,可以考虑增加这个参数)

3. 必须anchored tuples


上面几个条件随便哪一个没有满足,那么storm就不会跟踪消息,也就是消息如果失败了,不会重发,这个是否和kafka的 at most  once类似? 如果你对消息的要求不高,这个性能肯定是最好的,不需要那么多处理环节。

另外要解释一下什么是anchored tuples, 这个大家也可以去官网看,大致意思就是bolt在emit消息的同时必须把上一个tuple放入emit中,看下面代码:

       public void execute(Tuple tuple) {
            String sentence = tuple.getString(0);
            for(String word: sentence.split(" ")) {
                _collector.emit(tuple, new Values(word));
            }
            _collector.ack(tuple);
        }

我们发送新的消息new values(word), 但是在emit还把原始的tuple也带上了,这个就是anchored tuple, 用于构建一个连接,来跟踪消息。

再来思考一下,如果我所有环节条件都满足,但是我就是不发ack给spout, 会怎么样? 最后的结果就是OOM, 因为所有的跟踪处理都会在内存里.

Storm有2种接口,basic和rich ,  richbolt表示我们所有的细节需要自己处理,比如分配message id , anchored tuples, 必须显示发送命令才可以。如果我们使用了basic接口,那么不需要去分配一个message id ,系统会自动帮我们分配。 

整个过程其实也不是很复杂,但是实际上还是有些疑问,这些官网上并没有介绍很清楚,多级bolt 怎么保证消息重新发送处理? A->B->C->D, 假如是这样一个tree, B已经处理完成,并发送了新的消息给C,然后B 发送ACK消息给A,但是C出错了,按照理论,C需要重新处理这个消息,但是这个消息是从A发送出来的,但是A已经收到了B的ack, 消息已经pop了, 这个时候A是在怎么处理的? 我看了官网,好像没做做具体介绍。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tom_fans

谢谢打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值