1、定义拓扑topology

public class MessageTopology {

    public static void main(String[] args) throws Exception {
//组装topology
TopologyBuilder topologyBuilder = new TopologyBuilder();
topologyBuilder.setSpout("RabbitmqSpout", new RabbitmqSpout());
topologyBuilder.setBolt("FilterBolt", new FilterBolt()).shuffleGrouping("RabbitmqSpout"); Config conf = new Config ();
try {
if (args.length > 0) {
StormSubmitter.submitTopology(args[0], conf, topologyBuilder.createTopology());
} else {
LocalCluster localCluster = new LocalCluster();
localCluster.submitTopology("messageTopology", conf, topologyBuilder.createTopology());
}
} catch (AlreadyAliveException e) {
e.printStackTrace();
}
}
}

2、定义数据源RabbitmqSpout

RabbitmqSpout继承自org.apache.storm.topology.IRichSpout接口,实现对应的方法:open(),close(),activate(),deactivate(),nextTuple(),ack(),fail()。

unconfirmedMap对象存储了MQ所有发射出去等待确认的消息唯一标识deliveryTag,当storm系统回调ack、fail方法后进行MQ消息的成功确认或失败重回队列操作(Storm系统回调方法会在bolt操作中主动调用ack、fail方法时触发)。

public class RabbitmqSpout implements IRichSpout {
private final Logger LOGGER = LoggerFactory.getLogger(RabbitmqSpout.class); private Map map;
private TopologyContext topologyContext;
private SpoutOutputCollector spoutOutputCollector; private Connection connection;
private Channel channel; private static final String QUEUE_NAME = "message_queue";
private final Map<String, Long> unconfirmedMap = Collections.synchronizedMap(new HashMap<String, Long>()); //连接mq服务
private void connect() throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setUsername("admin");
factory.setPassword("admin");
factory.setVirtualHost("/"); connection = factory.newConnection();
channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, true, false, false, null);
} @Override
public void open(Map map, TopologyContext topologyContext, SpoutOutputCollector spoutOutputCollector) {
this.map = map;
this.topologyContext = topologyContext;
this.spoutOutputCollector = spoutOutputCollector; try {
this.connect();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
} @Override
public void close() {
try {
channel.close();
connection.close();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
} @Override
public void nextTuple() {
try {
GetResponse response = channel.basicGet(QUEUE_NAME, false);
if (response == null) {
Utils.sleep(3000);
} else {
AMQP.BasicProperties props = response.getProps();
String messageId = UUID.randomUUID().toString();
Long deliveryTag = response.getEnvelope().getDeliveryTag();
String body = new String(response.getBody()); unconfirmedMap.put(messageId, deliveryTag);
LOGGER.info("RabbitmqSpout: {}, {}, {}, {}", body, messageId, deliveryTag, props); this.spoutOutputCollector.emit(new Values(body), messageId);
}
} catch (IOException e) {
e.printStackTrace();
}
} @Override
public void ack(Object o) {
String messageId = o.toString();
Long deliveryTag = unconfirmedMap.get(messageId);
LOGGER.info("ack: {}, {}, {}\n\n", messageId, deliveryTag, unconfirmedMap.size());
try {
unconfirmedMap.remove(messageId);
channel.basicAck(deliveryTag, false);
} catch (IOException e) {
e.printStackTrace();
}
} @Override
public void fail(Object o) {
String messageId = o.toString();
Long deliveryTag = unconfirmedMap.get(messageId);
LOGGER.info("fail: {}, {}, {}\n\n", messageId, deliveryTag, unconfirmedMap.size());
try {
unconfirmedMap.remove(messageId);
channel.basicNack(deliveryTag, false, true);
} catch (IOException e) {
e.printStackTrace();
}
} @Override
public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
outputFieldsDeclarer.declare(new Fields("body"));
} @Override
public Map<String, Object> getComponentConfiguration() {
return null;
} @Override
public void activate() { } @Override
public void deactivate() { }
}

3、定义数据流处理FilterBolt

public class FilterBolt implements IRichBolt {
private final Logger LOGGER = LoggerFactory.getLogger(FilterBolt.class); private Map map;
private TopologyContext topologyContext;
private OutputCollector outputCollector; @Override
public void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {
this.map = map;
this.topologyContext = topologyContext;
this.outputCollector = outputCollector;
} @Override
public void execute(Tuple tuple) {
String value = tuple.getStringByField("body"); LOGGER.info("FilterBolt:{}", value);
outputCollector.ack(tuple);
} @Override
public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
outputFieldsDeclarer.declare(new Fields("body"));
} @Override
public Map<String, Object> getComponentConfiguration() {
return null;
} @Override
public void cleanup() { }
}

