Storm入门(七)可靠性机制代码示例
一、关联代码
使用maven,代码如下。
pom.xml 参考 http://www.cnblogs.com/hd3013779515/p/6970551.html
MessageTopology.java

- package cn.ljh.storm.reliability;
- import org.apache.storm.Config;
- import org.apache.storm.LocalCluster;
- import org.apache.storm.topology.TopologyBuilder;
- import org.apache.storm.utils.Utils;
- public class MessageTopology {
- public static void main(String[] args) throws Exception {
- TopologyBuilder builder = new TopologyBuilder();
- builder.setSpout("MessageSpout", new MessageSpout(), 1);
- builder.setBolt("SpilterBolt", new SpliterBolt(), 5).shuffleGrouping("MessageSpout");
- builder.setBolt("WriterBolt", new WriterBolt(), 1).shuffleGrouping("SpilterBolt");
- Config conf = new Config();
- conf.setDebug(false);
- LocalCluster cluster = new LocalCluster();
- cluster.submitTopology("messagetest", conf, builder.createTopology());
- Utils.sleep(20000);
- cluster.killTopology("messagetest");
- cluster.shutdown();
- }
- }

MessageSpou.java

- package cn.ljh.storm.reliability;
- import org.apache.storm.topology.OutputFieldsDeclarer;
- import java.util.Map;
- import org.apache.storm.spout.SpoutOutputCollector;
- import org.apache.storm.task.TopologyContext;
- import org.apache.storm.topology.base.BaseRichSpout;
- import org.apache.storm.tuple.Fields;
- import org.apache.storm.tuple.Values;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- public class MessageSpout extends BaseRichSpout {
- public static Logger LOG = LoggerFactory.getLogger(MessageSpout.class);
- private SpoutOutputCollector _collector;
- private int index = 0;
- private String[] subjects = new String[]{
- "Java,Python",
- "Storm,Kafka",
- "Spring,Solr",
- "Zookeeper,FastDFS",
- "Dubbox,Redis"
- };
- public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
- _collector = collector;
- }
- public void nextTuple() {
- if(index < subjects.length){
- String sub = subjects[index];
- //使用messageid参数,使可靠性机制生效
- _collector.emit(new Values(sub), index);
- index++;
- }
- }
- public void declareOutputFields(OutputFieldsDeclarer declarer) {
- declarer.declare(new Fields("subjects"));
- }
- @Override
- public void ack(Object msgId) {
- LOG.info("【消息发送成功!】(msgId = " + msgId + ")");
- }
- @Override
- public void fail(Object msgId) {
- LOG.info("【消息发送失败!】(msgId = " + msgId + ")");
- LOG.info("【重发进行中。。。】");
- _collector.emit(new Values(subjects[(Integer)msgId]), msgId);
- LOG.info("【重发成功!】");
- }
- }

SpliterBolt.java

- package cn.ljh.storm.reliability;
- import java.util.Map;
- import org.apache.storm.task.OutputCollector;
- import org.apache.storm.task.TopologyContext;
- import org.apache.storm.topology.OutputFieldsDeclarer;
- import org.apache.storm.topology.base.BaseRichBolt;
- import org.apache.storm.tuple.Fields;
- import org.apache.storm.tuple.Tuple;
- import org.apache.storm.tuple.Values;
- public class SpliterBolt extends BaseRichBolt {
- OutputCollector _collector;
- private boolean flag = false;
- public void prepare(Map conf, TopologyContext context, OutputCollector collector) {
- _collector = collector;
- }
- public void execute(Tuple tuple) {
- try{
- String subjects = tuple.getStringByField("subjects");
- // if(!flag && subjects.equals("Spring,Solr")){
- // flag = true;
- // int a = 1/0;
- // }
- String[] words = subjects.split(",");
- for(String word : words){
- //注意:要携带tuple对象,用于处理异常时重发策略。
- _collector.emit(tuple, new Values(word));
- }
- //对tuple进行ack
- _collector.ack(tuple);
- }catch(Exception ex){
- ex.printStackTrace();
- //对tuple进行fail,使重发。
- _collector.fail(tuple);
- }
- }
- public void declareOutputFields(OutputFieldsDeclarer declarer) {
- declarer.declare(new Fields("word"));
- }
- }

