Storm框架:如何消费RabbitMq消息(代码案例)
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消息(代码案例)的更多相关文章
- 压测应用服务对RabbitMQ消息的消费能力--实践脚本
最近运维跟我反馈我负责的应用服务线上监控到消费RabbitMQ消息队列过慢,目前只有20左右,监控平台会有消息积压的告警. 开发修改了一版应用服务的版本,提交给我做压测验证. 之前没有做过消息中间件的 ...
- RabbitMQ消息队列阻塞导致服务器宕机
最近工作中存储服务器由于压力太大无法及时消费消息.这个过程中,导致RabbitMQ意外挂掉,无法访问.下面是部分问题分析过程. 麒麟系统服务器分析 1.服务器异常信息: [root@localhost ...
- RabbitMQ学习系列二:.net 环境下 C#代码使用 RabbitMQ 消息队列
一.理论: .net环境下,C#代码调用RabbitMQ消息队列,本文用easynetq开源的.net Rabbitmq api来实现. EasyNetQ 是一个易于使用的RabbitMQ的.Net客 ...
- RabbitMQ消息丢失问题和保证消息可靠性-消费端不丢消息和HA(二)
继续上篇文章解决RabbitMQ消息丢失问题和保证消息可靠性(一) 未完成部分,我们聊聊MQ Server端的高可用和消费端如何保证消息不丢的问题? 回归上篇的内容,我们知道消息从生产端到服务端,为了 ...
- RabbitMQ消息发布和消费的确认机制
前言 新公司项目使用的消息队列是RabbitMQ,之前其实没有在实际项目上用过RabbitMQ,所以对它的了解都谈不上入门.趁着周末休息的时间也猛补习了一波,写了两个窗体应用,一个消息发布端和消息消费 ...
- RabbitMQ消息的消费与持久化
作为消费者的客户端要消费Rabbitmq的消息,首先要建立与它某个队列的连接,具体连接时可指定队列的BindingKey和关系的exchange标识,Rabbitmq判断若已有队列通过BindingK ...
- RabbitMQ学习系列三:.net 环境下 C#代码订阅 RabbitMQ 消息并处理
上一篇已经讲了Rabbitmq如何在Windows平台安装 不懂请移步: RabbitMQ学习系列二:.net 环境下 C#代码使用 RabbitMQ 消息队列 一.理论 .net环境下,C#代码订阅 ...
- 消息中间件RabbitMq的代码使用案例
消费者: ---------------------- 构造初始化: public RabbitMqReceiver(String host, int port, String username, S ...
- 使用EasyNetQ组件操作RabbitMQ消息队列服务
RabbitMQ是一个由erlang开发的AMQP(Advanved Message Queue)的开源实现,是实现消息队列应用的一个中间件,消息队列中间件是分布式系统中重要的组件,主要解决应用耦合, ...
随机推荐
- BZOJ 5395--[Ynoi2016]谁的梦(STL&容斥)
5395: [Ynoi2016]谁的梦 Time Limit: 80 Sec Memory Limit: 128 MBSubmit: 22 Solved: 7[Submit][Status][Di ...
- Redis 的 Sentinel
Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务: 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服 ...
- 深入理解Java接口和抽象类
对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的时候会以为它们可以随意互换使用, ...
- 原生ajax封装,包含post、method方式
原生ajax封装,包含post.method方式 function ajax(method, url, data, success) { var xhr = null; try { xhr = new ...
- (转)MySQL慢查询日志总结
慢查询日志概念 原文:http://www.cnblogs.com/kerrycode/p/5593204.html MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应 ...
- (转)IBM AIX系统为rootvg实现镜像
IBM AIX系统为rootvg实现镜像 AIX系统安装的时候,没有选择安装镜像,因此在系统安装完成后,出于安全方面的考虑,决定为rootvg创建镜像. 工具/原料 AIX rootvg lspv c ...
- nodejs(三) --- nodejs进程与子进程
嗯,对于node的学习还远远不够,这里先做一个简单的api的记录,后续深入学习. 第一部分:nodejs中的全局对象之process进程对象 在node中的全局对象是global,相当于浏览器中的wi ...
- Linux下安装jdk8步骤详述(转载)
Linux下安装jdk8步骤详述 原文地址:http://www.cnblogs.com/shihaiming/p/5809553.html 作为Java开发人员,在Linux下安装一些开发工具是必备 ...
- 使用openssh-clients的scp命令来传输文件
了解openssh-client是请参阅:https://blog.csdn.net/u010215256/article/details/53239905 了解scp命令来传输文件请参阅:https ...
- java泛型---通配符,泛型嵌套
package generic; import java.util.ArrayList; import java.util.List; /** * ? -->通配符,类型不确定,用于声明 变量| ...