Storm框架:如何消费RabbitMq消息(代码案例)的更多相关文章

  1. 压测应用服务对RabbitMQ消息的消费能力--实践脚本

    最近运维跟我反馈我负责的应用服务线上监控到消费RabbitMQ消息队列过慢,目前只有20左右,监控平台会有消息积压的告警. 开发修改了一版应用服务的版本,提交给我做压测验证. 之前没有做过消息中间件的 ...

  2. RabbitMQ消息队列阻塞导致服务器宕机

    最近工作中存储服务器由于压力太大无法及时消费消息.这个过程中,导致RabbitMQ意外挂掉,无法访问.下面是部分问题分析过程. 麒麟系统服务器分析 1.服务器异常信息: [root@localhost ...

  3. RabbitMQ学习系列二:.net 环境下 C#代码使用 RabbitMQ 消息队列

    一.理论: .net环境下,C#代码调用RabbitMQ消息队列,本文用easynetq开源的.net Rabbitmq api来实现. EasyNetQ 是一个易于使用的RabbitMQ的.Net客 ...

  4. RabbitMQ消息丢失问题和保证消息可靠性-消费端不丢消息和HA(二)

    继续上篇文章解决RabbitMQ消息丢失问题和保证消息可靠性(一) 未完成部分,我们聊聊MQ Server端的高可用和消费端如何保证消息不丢的问题? 回归上篇的内容,我们知道消息从生产端到服务端,为了 ...

  5. RabbitMQ消息发布和消费的确认机制

    前言 新公司项目使用的消息队列是RabbitMQ,之前其实没有在实际项目上用过RabbitMQ,所以对它的了解都谈不上入门.趁着周末休息的时间也猛补习了一波,写了两个窗体应用,一个消息发布端和消息消费 ...

  6. RabbitMQ消息的消费与持久化

    作为消费者的客户端要消费Rabbitmq的消息,首先要建立与它某个队列的连接,具体连接时可指定队列的BindingKey和关系的exchange标识,Rabbitmq判断若已有队列通过BindingK ...

  7. RabbitMQ学习系列三:.net 环境下 C#代码订阅 RabbitMQ 消息并处理

    上一篇已经讲了Rabbitmq如何在Windows平台安装 不懂请移步: RabbitMQ学习系列二:.net 环境下 C#代码使用 RabbitMQ 消息队列 一.理论 .net环境下,C#代码订阅 ...

  8. 消息中间件RabbitMq的代码使用案例

    消费者: ---------------------- 构造初始化: public RabbitMqReceiver(String host, int port, String username, S ...

  9. 使用EasyNetQ组件操作RabbitMQ消息队列服务

    RabbitMQ是一个由erlang开发的AMQP(Advanved Message Queue)的开源实现,是实现消息队列应用的一个中间件,消息队列中间件是分布式系统中重要的组件,主要解决应用耦合, ...

随机推荐

  1. pageadmin CMS网站制作教程:栏目单页内容如何修改

    pageadmin CMS网站制作教程:栏目单页内容如何修改 一般情况下,如公司介绍,联系方式等介绍内页面都属于单页,单页内容可以直接在栏目设置界面进行修改,如下 1.对栏目单页内容进行设置,登录后台 ...

  2. [Swift实际操作]七、常见概念-(10)使用UserDefaults和归档方式存取用户数据实际操作

    在项目开发之中,你会经常需要将一些数据存储在本地,以便记录用户生产的数据或操作习惯.在项目文件夹上带点击鼠标右键.弹出右键菜单.本文将为你演示,存储用户数据的两种常用方式. 选择菜单中的创建新文件选项 ...

  3. Linux命令学习与使用2

    1.Ctrl+a:跳到命令行首 Ctrl+E: 跳到命令行尾 Ctrl+L:清屏2.切换用户 su - 用户名3.更换yum镜像源 1.进入/etc/yum.repos.d 备份CentOS-Base ...

  4. cms的使用与总结

    1,把cms中的basecms复制进Wamp里面的www文件夹, 2,打开Wamp,打开网址http://localhost/basecms/core/admin/admin.php(该网址默认端口为 ...

  5. 【BZOJ3992】【SDOI2015】序列统计 EGF+多项式快速幂+循环卷积

    如果是求$n$个数之和在模$m$意义下为$x$,那么做法是显然的. 但是这道题问的是$n$个数之积在模m意义下为$x$,那么做法就和上面的问题不同. 考虑如何把乘法转换成加法(求log): 题目中有一 ...

  6. 【bzoj3028】 食物 生成函数+隔板法

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3028 这题的推导很妙啊,裸的推母函数的题. 我们首先构造出每种食物的母函数: 汉堡:$ ...

  7. 51单片机SRF寄存器

    1.21个寄存器介绍        51系列单片机内部主要有四大功能模块,分别是I/O口模块.中断模块.定时器模块和串口通信模块(串行I/O口),如其结构和功能如下图: 图1 51单片机结构和功能图 ...

  8. (转)Python——functools

    原文:https://www.cnblogs.com/Security-Darren/p/4168310.html#t7 http://www.wklken.me/posts/2013/08/18/p ...

  9. sql server 2012 数据库日志文件过大,怎么缩小?

    最近发现网站不能访问,原因数据库服务器磁盘剩余空间没了.再细查发现日志文件占用了70%,收缩日志文件失败. 在网上查找原因,是没有备份不能收缩日志文件. 临时解决的方式: 备份事务日志,再收缩日志文件 ...

  10. 监督学习——决策树理论与实践(上):分类决策树

    1. 介绍         决策树是一种依托决策而建立起来的一种树.在机器学习中,决策树是一种预测模型,代表的是一种对象属性与对象值之间的一种映射关系,每一个节点代表某个对象/分类,树中的每一个分叉路 ...