大数据_Storm_cluster模式下storm kill topology时做cleanup的解决方法

1.背景

在bolt中,需要在topology被关闭前执行某个操作,而根据官方文档:


The  cleanup method is called when a Bolt is being shutdown and should cleanup any resources that were opened. There's no guarantee that this method will be called on the cluster: for example, if the machine the task is running on blows up, there's no way to invoke the method. The  cleanup method is intended for when you run topologies in  local mode (where a Storm cluster is simulated in process), and you want to be able to run and kill many topologies without suffering any resource leaks.

cleanup方法并不可靠,它只在local mode下生效。

2.解决方案

在killing a topology之前,需要先deactivate相应的topology,然后处理未完成的message。可以调用Spout.deactivate()方法,传给bolt一个特殊的tuple,在bolt处检查该特殊tuple,一旦收到执行需要执行的操作。
tuple的特殊性可以通过tuple的stream来区分。


3.code&result

下面的代码中,正常的消息都来自kafkaSpout,对于关闭的信息,单独写了一个spout叫MySpout来处理。

topology部分:增加单独的Spout

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public StormTopology buildTopology(Map map) {  
  2.     String zkServer = map.get("zookeeper").toString();  
  3.     System.out.println("zkServer: " + zkServer);  
  4.     final BrokerHosts zkHosts = new ZkHosts(zkServer);  
  5.     SpoutConfig kafkaConfig = new SpoutConfig(zkHosts, Constants.KAFKA_TOPIC, "/test""shutdown-test");  
  6.     kafkaConfig.scheme = new SchemeAsMultiScheme(new StringScheme());  
  7.     TopologyBuilder builder = new TopologyBuilder();  
  8.     builder.setSpout("kafkaSpout"new KafkaSpout(kafkaConfig), SPOUT_PARALLELISM_HINT);  
  9.     builder.setSpout("shutDownSpout"new MySpout());  
  10.     builder.setBolt("parseBolt"new ParseBolt(), PARSE_BOLT_PARALLELISM_HINT).  
  11.             shuffleGrouping("kafkaSpout").allGrouping("shutDownSpout""stop");  
  12.     builder.setBolt("ToDruidBolt"new BeamBolt(new ToDruidBolt()), STAT_BOLT_PARALLELISM_HINT).shuffleGrouping("parseBolt");  
  13.     return builder.createTopology();  
  14. }  

MySpout部分:重点在于deactivate方法和declareOutputFields方法,后者的
message.declareStream方法标记了topology deactivate前发送的tuple的stream,用于在bolt中与普通tuple做区别。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class MySpout extends BaseRichSpout {  
  2.     private static final Logger logger = LoggerFactory.getLogger(MySpout.class);  
  3.     private SpoutOutputCollector _collector;  
  4.   
  5.     public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {  
  6.         logger.info("shutdown spout open function called");  
  7.         _collector = collector;  
  8.     }  
  9.   
  10.     public void activate() {  
  11.         logger.info("shutdown spout activate function called");  
  12.     }  
  13.   
  14.     public void deactivate() {  
  15.         logger.info("shutdown deaactivate to spout and bolt");  
  16.         try {  
  17.             String mes = "shutDown";  
  18.             long id = 11111111111111111L;  
  19.             _collector.emit("stop"new Values(mes), id);  
  20.             //Thread.sleep(1000);  
  21.         } catch (Exception e) {  
  22.             e.printStackTrace();  
  23.         }  
  24.     }  
  25.   
  26.     public void nextTuple() {  
  27.         try {  
  28.             Thread.sleep(10000);  
  29.         } catch (Exception e) {  
  30.             e.printStackTrace();  
  31.         }  
  32.     }  
  33.   
  34.     public void declareOutputFields(OutputFieldsDeclarer message) {  
  35.         message.declareStream("stop"new Fields("stop"));  
  36.     }  
  37.   
  38.     public void ack(Object msgId) {  
  39.         logger.info("shutDown spout ack, msId " + msgId);  
  40.     }  
  41.   
  42.     public void fail(Object msgId) {  
  43.         logger.error("shutDown spout fail, msId " + msgId);  
  44.     }  
  45. }  

ParseBolt部分:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. if ( tuple.getSourceStreamId().equals("stop") ) {  
  2.     System.out.println("==========clear=============");  
  3.     flush();  
  4.     return;  
  5. }  
  6. public void flush() {  
  7.     //some things to do before topology will be killed  
  8. }  

4.注意事项

(1)kill topology时,建议输入的等待时间尽量长,有时时间过短消息来不及传递,会导致该方法失效
(2)对接spout的bolt一般不只一个,需要用allGrouping策略来确保这些bolt都收到消息


参考:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值