jstorm源码解析之bolt异常处理方法
作者:jingxian 发布时间:2022-08-05 23:12:08
问题
用过storm或者jstorm的都知道,如果在bolt代码中发生了没被catch住的异常,所在worker进程会退出。本文就从源码角度分析一下具体设计,其实并不是“有异常然后进程崩了”这么简单。
实质
我们先看BasicBoltExecutor的源码:
public void execute(Tuple input) {
_collector.setContext(input);
try {
_bolt.execute(input, _collector);
_collector.getOutputter().ack(input);
} catch (FailedException e) {
if (e instanceof ReportedFailedException) {
_collector.reportError(e);
}
_collector.getOutputter().fail(input);
}
}
_bolt.execute(input, _collector) 就是执行我们自己编写的bolt里的excute方法。可以看到,在这里,只会catch storm自己定义的FailedException,并且发送fail消息,标记tuple处理失败, 其余异常则会被放过。
再外层是BoltExecutors的processTupleEvent方法:
try {
if (!isSystemBolt && tuple.getSourceStreamId().equals(Common.TOPOLOGY_MASTER_CONTROL_STREAM_ID)) {
backpressureTrigger.handle(tuple);
} else {
bolt.execute(tuple);
}
} catch (Throwable e) {
error = e;
LOG.error("bolt execute error ", e);
report_error.report(e);
}
在这里,所有异常都会被catch住,但是只会进行report_error,并不会发fail消息,相关tuple只能等超时才能被标记为失败。
再来看report_error.report(e) 的具体实现,通过看构造函数,可以看到report_error是一个TaskReportErrorAndDie类,
@Override
public void report(Throwable error) {
this.reporterror.report(error);
this.haltfn.run();
}
在这里,reporterror是一个AsyncLoopDefaultKill类
@Override
public void run() {
JStormUtils.halt_process(1, "Async loop died!");
}
这里就是整个过程的最终步骤了, JStormUtils.halt_process()方法会打印一条"Async loop died!"的日志后将worker进程杀死。
思考
通过代码可以出来,对于jstorm,“异常后worker退出”是一个故意设计出的特性,并非程序不健壮。猜测这一块的设计理念就是对于已知异常,开发人员自己捕获并重新抛出FailedException,使相应消息失败;未知异常则强制使进程直接失败退出,避免过度的catch导致问题被掩盖。
不过虽然话是这么说,对这个设计还是持保留意见,毕竟storm和普通的java程序不一样,storm的worker进程在退出后是会自动被重启的,所以这种异常处理方式并不能起到failfast的效果。
相反,worker的持续重启,还会带来一些其他问题。再一个,不主动将消息标为失败,而是等超时,如果设置的超时时间过长(当然超时时间太长也不合理),也会引入一些问题。比如说kafkaSpout, 一条消息没被ack之前是不会继续取后边的数据的,这样如果有一条数据需要等超时,同分区下的数据在这一个超时周期内,就都无法被处理了。
从另一方面来说,如果像FailedException一样处理其他所有异常,由于异常之后可以看到有数据fail,也并不会掩盖问题。
所以说,这一块的处理逻辑,个人感觉还是需要斟酌一下。


猜你喜欢
- Dockerfile 构建java web 环境Dockfile 介绍:Dockfile是一种被Docker程序解释的脚本,Dockerfi
- Java提供一种机制叫做序列化,通过有序的格式或者字节序列持久化java对象,其中包含对象的数据,还有对象的类型,和保存在对象中
- IO流代码:void LoadByIO() { float time = Time.t
- 这篇文章主要介绍了Java通过Scanner了解if...else if语句,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的
- 本文实例为大家分享了C++实现连连看游戏的具体代码,供大家参考,具体内容如下这个项目还是挺不错的,运行后也比较有意思,可以看看。#inclu
- 以下是介绍利用List的subList方法实现对List分页,废话不多说了,直接看代码把/** *//** * List分页 &
- 方法一:实现Comparator接口,并重写compare方法实体类代码:import java.util.Comparator;/** *
- java中 Set与Map排序输出到Writer详解及实例一般来说java.util.Set,java.util.Map输出的内
- .net core提供了Json处理模块,在命名空间System.Text.Json中,下面通过顶级语句,对C#的Json功能进行讲解。序列
- 本文实例讲述了Java连接redis及基本操作。分享给大家供大家参考,具体如下:点击此处:本站下载安装。解压安装启动redis:使用cd命令
- 基本哪些属于引用类型类(object,string),接口、数组、委托引用类型分配在哪里引用类型变量位于线程栈。引用类型实例分配在托管堆上。
- 概念CAS的全称是Compare-And-Swap,它是cpu并发原语它的功能是判断内存某个位置的值是否为预期值。如果是则更改为新的值,这个
- java.lang.NoClassDefFoundError错误解决办法前言在日常Java开发中,我们经常碰到java.lang.NoCla
- 主要功能共有三个角色:管理员、教师、学生。管理员功能有:学生管理、教师管理、评教管理、指标管理、课程管理等。教师功能有:学生管理、指标管理、
- 前言我们知道在Java中除了基础的数据类型以外,其它的都为引用类型。而Java根据其生命周期的长短将引用类型又分为强引用、软引用、弱引用、幻
- 自动完成文本框(AutoCompleteTextView),用于实现允许用户输入一定字符后,显示一个下拉菜单,供用户从中选择,当用户选择某个
- 本文实例讲述了Android ActionBar搜索功能用法。分享给大家供大家参考,具体如下:使用ActionBar SearchView时
- 实现HandlerInterceptor接口或者继承HandlerInterceptor的子类,比如Spring 已经提供的实现了Handl
- springboot多模块项目添加一新模块选择Maven Module,填写模块名若空白,catalog目录可选择internal更改包名完
- code #1private void Form1_SizeChanged(object sender, EventArgs e) //最小