RabbitMQ详解(二)------消息通信的概念
PS:近期在南宁出差,工作比较忙,所以更新会比较慢。
说到消息通信,可能我们首先会想到的是邮箱,QQ,微信,短信等等这些通信方式,这些通信方式都有发送者,接收者,还有一个中间存储离线消息的容器。但是这些通信方式和我们要讲的 RabbitMQ 的通信模型是不一样的,比如和邮件的通信方式相比,邮件服务器基于 POP3/SMTP 协议,通信双方需要明确指定,并且发送的邮件内容有固定的结构。而 RabbitMQ 服务器基于 AMQP 协议,这个协议是不需要明确指定发送方和接收方的,而且发送的消息也没有固定的结构,甚至可以直接存储二进制数据,并且和邮件服务器一样,也能存储离线消息,最关键的是 RabbitMQ 既能够以一对一的方式进行路由,还能够以一对多的方式进行广播。
下面这张图是大致展示了 RabbitMQ 消息通信的过程:

ps:看不懂没关系,后面会通过具体的例子进行讲解。
1、生产者和消费者
在 RabbitMQ 的通信过程中,有两个主要的角色:生产者和消费者。类比于邮件通信的发送方和接收方。
这里首先我们要明确 RabbtiMQ 服务器是不能够产生数据的,正如同其名字——消息中间件,是一个用来传递消息的中间商。生产者产生创建消息,然后发布到代理服务器(RabbitMQ),而消费者则从代理服务器获取消息(不是直接找生产者要消息),而且在实际应用中,生产者和消费者也是可以角色互相转换的,所以当我们应用程序连接到 RabbitMQ 服务器时,必须要明确我是生产者呢还是消费者。
2、消息
生产者创建消息,然后发布到 RabbitMQ 服务器中,那么什么是消息?
这里的消息分为两部分:有效内容和内容标签。
①、有效内容:可以是任何内容,一个数组,一个集合,甚至二进制数据都可以。RabbitMQ 不会在意你发什么数据,尽管发就行了。
②、内容标签:描述有效内容,是 RabbitMQ 用来决定谁将获得消息。前面说的邮件通信,必须明确指定发送方地址和收件方地址,而基于 AMQP 协议的 RabbitMQ 则是通过生产者发送消息附带的内容标签将消息发送个感兴趣的消费者。

后面我们会详细解析标签是什么,这里只需要知道生产者会创建消息并设置标签。注意最上面的大图,一般来说生产者创建消息会设置标签,但是传输到消费者那里就没有标签了,除非你在有效内容中说明谁是生产者,一般消费者是不知道谁产生的消息的。
3、信道
生产者产生了消息,然后发布到 RabbitMQ 服务器,发布之前肯定要先连接上服务器,也就是要在应用程序和rabbitmq 服务器之间建立一条 TCP 连接,一旦连接建立,应用程序就可以创建一条 AMQP 信道。
信道是建立在“真实的”TCP 连接内的虚拟连接,AMQP 命令都是通过信道发送出去的,每条信道都会被指派一个唯一的ID(AMQP库会帮你记住ID的),不论是发布消息、订阅队列或者接收消息,这些动作都是通过信道来完成的。

可能有人会问,为什么不直接通过 TCP 连接来发送AMQP命令呢?
这里原因是效率问题,因为对于操作系统来说,每次建立和销毁 TCP 会话是非常昂贵的开销,而实际系统中,比如电商双十一,每秒钟高峰期成千上万条连接,一般来说操作系统建立TCP连接是有数量限制的,那么这就会遇到瓶颈。
引入信道的概念,我们可以在一条 TCP 连接上创建 N多个信道,这样既能发送命令,也能够保证每条信道的私密性,我们可以将其想象为光纤电缆。

4、交换器和队列
截取上面的一部分图:

