RabbitMQ必备核心知识(精选)

现在很多知名的互联网公司都有用到RabbitMQ,其性能,可扩展性让很多大公司青睐于使用它,不过想要完全使用好RabbitMQ需要掌握其核心的一些概念,这里就说说掌握RabbitMQ所需的必要知识

生产者与消费者

生产者: 创建消息,然后发送到代理服务器(RabbitMQ)的程序

消费者:连接到代理服务器,并订阅到队列上接收消息

消息流程

AMQP协议规定,AMQP消息必须有三部分,交换机,队列和绑定。生产者把消息发送到交换机,交换机与队列的绑定关系决定了消息如何路由到特定的队列,最终被消费者接收。

Note: 消息是不能直接到达队列(Queue)的

交换机

消息实际上投递到的是交换机,具体路由到那个队列由交换机根据路由键(routing key)完成。

当你发消息到代理服务器时,即便路由键是空的,RabbitMQ也会将其和使用的路由键进行匹配。如果路由的消息不匹配任何绑定模式,消息将会进入黑洞。

交换机在队列与消息中间起到了中间层的作用,有了交换机我们可以实现更灵活的功能,RabbitMQ中有三种常用的交换机类型:

direct: 如果路由键匹配,消息就投递到对应的队列

fanout:投递消息给所有绑定在当前交换机上面的队列

topic:允许实现有趣的消息通信场景,使得5不同源头的消息能够达到同一个队列。topic队列名称有两个特殊的关键字。

* 可以替换一个单词

# 可以替换所有的单词

可以理解,direct为1v1, fanout为1v所有,topic比较灵活,可以1v任意。

虚拟主机

每一个虚拟主机(vhost)相当于mini版的RabbitMQ服务器,拥有自己的队列,交换机和绑定,权限… 这使得一个RabbitMQ服务众多的应用程序,而不会互相冲突。

rabbitMQ默认的虚拟主机为: “/” ,一般我们在创建Rabbit的用户时会再给用户分配一个虚拟主机。

操作虚拟主机,除了命令行之外还有一个web管理页面

#创建虚拟主机

rabbitmqctl add vhost [vhost_name]

#删除虚拟主机

rabbitmqctl delete vhost [vhost_name]

#列出虚拟主机

rabbitmqctl list_vhosts

消息投递策略

默认情况下RabbitMQ的队列和交换机在RabbitMQ服务器重启之后会消失,原因在于队列和交换机的durable属性,该属性默认情况下为false.

能从AMQP服务器崩溃中恢复的消息称为持久化消息,如果想要从崩溃中恢复那么消息必须

投递模式设置2,来标记消息为持久化

发送到持久化的交换机

到到持久化的队列

缺点:消息写入磁盘性能差很多。除非特别关键的消息会使用

关键API

以上都是概念性的内容,实际我们还是要通过编程来实现我们的目的,RabbitMQ的客户端api提供了很多功能,通过看代码,来了解它的强大之处。

基本步骤之前的RabbitMQ快速入门已经提过了,Channel类是关键的部分:包含了很多我们想要的功能

消息确认

生成端可以添加监听事件:

channel.addConfirmListener(new ConfirmListener() {

@Override

public void handleNack(long deliveryTag, boolean multiple) throws IOException {

System.err.println("-------no ack!-----------");

}

@Override

public void handleAck(long deliveryTag, boolean multiple) throws IOException {

System.err.println("-------ack!-----------");

}

});

消费端可以确认消息状态:

public class MyConsumer extends DefaultConsumer {

private Channel channel ;

public MyConsumer(Channel channel) {

super(channel);

this.channel = channel;

}

@Override

public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {

System.err.println("-----------consume message----------");

System.err.println("body: " + new String(body));

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

e.printStackTrace();

}

if((Integer)properties.getHeaders().get("num") == 0) {

channel.basicNack(envelope.getDeliveryTag(), false, true);

} else {

channel.basicAck(envelope.getDeliveryTag(), false);

}

}

}

channel.basicAck与basicNack最后一个参数指定消息是否重回队列。

监听不可达消息

我们的消息生产者通过指定交换机和路由键来把消息送到队列中,但有时候指定的路由键不存在,或者交换机不存在,那么消息就会return,我们可以通过添加return listener来实现:

channel.addReturnListener(new ReturnListener() {

@Override

public void handleReturn(int replyCode, String replyText, String exchange,

String routingKey, BasicProperties properties, byte[] body) throws IOException {

System.err.println("---------handle return----------");

System.err.println("replyCode: " + replyCode);

System.err.println("replyText: " + replyText);

System.err.println("exchange: " + exchange);

System.err.println("routingKey: " + routingKey);

System.err.println("properties: " + properties);

System.err.println("body: " + new String(body));

}

});

channel.basicPublish(exchange, routingKeyError, true, null, msg.getBytes());

在basicPublish中的Mandatory要设置为true才会生效,否则broker会删除该消息

消费端限流

假设MQ服务器上面囤积了成千上万条的消息的时候,这个时候突然连接消费端,那么巨量的消息全部推过来,但是客户端无法一次性处理这么多的数据。

在高并发的时候,瞬间产生的流量很大,消息很大,而MQ有个重要的作用就是限流,限流则是消费端做的。

RabbitMQ提供了一种Qos(服务质量保证)功能,即在非自动确认消息的前提下,在一定数量的消息未被消费前,不进行消费新的消息。

// prefetchSize消息的限制大小,一般设置为0,在生产端限制

// prefetchCount 我们一次最多消费多少条消息,一般设置为1

// global,一般设置为false,在消费端进行限制

channel.basicQos(int prefetchSize, int prefetchCount, boolean global)

// 使用

channel.basicQos(0, 1, false);

channel.basicConsume(queueName, false, new MyConsumer(channel));

Note: autoAck设置为false, 一定要手工签收消息

死信队列(DLX)

当消息在队列中变成死信,没有消费者进行消费的时候,消息可能会被重新发布到另外一个队列中,这个队列就是死信队列。

以下情况会导致消息进入死信队列:

basic.reject/basic.nack 并且 requeue为false(不重回队列)的时候,消息就是死信

消息TTL过期

队列达到最大的长度

死信队列也是正常的Exchange,和一般的Exchange没什么区别,不过要做一点操作。

设置死信队列包括:

设置Exchange(dlx.exchange名称随意),设置Queue(dlx.queue),设置RoutingKey(#)

创建正常的交换机,队列,绑定,只不过加上一个参数 arguments.put(“x-dead-letter-exchange”,“dlx.exchange”)

// 这就是一个普通的交换机 和 队列 以及路由

String exchangeName = "test_dlx_exchange";

String routingKey = "dlx.#";

String queueName = "test_dlx_queue";

channel.exchangeDeclare(exchangeName, "topic", true, false, null);

Map agruments = new HashMap();

agruments.put("x-dead-letter-exchange", "dlx.exchange");

//这个agruments属性,要设置到声明队列上

channel.queueDeclare(queueName, true, false, false, agruments);

channel.queueBind(queueName, exchangeName, routingKey);

//要进行死信队列的声明:

channel.exchangeDeclare("dlx.exchange", "topic", true, false, null);

channel.queueDeclare("dlx.queue", true, false, false, null);

channel.queueBind("dlx.queue", "dlx.exchange", "#");

Java高架构师、分布式架构、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战学习架构师视频免费获取架构群:854180697

群链接:加群链接

写在最后:欢迎留言讨论,加关注,持续更新!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351

推荐阅读更多精彩内容

  • http://liuxing.info/2017/06/30/Spring%20AMQP%E4%B8%AD%E6%...
    sherlock_6981阅读 15,899评论 2 11
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,644评论 18 139
  • 来源 RabbitMQ是用Erlang实现的一个高并发高可靠AMQP消息队列服务器。支持消息的持久化、事务、拥塞控...
    jiangmo阅读 10,353评论 2 34
  • 摘要:RabbitMQ发送消息时,都是先把消息发送给ExChange(交换机),然后再分发给有相应RoutingK...
    请叫wo小爷阅读 1,280评论 0 2
  • 春天,树叶开始闪出黄青,花苞轻轻的在风中摆动,似乎夹杂着一种冬天的凄寒,只等着一场春雨的洗礼,春天才是真正的来临...
    微汐儿阅读 403评论 0 2