rabbitmq取消自动重连_rabbitmq-access

20161227 更新

1 bug fix: 将messageProcess包裹在try,catch中,避免队列中出现unack的死信息

20161205 更新

1 增加topic模式

2 原有的使用direct方式无需更改,本次为兼容性升级,增加了buildTopicMessageSender和buildTopicMessageConsumer方法

3 ThreadPoolConsumer默认为direct方式,可以通过setType("topic")修改为topic模式

20160907 更新

1 解决因网络抖动而引起的发送数据丢失

2 增加retry模块

3 在本地缓存已发送数据,根据ack的确认将已ack的删除

4 定时触发重发未收到ack的数据

5 保证在网络抖动的情况下数据不丢失,但可能会造成数据的重复发送(建议在consumer端做到message处理的幂等性)

最近的一个计费项目,在rpc调用和流式处理之间徘徊了许久,后来选择流式处理。一是可以增加吞吐量,二是事务的控制相比于rpc要容易很多。

确定了流式处理的方式,后续是技术的选型。刚开始倾向于用storm,无奈文档实在太少,折腾起来着实费劲。最终放弃,改用消息队列+微服务的方式实现。

消息队列的选型上,有activemq,rabbitmq,kafka等。最开始倾向于用activemq,因为以前的项目用过,很多代码都是可直接复用的。后来看了不少文章对比,发现rabbitmq对多语言的支持更好一点,同时相比于kafka,牺牲了部分的性能换取了更好的稳定性安全性以及持久化。

最终决定使用rabbitmq。

rabbitmq的官网如下:

对rabbitmq的封装,有几个目标:

1 提供send接口

2 提供consume接口

3 保证消息的事务性处理

所谓事务性处理,是指对一个消息的处理必须严格可控,必须满足原子性,只有两种可能的处理结果:

(1) 处理成功,从队列中删除消息

(2) 处理失败(网络问题,程序问题,服务挂了),将消息重新放回队列

为了做到这点,我们使用rabbitmq的手动ack模式,这个后面细说。

1 send接口

public interface MessageSender {

DetailRes send(Object message);

}

send接口相对简单,我们使用spring的RabbitTemplate来实现,代码如下:

//1 构造template, exchange, routingkey等

//2 设置message序列化方法

//3 设置发送确认

//4 构造sender方法

public MessageSender buildMessageSender(final String exchange, final String routingKey, final String queue) throws IOException, TimeoutException {

Connection connection = connectionFactory.createConnection();

//1

buildQueue(exchange, routingKey, queue, connection);

final RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);

rabbitTemplate.setMandatory(true);

rabbitTemplate.setExchange(exchange);

rabbitTemplate.setRoutingKey(routingKey);

//2

rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());

//3

rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {

@Override

public void confirm(CorrelationData correlationData, boolean ack, String cause) {

if (!ack) {

log.info("send message failed: " + cause); //+ correlationData.toString());

throw new RuntimeException("send error " + cause);

}

}

});

//4

return new MessageSender() {

@Override

public DetailRes send(Object message) {

try {

rabbitTemplate.convertAndSend(message);

} catch (RuntimeException e) {

e.printStackTrace();

log.info("send failed " + e);

try {

//retry

rabbitTem

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值