storm坑之---传递对象
继之前遇到的那个同步问题的坑之后(storm坑之---同步问题),最近对代码又做了调整和重构,并且又遇到了另一个storm开发中应该值得警惕的坑。接下来说说这个坑的大体情况。
在我的storm程序中,Abolt需要将数据封装成一个对象同时发送给Bbolt和Cbolt各一份,Bbolt和Cbolt分别对对象做一定的处理后,更新到数据库。在查看日志时,意外的发现有些数据是不正确的诡异的,我先是怀疑算法问题,但又发现有部分数据又是正确的。算法应该没啥问题。纠结之下之后打印了更详细的日志,通过观察诡异数据的规律最后恍然大悟:肯定是Bbolt收到对象后对对象的修改影响到了Cbolt。在这里笔者几乎可以肯定的是:当Bbolt和Cbolt运行在同一个进程中时。发送给Bbolt和Cbolt的对象他们是公用的。Bbolt的修改会影响到Cbolt,反之亦然。如果Bbolt和Cbolt不是同一进程,则没有此影响。这就解释了为什么有的数据正常有的异常。
下面举一个例子代码测试一下:
拓扑构建类:
public class Main {
public static void main(String[] args) {
TopologyBuilder builder = new TopologyBuilder();
builder.setSpout("test", new TestWordSpout());
builder.setBolt("print1",new PrintBolt("PrintBolt1")).shuffleGrouping("test");
builder.setBolt("print2",new PrintBolt("PrintBolt2")).shuffleGrouping("test");
Config conf = new Config();
conf.setDebug(false);
conf.setNumWorkers(1);
LocalCluster cluster = new LocalCluster();
cluster.submitTopology("test-kafka-1", conf, builder.createTopology());
}
}
spout类:
public class TestWordSpout extends BaseRichSpout {
private static final long serialVersionUID = 1L;
SpoutOutputCollector _collector;
public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
_collector = collector;
}
public void close() {
}
public void nextTuple() {
Utils.sleep(1000);
Name name = new Name();
name.setName("123");
_collector.emit(new Values(name));
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word"));
}
}
bolt类:
public class PrintBolt extends BaseRichBolt {
private static final long serialVersionUID = 1L;
private String name;
int taskid;
public PrintBolt(String name){
this.name = name;
}
@Override
public void prepare(Map stormConf, TopologyContext context,
OutputCollector collector) {
this.taskid = context.getThisTaskId();
}
@Override
public void execute(Tuple input) {
Name name = (Name) input.getValueByField("word");
System.out.println(logPrefix()+name.getName());
name.setName(this.name);
}
private String logPrefix(){
return this.name+":";
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
}
}
可能发生的执行结果:
PrintBolt2:123
PrintBolt1:123
PrintBolt2:123
PrintBolt1:123
PrintBolt2:123
PrintBolt1:123
PrintBolt2:PrintBolt1
PrintBolt2:123
PrintBolt1:123
PrintBolt1:123
PrintBolt2:123
PrintBolt1:123
PrintBolt2:123
从上边结果可以看到,PrintBolt2打印了PrintBolt1的修改。
了解了这个情况,以后写代码就得要考虑到这种意外。如果一个对象会同时发送给两个bolt来处理,切bolt都要对此对象进行修改,在做修改之前一定要克隆一份,而不要直接修改!
storm坑之---传递对象的更多相关文章
- Message和handler传递对象
Bundle可以传递对象,message又可以传递Bundle于是就可以利用buddle作为中间载体传递对象了 Message msg = Message.obtain(); Bundle b = ...
- Android 全局获取 Context 与使用 Intent 传递对象
=====================全局获取 Context======================== Android 开发中很多地方需要用到 Context,比如弹出 Toast.启动活 ...
- Android--Intent传递对象
Intent 传递对象通常有两种实现方式,Serializable 和 Parcelable: 一.Serializable:序列化,表示将一个对象转换成可存储或可传输的状态,序列化后的对象可以在网络 ...
- 实现在GET请求下调用WCF服务时传递对象(复合类型)参数
WCF实现RESETFUL架构很容易,说白了,就是使WCF能够响应HTTP请求并返回所需的资源,如果有人不知道如何实现WCF支持HTTP请求的,可参见我之前的文章<实现jquery.ajax及原 ...
- Android中如何使用Intent在Activity之间传递对象[使用Serializable或者Parcelable]
http://blog.csdn.net/cjjky/article/details/6441104 在Android中的不同Activity之间传递对象,我们可以考虑采用Bundle.putSeri ...
- Intent传递对象的两种方法(Serializable,Parcelable) (转)
今天讲一下Android中Intent中如何传递对象,就我目前所知道的有两种方法,一种是Bundle.putSerializable(Key,Object);另一种是Bundle.putParcela ...
- Intent传递对象的两种方法
Android为intent提供了两种传递对象参数类型的方法 分别需要使实体类实现Serializable接口.Parcelable接口 首先我们要知道,传递对象,需要先将对象序列化 一.那么为什么要 ...
- Android中Intent传递对象的两种方法(Serializable,Parcelable)
今天要给大家讲一下Android中 Intent中如何传递对象,就我目前所知道的有两种方法,一种是Bundle.putSerializable(Key,Object);另一种是 Bundle.putP ...
- 利用Bundle在activity之间传递对象
(2010-12-04 09:45:54) 转载▼ 标签: it 分类: android开发 转自:http://chen592969029.javaeye.com/blog/772656 假如需要在 ...
随机推荐
- HTML5-格式化
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- codeblocks配置GLUT
codeblocks配置OPENGL GLUT 作者 He YiJun – storysnail<at>gmail.com 团队 ls 版权 转载请保留本声明! 本文档包含的原创代码根据G ...
- 在WebApi中基于Owin OAuth使用授权发放Token
如何基于Microsoft.Owin.Security.OAuth,使用Client Credentials Grant授权方式给客户端发放access token? Client Credentia ...
- 全面理解Javascript闭包和闭包的几种写法及用途
好久没有写博客了,过了一个十一长假都变懒了,今天总算是恢复状态了.好了,进入正题,今天来说一说javascript里面的闭包吧!本篇博客主要讲一些实用的东西,主要将闭包的写法.用法和用途. 一.什么 ...
- Ubuntu环境搭建系列—JavaEE篇
恩,其实我是一时兴起,所以就写了目前这几篇环境的博文,希望能给自己做一个笔记,同时也能够给一些新手带来一些帮助,不会在配置方面那么迷茫.本篇文章主要就是针对Java web开发进行环境搭建. 一.To ...
- Ember.js实现单页面应用程序
1.1.1 摘要 单页应用程序 (SPA) 是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序. SPA使用AJAX和HTML5创建流畅且响应迅速的Web应用程序,不会经常 ...
- 据说每个大牛、小牛都应该有自己的库——Event处理
今天抽时间写了一部分Event处理方面的函数愈发的觉得jQuery的优秀,自己前期的想法太粗糙,造成后面这些函数参数很多,操作很很不直观,看样子是要重构的节奏,还好小伙儿伴们安慰,架构都是改出来的.继 ...
- 虚拟化平台cloudstack(4)——几个异常
cloudstack主机添加不成功 CloudStack正常启动,添加区域.提供点和群集都正常,但是添加主机时提示添加不成功. 先添加主机: 然后出现提示: 在网上找了一圈,基本上没什么回复,没办法, ...
- 使用aggregate在MongoDB中查找重复的数据记录
我们知道,MongoDB属于文档型数据库,其存储的文档类型都是JSON对象.正是由于这一特性,我们在Node.js中会经常使用MongoDB进行数据的存取.但由于Node.js是异步执行的,这就导致我 ...
- cxf restful
Restful 服务端 1 创建好pojo.dao.service, dao进行数据库操作,service提供服务 @Path("/roomservice") @Produces( ...