架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例

1.初识RabbitMQ核心概念

(1)初始RabbitMQ

RabbitMQ是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用之间共享数据,RabbitMQ是使用Erlang语言来编写的,并且RabbitMQ是基于AMQP协议的。

即时性要求比较高的,往往采用RPC远程调用和HTTP/HTTPS来调用,比如用户下订单后,就要马上响应是否下单成功。那如果即时性要求不高的话,可以采用MQ来解决,比如你下完单后,进入物流环节,物流环节往往要等待很长时间,不可能商品马上就给你送过来,这时下单系统与物流系统之间就可以通过MQ来解耦。当请求过程不要求即时性,那我们就可以整个过程解耦,把整个过程的顺序性存放在MQ中,让整个过程慢慢去处理。

(2)什么是AMQP协议?

AMQP全称高级消息队列协议(Advanced Message Queuing Protocol)
RabbitMQ是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用之间共享数据,RabbitMQ是使用Erlang语言来编写的,并且RabbitMQ是基于AMQP协议的。

(3)AMPQ协议模型
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第1张图片

  • Server: 又称Broker, 接受客户端的连接,实现AMQP实体服务;
  • Connection: 连接,应用程序与Broker的网络连接;
  • Channel:网络信道,几乎所有的操作都在Channel中进行,Channel是进行消息读写的通道。客户端可建立多个Channel, 每个Channel代表一个会话务;
  • Message:消息,服务器和应用程序之间传送的数据,由Properties和Body组成。Properties可以对消息进行修饰,比如消息的优先级、延迟等高级特性;
    Body则就是消息体内容;
  • Virtual host:虚拟地址,用于进行逻辑隔离,最上层的消息路由。一个Virtual Host里面可以有若干个Exchange和Queue,同一个VirtualHost里面不能有相同名称的Exchange或Queue;
  • Exchange: 交换机,接收消息,根据路由键转发消息到绑定的队列; Binding: Exchange和Queue之间的虚拟连接, binding中可以包含routing key;
  • Routing key: 一个路由规则,虚拟机可用它来确定如何路由一个特定消息; Queue: 也称Message Queue,消息队列,保存消息并将它们转发给消费者;

(4)RabbitMQ整体架构是什么样子

架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第2张图片

Exchange与Queue理论上是多对多关系,在实际开发中建议是一对多关系
一个Consume可以消费多个Queue,在实际开发中建议是一对一消费

(5)RabbitMQ消息是如何流转的?

架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第3张图片

2.RabbitMQ环境搭建与控制台详解

(1)RabbitMQ的安装

RabbitMQ官网地址:http://www.rabbitmq.com
准备3台服务器,192.168.11.71、192.168.11.72、192.168.11.73

①yum下来一些基础的软件包,3台服务器都这么做

yum install build-essential openssl openssl-devel unixODBC unixODBC-devel make gcc gcc-c++ kernel-devel m4 ncurses-devel tk tc xz

②修改/etc/hosts和/etc/hostname文件,并测试能否ping通,3台服务器都这么做

vim /etc/hosts 

修改内容如下
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第4张图片

vim /etc/hostname

修改内容如下
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第5张图片
测试是否互通
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第6张图片

③下载RabbitMQ所需软件包

wget www.rabbitmq.com/releases/erlang/erlang-18.3-1.el7.centos.x86_64.rpm
wget http://repo.iotti.biz/CentOS/7/x86_64/socat-1.7.3.2-1.1.el7.lux.x86_64.rpm
wget www.rabbitmq.com/releases/rabbitmq-server/v3.6.5/rabbitmq-server-3.6.5-1.noarch.rpm

下载后结果
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第7张图片

④按顺序安装服务命令

rpm -ivh erlang-18.3-1.el7.centos.x86_64.rpm 
rpm -ivh socat-1.7.3.2-1.1.el7.x86_64.rpm
rpm -ivh rabbitmq-server-3.6.5-1.noarch.rpm

⑤修改用户登录与连接心跳检测,注意修改

vim /usr/lib/rabbitmq/lib/rabbitmq_server-3.6.5/ebin/rabbit.app

修改点1:loopback_users 中的 <<“guest”>>,只保留guest (用于用户登录)
修改点2:heartbeat 为10(用于心跳连接)

⑥安装管理插件

首先启动服务(后面 | 包含了停止、查看状态以及重启的命令)

/etc/init.d/rabbitmq-server start | stop | status | restart

可查看管理端口有没有启动:

lsof -i:15672 或者 netstat -tnlp | grep 15672

查看服务有没有启动: lsof -i:5672 (5672是Rabbit的默认端口)

rabbitmq-plugins enable rabbitmq_management

例如:
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第8张图片

⑦浏览器中访问RabbitMQ服务

架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第9张图片

(2)RabbitMQ的界面

跟着每一步骤去了解RabbitMQ的管理界面
1.RabbitMQ管理服务登录界面
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第10张图片

2.RabbitMQ管理界面组成部分
在这里插入图片描述

  • connections:无论生产者还是消费者,都需要与 RabbitMQ 建立连接后才可以完成消息的生产和消费,在这里可以查看连接情况
  • channels:通道,建立连接后,会形成通道,消息的投递获取依赖的通道
  • Exchanges:交换机,用来实现消息的路由
  • Queues:队列,就是消息队列,消息存放在队列中,等待消费,消费后会被移除队列

3.Totals
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第11张图片

反应连接数、通道数、交换机、队列、消费数总体个数

4.Node节点使用情况

架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第12张图片

5.Paths
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第13张图片