WriterBolt.java

- package cn.ljh.storm.reliability;
- import java.io.FileWriter;
- import java.io.IOException;
- import java.util.Map;
- import org.apache.storm.task.OutputCollector;
- import org.apache.storm.task.TopologyContext;
- import org.apache.storm.topology.OutputFieldsDeclarer;
- import org.apache.storm.topology.base.BaseRichBolt;
- import org.apache.storm.tuple.Tuple;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- public class WriterBolt extends BaseRichBolt {
- private static Logger LOG = LoggerFactory.getLogger(WriterBolt.class);
- OutputCollector _collector;
- private FileWriter fileWriter;
- private boolean flag = false;
- public void prepare(Map conf, TopologyContext context, OutputCollector collector) {
- _collector = collector;
- if(fileWriter == null){
- try {
- fileWriter = new FileWriter("D:\\test\\"+"words.txt");
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- public void execute(Tuple tuple) {
- try {
- String word = tuple.getStringByField("word");
- // if(!flag && word.equals("Kafka")){
- // flag = true;
- // int a = 1/0;
- // }
- fileWriter.write(word + "\r\n");
- fileWriter.flush();
- } catch (Exception e) {
- e.printStackTrace();
- //对tuple进行fail,使重发。
- _collector.fail(tuple);
- }
- //对tuple进行ack
- _collector.ack(tuple);
- }
- public void declareOutputFields(OutputFieldsDeclarer declarer) {
- }
- }

二、执行效果
1、代码要点说明
MessageSpout.java
(1)发射tuple时要设置messageId来使可靠性机制生效
- _collector.emit(new Values(sub), index);
(2)重写ack和fail方法

- @Override
- public void ack(Object msgId) {
- LOG.info("【消息发送成功!】(msgId = " + msgId + ")");
- }
- @Override
- public void fail(Object msgId) {
- LOG.info("【消息发送失败!】(msgId = " + msgId + ")");
- LOG.info("【重发进行中。。。】");
- _collector.emit(new Values(subjects[(Integer)msgId]), msgId);
- LOG.info("【重发成功!】");
- }

SpliterBolt.java
(1)发射新tuple时设置输入tuple参数,以使新tuple和输入tuple为一个整体
- _collector.emit(tuple, new Values(word));
(2)完成处理后进行ack,失败时进行fail
- _collector.ack(tuple);
- _collector.fail(tuple);
WriterBolt.java
(1)完成处理后进行ack,失败时进行fail
- _collector.ack(tuple);
- _collector.fail(tuple);
2、正常处理结果
3、放开SpliterBolt 的错误代码
结果显示能够正确的重发。
4、放开SpliterBolt 的错误代码
能够正确进行重发,但是文件中storm字符串出现了两次。
5、总结
通过以上测试,如果在第一个bolt处理时出现异常,可以让整个数据进行重发,如果第二个bolt处理时出现异常,也可以让整个数据进行重发,但是同时出现了重复处理的事务性问题,需要进行特殊的处理。
(1)如果数据入库的话,可以把messageId也进行入库保存。此messageId可以用来判断是否重复处理。
(2)事务性tuple尽量不要拆分。
(3)使用storm的Trident框架。
Storm入门(七)可靠性机制代码示例的更多相关文章
- Storm入门(四)WordCount示例
一.关联代码 使用maven,代码如下. pom.xml 和Storm入门(三)HelloWorld示例相同 RandomSentenceSpout.java /** * Licensed to t ...
- Linux信号机制代码示例
1 基本功能: 本Blog创建了两个进程(父子进程): 父进程: 执行文本复制操作,当收到 SIGUSR1信号后,打印出现在文件复制的进度: 子进程: 每个固定时间段向父进程发送一个 SIGUSR1 ...
- Storm入门(三)HelloWorld示例
一.配置开发环境 storm有两种操作模式: 本地模式和远程模式.使用本地模式的时候,你可以在你的本地机器上开发测试你的topology, 一切都在你的本地机器上模拟出来; 用远程模式的时候你提交的t ...
- <MyBatis>入门七 缓存机制
缓存机制 MyBatis包含强大的查询缓存特性,它可以非常方便的定制和配置.缓存可以极大的提升查询效率. MyBatis默认定义了两级缓存:一级缓存和二级缓存 1.默认情况下,只有一级缓存(sqlSe ...
- Storm入门(六)深入理解可靠性机制
转自http://blog.csdn.net/zhangzhebjut/article/details/38467145 一 可靠性简介 Storm的可靠性是指Storm会告知用户每一个消息单元是否在 ...
- My.Ioc 代码示例——使用观察者机制捕获注册项状态的变化
在 My.Ioc 中,要想在服务注销/注册时获得通知,可以通过订阅 ObjectBuilderRegistered 和 ObjectBuilderUnregistering 这两个事件来实现.但是,使 ...
- 中文代码示例之Angular入门教程尝试
原址: https://zhuanlan.zhihu.com/p/30853705 原文: 中文代码示例教程之Angular尝试 为了检验中文命名在Angular中的支持程度, 把Angular官方入 ...
- 中文代码示例之Vuejs入门教程(一)
原址: https://zhuanlan.zhihu.com/p/30917346 为了检验中文命名在主流框架中的支持程度, 在vuejs官方入门教程第一部分的示例代码中尽量使用了中文命名. 所有演示 ...
- 2017-10-31 中文代码示例教程之Vuejs入门&后续计划
"中文编程"知乎专栏原链 为了检验中文命名在主流框架中的支持程度, 这里把vuejs官方入门教程第一部分的示例代码中尽量使用了中文命名. 过程中有一些发现, 初步看来Vuejs对中 ...
随机推荐
- linux中~/cut/argus/
1.Linux shell 截取字符变量的前8位 实现方法有如下几种: expr substr "$a" 1 8 echo $a|awk '{print substr(,1,8)} ...
- JavaScript Array+String对象的常用方法
Array 对象 Array 对象用于在单个的变量中存储多个值. 创建 Array 对象的语法: new Array(); new Array(size); new Array(element0, e ...
- 远程连接MySQL(MariaDB)数据库
网络环境: MySQL(MariaDB)服务器的操作系统为 CentOS 7 MySQL(MariaDB)服务器IP:172.16.230.15 客户端操作系统为 Windows 2008 R2 客户 ...
- Robomongo连接MongoDB 报 Authorization failed 解决办法
首先将MongoDB安装文件的bin目录添加到环境变量Path中 如图: 这样就可以直接在cmd命令行,不需要进行目录切换,就可以直接使用啦 打开dos命令框 依次输入下图修改admin密码
- 根据高德API知道坐标获取详细地址信息
/** * 根据坐标获取具体地址 * @param coor 坐标字符串 * @return */ public static String getAdd(String coor){ String u ...
- 关于find命令的一些知识
在服务器运维的过程中,我们会用到这样一个命令,关于这个命令,你知道多少呢?接下来,咱们一起来研究一下它的用途. find命令主要用来在硬盘上搜索文件, find命令主要用于文件查找,列出当前目录及子目 ...
- client_v1.go
package nsqlookupd import ( "net" ) //客户端 结构体 type ClientV1 struct { net.Conn //客户 ...
- java.lang.IllegalArgumentException异常 数据库别名问题
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Path expect ...
- 【BZOJ 3626】 [LNOI2014]LCA【在线+主席树+树剖】
题目链接: TP 题解: 可能是我比较纱布,看不懂题解,只好自己想了…… 先附一个离线版本题解[Ivan] 我们考虑对于询问区间是可以差分的,然而这并没有什么卵用,然后考虑怎么统计答案. 首先LC ...
- [Poi2014]FarmCraft 树状dp
对于每个点,处理出走完其子树所需要的时间和其子树完全下载完软件的时间 易证,对于每个点的所有子节点,一定优先选择差值大的来给后面的时间 树规+贪心. #include<cstdio> #i ...