交换器和队列都是 RabbitMQ 服务器的一部分,我们知道生产者会将消息发送到 RabbitMQ 服务器,而进入该服务器后,首先进入交换机部分,然后由交换器根据消息附带的内容标签,将消息绑定到相应的队列。我们首先来看什么是队列:
①、容纳消息的场所,生产者发送到RabbitMQ服务器的消息会在队列中等待消费者消费。
②、队列是 RabbitMQ 服务器中最后的终点(除非消息进入了黑洞,黑洞的概念下面会介绍)。
③、队列可以实现负载均衡,我们可以增加一堆消费者,然后让 RabbitMQ 以循环的方式来均匀的分配消息。
搞清楚了队列是什么了,那么消息是如何到达队列的呢?没错,就是通过交换器。
消息进入RabbitMQ 服务器时,会首先将消息发送到交换器,然后交换器会根据特定的路由算法以及消息的内容标签将消息绑定到相应的队列。在 AMQP 协议中有四种交换器:direct、fanout、topic和 headers,每种交换器都实现了不同的路由算法,这也对应 RabbitMQ 工作的几种不同方式,这是重点,后面博客会进行详细介绍。
5、虚拟主机
最上面那张大图,我画了虚拟主机A以及虚拟主机B,说明在 RabbitMQ 服务器中存在着多个虚拟主机,那么虚拟主机到底是什么?
首先我们抛出这样一个问题,一个 RabbitMQ 肯定不是只服务一个应用程序,那么多个应用程序同时使用 RabbitMQ 服务器,如何保证彼此之间不会冲突?
答案就是使用虚拟主机,虚拟主机其实就是一个迷你版的RabbitMQ 服务器,它拥有自己的交换器和队列,更重要的是虚拟主机拥有自己的权限机制,一个服务器能够创建多个虚拟主机。那么我们在使用RabbitMQ服务器的时候,只需要将一个应用程序对应一个虚拟主机,这种各个实例间逻辑上的分离就能够保证不同的应用程序安全的传递消息。
默认的虚拟主机是“/”。
6、简单实例
介绍完RabbitMQ 消息通信过程中的一些基本概念后,下面我们通过一个代码实例来实际感受一下。
这是一个Maven工程,首先我们看 pom.xml 文件:导入 amqp-client 依赖即可
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.ys.rabbitmq</groupId>
<artifactId>RabbitMQTest</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging> <name>RabbitMQTest Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties> <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency> <dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>3.4.1</version>
</dependency> </dependencies> </project>
生产者:
package com.ys.simple; import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.ys.utils.ConnectionUtil; /**
* Create by hadoop
*/
public class Send {
private final static String QUEUE_NAME = "hello"; public static void main(String[] args) throws Exception{
//1、获取连接
Connection connection = ConnectionUtil.getConnection("192.168.146.251",5672,"/","guest","guest");
//2、声明通道
Channel channel = connection.createChannel();
//3、声明(创建)队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
//4、定义消息内容
String message = "hello rabbitmq ";
//5、发布消息
channel.basicPublish("",QUEUE_NAME,null,message.getBytes());
System.out.println("[x] Sent'"+message+"'");
//6、关闭通道和连接
channel.close();
connection.close();
}
}
消费者:
package com.ys.simple; import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.QueueingConsumer;
import com.ys.utils.ConnectionUtil; /**
* Create by hadoop
*/
public class Recv { private final static String QUEUE_NAME = "hello"; public static void main(String[] args) throws Exception{
//1、获取连接
Connection connection = ConnectionUtil.getConnection("192.168.146.251",5672,"/","guest","guest");
//2、声明通道
Channel channel = connection.createChannel();
//3、声明队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
//4、定义队列的消费者
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
//5、监听队列
channel.basicConsume(QUEUE_NAME,true,queueingConsumer);
//6、获取消息
while (true){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
}
} }
工具类:ConnectionUtil
package com.ys.utils; import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory; /**
* Create by hadoop
*/
public class ConnectionUtil { public static Connection getConnection(String host,int port,String vHost,String userName,String passWord) throws Exception{
//1、定义连接工厂
ConnectionFactory factory = new ConnectionFactory();
//2、设置服务器地址
factory.setHost(host);
//3、设置端口
factory.setPort(port);
//4、设置虚拟主机、用户名、密码
factory.setVirtualHost(vHost);
factory.setUsername(userName);
factory.setPassword(passWord);
//5、通过连接工厂获取连接
Connection connection = factory.newConnection();
return connection;
}
}
RabbitMQ详解(二)------消息通信的概念的更多相关文章
- Shiro 安全框架详解二(概念+权限案例实现)
Shiro 安全框架详解二 总结内容 一.登录认证 二.Shiro 授权 1. 概念 2. 授权流程图 三.基于 ini 的授权认证案例实现 1. 实现原理图 2. 实现代码 2.1 添加 maven ...
- Spring Boot(八):RabbitMQ详解
Spring Boot(八):RabbitMQ详解 RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发的作用. 消息中间件在互联网公司的使用中越来越多 ...
- RabbitMQ详解(一)------简介与安装(Docker)
RABBITMQ详解(一)------简介与安装(DOCKER) 刚刚进入实习,在学习过程中没有接触过MQ,RabbitMQ 这个消息中间件,正好公司最近的项目中有用到,学习了解一下. 首先什么是MQ ...
- HTTPS详解二:SSL / TLS 工作原理和详细握手过程
HTTPS 详解一:附带最精美详尽的 HTTPS 原理图 HTTPS详解二:SSL / TLS 工作原理和详细握手过程 在上篇文章HTTPS详解一中,我已经为大家介绍了 HTTPS 的详细原理和通信流 ...
- RabbitMQ详解(三)------RabbitMQ的五种模式
RabbitMQ详解(三)------RabbitMQ的五种模式 1.简单队列(模式) 上一篇文章末尾的实例给出的代码就是简单模式. 一个生产者对应一个消费者!!! pom.xml 必须导入Rab ...
- PopUpWindow使用详解(二)——进阶及答疑
相关文章:1.<PopUpWindow使用详解(一)——基本使用>2.<PopUpWindow使用详解(二)——进阶及答疑> 上篇为大家基本讲述了有关PopupWindow ...
- pika详解(二) BlockingConnection
pika详解(二) BlockingConnection 本文链接:https://blog.csdn.net/comprel/article/details/94592348 版权 Blocki ...
- spring-boot(五) RabbitMQ详解 定时任务
学习文章来自:springboot(八):RabbitMQ详解 springboot(九):定时任务 RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分 ...
- .Net使用RabbitMQ详解 转载http://www.cnblogs.com/knowledgesea/p/5296008.html
.Net使用RabbitMQ详解 序言 这里原来有一句话,触犯啦天条,被阉割!!!! 首先不去讨论我的日志组件怎么样.因为有些日志需要走网络,有的又不需要走网路,也是有性能与业务场景的多般变化在其 ...
- 爬虫入门之urllib库详解(二)
爬虫入门之urllib库详解(二) 1 urllib模块 urllib模块是一个运用于URL的包 urllib.request用于访问和读取URLS urllib.error包括了所有urllib.r ...
随机推荐
- 如何用ABP框架快速完成项目(9) - 用ABP一个人快速完成项目(5) - 不要执着于设计模式和DDD理论,避免原教旨主义
为什么要写这节文章呢? 首先主动看我这系列文章和参加活动课程的同学, 肯定是积极好学的. 所以很大概率是学过设计模式和DDD理论的. 很大概率不是走一点都不懂设计模式和DDD理论这个极端, 而是走 ...
- Nginx filebeat+logstash+Elasticsearch+kibana实现nginx日志图形化展示
filebeat+logstash+Elasticsearch+kibana实现nginx日志图形化展示 by:授客 QQ:1033553122 测试环境 Win7 64 CentOS-7- ...
- Native SBS for Android
Native SBS for Android是一款非常棒的软件,支持安卓在2D界面下左右分屏显示,并可以设置缩放比例及左右间距,横屏自动切换为左右分屏显示模式,竖屏则为正常显示.启动左右分屏模式后,将 ...
- 使用VSTS的Git进行版本控制(七)——管理仓库
使用VSTS的Git进行版本控制(七)--管理仓库 在团队项目中创建Git repo管理项目的源代码.每个Git repo都有自己的权限和分支,可以与项目中的其他工作隔离开来. 任务1:从web门户创 ...
- vi中的全局替换
一.基本语法 替换命令语法: :[addr]s/源字符串/目标字符串/[option] 全局替换: :%s/源字符串/目标字符串/g 参数说明: [addr]--表示检索范围,省略时表示当前行. &q ...
- ERP服务启动后无法连接数据库的解决方法
请安照步骤一步一步走,一个方法一个方法试. 方法一: 第一步,退出ERP 第二步,卸载sql服务,操作方法如下(win+R—输入cmd—输入sc delete mysql_sl 回车键) 第三步,重启 ...
- 非常全面的SQL Server巡检脚本来自sqlskills团队的Glenn Berry
非常全面的SQL Server巡检脚本来自sqlskills团队的Glenn Berry Glenn Berry 曾承诺对这个脚本持续更新 -- SQL Server 2012 Diagnostic ...
- DPA从DPA 10.0.352升级到DPA 11.0.373
1: 解压安装文件SolarWinds-DPA-11.0.373-64bit.tar.gz [root@lnxmonitor tmp]# tar -xzvf SolarWinds-DPA-11.0.3 ...
- [20190322]测试相同语句遇到导致cursor pin S的疑问.txt
[20190322]测试相同语句遇到导致cursor pin S的疑问.txt--//昨天测试遇到的情况,链接:http://blog.itpub.net/267265/viewspace-26388 ...
- SpringBoot整合模板引擎
一.SpringBoot整合freemarker: 1.引入freemarker模板依赖: <dependency> <groupId>org.springframework. ...