核心配置文件优先读取/etc/rabbitmq/rabbitmq.config,如果没有读取
/usr/lib/rabbitmq/lib/rabbitmq_server-3.6.5/ebin/rabbit.app

6.Ports and contexts 端口情况

架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第14张图片

7.Import / export definitions 导入导出
用于数据迁移、MQ版本升级
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第15张图片

(3)RabbitMQ的使用

1.尝试发一条消息
①新建exchang
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第16张图片

Type:direct:直连 topic:主题 fanout:广播
Durability:durable 持久化(服务重启不会丢失) transient 不持久化

查看新建结果
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第17张图片
②exchang要跟queue队列绑定,创建队列
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第18张图片

查看新建结果
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第19张图片

③建立exchang与queue之间的关系
点击exchang-test
在这里插入图片描述

填入队列名称和路由规则
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第20张图片

查看绑定结果
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第21张图片

④在exchang下发布一条消息
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第22张图片

发送成功,显示:
在这里插入图片描述

从queue-test中查看消息
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第23张图片

点击queue-test查看详情
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第24张图片

查看消息内容,点击Get Message(s)
架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第25张图片

3.RabbitMQ急速入门HelloWorld

(1)编写RabbitMQ几个要素

  • ConnectionFactory:获取连接工厂
  • Connection: 一个连接
  • Channel:数据通信信道,可发送和接收消息
  • Queue: 具体的消息存储队列
  • Producer & Consumer:生产和消费者

(2)引入Springboot和RabbitMQ依赖


<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.0modelVersion>

	<groupId>com.bfxygroupId>
	<artifactId>rabbitmq-apiartifactId>
	<version>0.0.1-SNAPSHOTversion>
	<packaging>jarpackaging>

	<name>rabbitmq-apiname>
	<description>rabbitmq-apidescription>

	<parent>
		<groupId>org.springframework.bootgroupId>
		<artifactId>spring-boot-starter-parentartifactId>
		<version>2.1.5.RELEASEversion>
		<relativePath/> 
	parent>

	<properties>
		<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
		<java.version>1.8java.version>
	properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starterartifactId>
		dependency>
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-testartifactId>
			<scope>testscope>
		dependency>
		<dependency>
			<groupId>com.rabbitmqgroupId>
			<artifactId>amqp-clientartifactId>
			<version>3.6.5version>
		dependency>	
	dependencies>
	
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.bootgroupId>
				<artifactId>spring-boot-maven-pluginartifactId>
			plugin>
			<plugin>
				<groupId>org.apache.maven.pluginsgroupId>
				<artifactId>maven-compiler-pluginartifactId>
				<configuration>
					<source>1.8source>
					<target>1.8target>
				configuration>
			plugin>			
		plugins>
	build>
project>

(3)在main函数中写一个生产者Sender

public class Sender {
	public static void main(String[] args) throws Exception {
		//	创建ConnectionFactory
		ConnectionFactory connectionFactory = new ConnectionFactory();
		connectionFactory.setHost("192.168.11.71");
		connectionFactory.setPort(5672);
		connectionFactory.setVirtualHost("/");
		//	创建Connection
		Connection connection = connectionFactory.newConnection();
		//	创建Channel
		Channel channel = connection.createChannel();  
	
		String queueName = "test001";  
             //	参数: queue名字,是否持久化,独占的queue(仅供此连接),不使用时是否自动删除, 其他参数
		channel.queueDeclare(queueName, false, false, false, null);
		
		Map<String, Object> headers = new HashMap<String, Object>();

		AMQP.BasicProperties props = new AMQP.BasicProperties.Builder()
		.deliveryMode(2)
		.contentEncoding("UTF-8")
		.headers(headers).build();
		
		for(int i = 0; i < 5;i++) {
			String msg = "Hello World RabbitMQ " + i;
// 发布消息,第一个参数:exchange为""会选择默认的exchange
			channel.basicPublish("", queueName , props , msg.getBytes()); 			
		}

// 关闭资源:略
	}
}

(4)在main函数中写一个消费者Receiver

public class Receiver {
	public static void main(String[] args) throws Exception {
        ConnectionFactory connectionFactory = new ConnectionFactory() ;  
        connectionFactory.setHost("192.168.11.71");
        connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");
	 // 服务宕机是否自动切换
        connectionFactory.setAutomaticRecoveryEnabled(true);
        connectionFactory.setNetworkRecoveryInterval(3000);

        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();  
        
        String queueName = "test001";  
        //	durable 是否持久化消息
        channel.queueDeclare(queueName, false, false, false, null);  
        QueueingConsumer consumer = new QueueingConsumer(channel);
        //	参数:队列名称、是否自动ACK、Consumer
        channel.basicConsume(queueName, true, consumer);  
        //	循环获取消息  
        while(true){  
            //	获取消息,如果没有消息,这一步将会一直阻塞  
            Delivery delivery = consumer.nextDelivery();  
            String msg = new String(delivery.getBody());    
            System.out.println("收到消息:" + msg);  
        } 
	}
}

(5)生产与消费流程

架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例_第26张图片

Step1:生产者producer发送消息到broker;
Step2:broker接收消息成功,回应生产者producer;
Step3:消费者consumer监听broker中的消息,光标指向1,并消费;
Step4:消费之后,回应broker处理完成,这时候光标指向2,继续获取消息来消费。自动ACK指自动完成消息处理,也就是自动移动光标,一般在现实开发中都是手动ACK回应的。

你可能感兴趣的:(架构师-分布式消息队列(二)-RabbitMQ核心概念、环境搭建、急速入门案例)