文章目录
一、中间件
1. 什么是中间件
什么是中间件
一个企业可能同时运行着多个不同的业务系统,这些系统可能基于不同的操作系统、不同的数据库、异构的网络环境。如何把这些信息系统结合成一个有机地协同工作的整体,真正实现企业跨平台、分布式应用。中间件便是解决之道,它用自己的复杂换取了企业应用的简单。
中间件(Middleware)是处于操作系统和应用程序之间的软件,也有人认为它应该属于操作系统中的一部分。人们在使用中间件时,往往是一组中间件集成在一起,构成一个平台(包括开发平台和运行平台),但在这组中间件中必须要有一个通信中间件,即中间件+平台+通信,这个定义也限定了只有用于分布式系统中才能称为中间件,同时还可以把它与支撑软件和使用软件区分开来
为什么需要使用消息中间件
具体地说,中间件屏蔽了底层操作系统的复杂性,使程序开发人员面对一个简单而统一的开发环境,减少程序设计的复杂性,将注意力集中在自己的业务上,不必再为程序在不同系统软件上的移植而重复工作,从而大大减少了技术上的负担,中间件带给应用系统的,不只是开发的简便、开发周期的缩短,也减少了系统的维护、运行和管理的工作量,还减少了计算机总体费用的投入。
中间件特点
必须遵循一定的规范,具有高可用、高可扩、持久性扥特征,
屏蔽底层操作系统复杂性、屏蔽技术架构局限性(不需要应用程序都要使用同一个语言)
中间件应具有如下的一些特点:
- 满足大量应用的需要
- 运行于多种硬件和 OS平台
- 支持分布计算,提供跨网络、硬件和 OS平台的透明性的应用或服务的交互
- 支持标准的协议
- 支持标准的接口
TCP/IP协议是中间的主要通信协议,但他比较底层并不能完全满足需求,我们还要基于TCP/IP构建自己的请求信息。
在项目中什么时候使用中间件技术
在项目的架构和重构中,使用任何技术和架构的改变我们都需要谨慎斟酌和思考,因为任何技术的融入和变化都可能人员,技术,和成本的增加,如果你仅仅还只是一个初创公司建议还是使用单体架构,最多加个缓存中间件即可,不要盲目追求新或者所谓的高性能,而追求的背后一定是业务的驱动和项目的驱动,因为一旦追求就意味着你的学习成本,公司的人员结构以及服务器成本,维护和运维的成本都会增加,所以需要谨慎选择和考虑。
但是作为一个开发人员,一定要有学习中间件技术的能力和思维。
2. 中间件技术及架构的概述
分布式消息中间件:
- ActiveMQ:比较老牌,Java语言开发,高性能,现在选型比较少了,略复杂
- RabbitMQ:比较流行,支持模式完善、Spring的支持很完善
- Kafka:性能最高,最接近的底层,不支持事务,支持持久化、分发机制,大数据领域应用多,开源
- RocketMQ:阿里开发,谨慎对待,目前在Apache托管,将来是否继续维护还不确定
为什么消息中间件还有自己的协议?
因为TCP/IP协议比较底层,无法完全满足我们的需求,所以在TCP/IP协议之上构建了自己的协议,底层还是TCP/IP
负载均衡中间:
- Nginx 负载均衡
- LVS负载均衡:对Nginx进行集群
- KeepAlive:保持心跳
- CDN:加速技术
缓存中间件:
MemCache:适合小规模缓存使用
Redis:适合大规模缓存使用
数据库中间件:
- MySQL可以持久化,但高可用能力不强,而且数据库自身的优化已经达到瓶颈之后,就需要中间件来解决
- MyCat:解决数据库高可用,
- ShardingJDBC:
学习中间件的方式和技巧
- 理解中间件在项目架构中的作用,以及各中间件的底层实现
- 可以使用一些类比的生活概念去理解中间件
- 使用一些流程图或者脑图的方式去梳理各个中间件在架构中的作用
- 尝试用 java技术去实现中间件的原理
- 静下来去思考中间件在项目中设计的和使用的原因
- 如果找到对应的代替总结方案
- 尝试编写博文总结类同中间件技术的对比和使用场景
- 学会查看中间件的源码以及开源项目和博文
单体架构
在企业开发当中,大部分的初期架构都采用的是单体架构的模式进行架构,而这种架构的典型的特点:就是把所有的业务和模块,源代码,静态资源文件等都放在一个工程中,如果其中的一个模块升级或者迭代发生一个很小的变动都会重新编译和重新部署项目。这种架构存在的问题是:
- 耦合度太高
- 不易维护
- 服务器的成本高
- 以及升级架构的复杂度也会增大
这样就有后续的分布式架构系统。如下
分布式架构
何谓分布式系统:
通俗一点:就是一个请求由服务器端的多个服务(服务或者系统)协同处理完成
和单体架构不同的是,单体架构是一个请求发起 jvm调度线程(确切的是 tomcat线程池)分配线程 Thread来处理请求直到释放,而分布式系统是:一个请求时由多个系统共同来协同完成,jvm和环境都可能是独立。如果生活中的比喻的话,单体架构就像建设一个小房子很快就能够搞定,如果你要建设一个鸟巢或者大型的建筑,你就必须是各个环节的协同和分布,这样目的也是项目发展到后期的时候要去部署和思考的问题。我们也不难看出来:分布式架构系统存在的特点和问题如下:
存在问题:
- 学习成本高,技术栈过多
- 运维成本和服务器成本增高
- 人员的成本也会增高
- 项目的负载度也会上升
- 面临的错误和容错性也会成倍增加
- 占用的服务器端口和通讯的选择的成本高
- 安全性的考虑和因素逼迫可能选择 RMI/MQ相关的服务器端通讯
好处:
- 服务系统的独立,占用的服务器资源减少和占用的硬件成本减少,确切的说是:可以合理的分配服务资源,不造成服务器资源的浪费
- 系统的独立维护和部署,耦合度降低,可插拔性
- 系统的架构和技术栈的选择可以变的灵活(而不是单纯地选择 java)
- 弹性的部署,不会造成平台因部署造成的瘫痪和停服的状态
3. 基于消息中间件的分布式系统的架构
从上图中可以看出来,消息中间件的是
- 利用可靠的消息传递机制进行系统和系统直接的通讯
- 通过提供消息传递和消息的派对机制,它可以在分布式系统环境下扩展进程间的通讯(不受语言限制)
消息中间件应用的场景
- 跨系统数据传递
- 高并发的流量削峰
- 数据的并发和异步处理
- 大数据分析与传递
- 分布式事务比如你有一个数据要进行迁移或者请求并发过多的时候,
比如你有10 W的并发请求下订单,我们可以在这些订单入库之前,我们可以把订单请求堆积到消息队列中,让它稳健可靠的入库和执行
串行的总时间为所有系统运行的时间之和;
并行的运行的总时间取决于最慢的那个系统的运行时间,比串行的求和要快很多;
常见的消息中间件
ActiveMQ、RabbitMQ、Kafka、RocketMQ等
消息中间件的本质及设计
它是一种接受数据、接受请求、存储数据、发送数据等功能的技术服务
MQ消息队列:负责数据的接受,存储和传递,所以性能要高于普通服务和技术
消息中间件的核心组成部分
- 消息的协议
- 消息的持久化机制
- 消息的分发策略
- 消息的高可用,高可靠
- 消息的容错机制
小结
其实不论选择单体架构还是分布式架构都是项目开发的一个阶段,在什么阶段选择合适的架构方式,而不能盲目追求,最后造成的后果和问题都需要自己买单。但作为一个开发人员学习和探讨新的技术使我们每个程序开发者都应该去保持和思考的问题。当我们没办法去改变社会和世界的时候,我们为了生活和生存那就必须要迎合企业和市场的需求,发挥你的价值和所学的才能,创造价值和实现自我
4. 消息队列协议
什么是协议
所谓协议是指:
- 计算机底层操作系统和应用程序通讯时共同遵守的一组约定,只有遵循共同的约定和规范,系统和底层操作系统之间才能相互交流
- 和一般的网络应用程序的不同它主要负责数据的接受和传递,所以性能比较的高
- 协议对数据格式和计算机之间交换数据都必须严格遵守规范
网络协议的三要素
- 语法:语法是用户数据与控制信息的结构与格式,以及数据出现的顺序
- 语义:语义是解释控制信息每个部分的意义,它规定了需要发出何种控制信息,以及完成的动作与做出什么样的响应
- 时序:时序是对事件发生顺序的详细说明
比如我 MQ发送一个信息,是以什么数据格式发送到队列中,然后每个部分的含义是什么,发送完毕以后的执行的动作,以及消费者消费消息的动作,消费完毕的相应结构和反馈是什么,然后按照对应的执行顺序进行处理。如果你还是不理解:大家每天都在接触的 http请求协议:
- 语法:http规定了请求报文和响应报文的格式
- 语义:客户端主动发起请求称之为请求(这是一种定义,同时你发起的是 post/get请求)
- 时序:一个请求对应一个响应(一定先有请求再有响应,这个是时序)
而消息中间件采用的并不是 http协议,常见的消息中间件协议基于TCP/IP协议之上封装成:OpenWire、AMQP、MQTT、Kafka,OpenMessage协议
面试题:为什么消息中间件不直接使用 http协议
- 因为 http请求报文头和响应报文头是比较复杂的,包含了Cookie,数据的加密解密,窗台吗,响应码等附加的功能,但是对于一个消息而言,我们并不需要这么复杂,也没有这个必要性,它其实就是负责数据传递,存储,分发就行,一定要追求的是高性能。尽量简洁,快速
- 大部分情况下 http大部分都是短链接,在实际的交互过程中,一个请求到响应都很有可能会中断,中断以后就不会执行持久化,就会造成请求的丢失。这样就不利于消息中间件的业务场景,因为消息中间件可能是一个长期的获取信息的过程,出现问题和故障要对数据或消息执行持久化等,目的是为了保证消息和数据的高可靠和稳健的运行
AMQP协议
AMQP:(全称:Advanced Message Queuing Protocol)是高级消息队列协议。由摩根大通集团联合其他公司共同设计。是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。Erlang中的实现由 RabbitMQ等
特性:
- 分布式事务支持
- 消息的持久化支持
- 高性能和高可靠的消息处理优势
MQTT协议
MQTT协议(Message Queueing Telemetry Transport)消息队列是 IBM开放的及时通讯协议,物联网系统架构中的重要组成部分
特点:
- 轻量
- 结构简单
- 传输快,不支持事务
- 没有持久化设计
应用场景:
- 适用于计算能力有限
- 低带宽
- 网络不稳定的场景
OpenMessage协议
是近几年由阿里、雅虎和滴滴出行、Stremalio等公司共同参与创立的分布式信息中间件、流处理等领域的应用开发标准
特点:
- 结构简单
- 解析速度快
- 支持事务和持久化设计
Kafka协议
Kafka协议是基于 TCP/IP的二进制协议。消息内部是 通过长度来分割,由一些基本数据类型组成
特点:
- 结构简单
- 解析速度快,性能最高
- 无事务支持
- 有持久化设计
小结
协议:
其实就是 TCP/IP 协议基础之上构建的一种约定俗称的规范和机制、它的主要目的可以让客户端(应用程序 java,go)进行沟通和通讯。并且这种写一下规范必须具有持久性,高可用,高可靠的性能
5. 消息队列持久化
持久化
简单来说就是将数据存入磁盘,而不是存在内存中随服务器重启断开而消失,使数据能够永久保存
常见的持久化方式
6. 消息的分发策略
消息的分发策略
MQ消息 队列有如下几个角色
- 生产者
- 存储消息
- 消费者
那么生产者生成消息以后,MQ进行存储,消费者是如何获取消息的呢?
一般获取数据的方式无外乎推(push)或者拉(pull)两种方式,典型的 git就有推拉机制,我们发送的 http请求就是一种典型的拉取数据库数据返回的过程。
而消息队列 MQ是一种推送的过程,而这些推机制会使用到很多的业务场景也有很多对应推机制策略
场景分析一
比如我在 APP上下了一个订单,我们的系统和服务很多,我们如何得知这个消息被哪个系统或者哪些服务器或者系统进行消费,那这个时候就需要一个分发的策略。这就需要消费策略。或者称之为消费的方法论
场景分析二
在发送消息的过程中可能会出现异常,或者网络的抖动,故障等等因为造成消息的无法消费,比如用户在下订单,消费 MQ接受,订单系统出现故障,导致用户支付失败,那么这个时候就需要消息中间件就必须支持消息重试机制策略。也就是支持:出现问题和故障的情况下,消息不丢失还可以进行重发
消息分发策略的机制和对比
轮询分发侧重公平性,不会因为消费处理的快与慢而对数据分发有倾斜,对应自动应答,自动ACK
公平分发侧重能者多劳,会根据实际的使用情况有一定的倾斜,对应手动应答,手动ACK
重发为了保证消息的可靠性
消息队列很少使用消息拉取操作
综合来看,Rabbit的功能最完善,最稳定;kafka性能最高,
7. 消息队列高可用和高可靠
什么是高可用机制
所谓高可用:是指产品在规定的条件和规定的时刻或时间内处于可执行规定功能状态的能力
当业务量增加时,请求也过大,一台消息中间件服务器的会触及硬件(CPU,内存,磁盘)的极限,一台消息服务器你已经无法满足业务的需求,所以消息中间件必须支持集群部署,来达到高可用的目的
说白了,就是尽可能做到,有服务器出故障、宕机之后系统也能正常使用
集群模式1 - Master-slave主从共享数据的部署方式
集群模式2 - Master-slave主从同步部署方式
解释:这种模式写入消息同样在 Master主节点上,但是主节点会同步数据到 slave节点形成副本,和 zookeeper或者 redis主从机制很雷同。这样可以达到负载均衡的效果,如果消费者有多个这样就可以去不同的节点进行消费,以为消息的拷贝和同步会占用很大的带宽和网络资源。在后续的 rabbitmq中会有使用
所以要尽量部署在同一个机房内,保证带宽不受影响,
集群模式3 - 多主集群同步部署模式
解释:和上面的区别不是特别的大,但是它的写入可以往任意节点去写入
集群模式4 - 多主集群转发部署模式
解释:如果你插入的数据是 broker-1中国,元数据信息会存储数据的相关描述和记录存放的位置(队列)。它会对描述信息也就是元数据信息进行同步,如果消费者在 broker-2中进行消费,发现自己节点没有对应的信息,可以从对应的元数据信息中去查询,然后返回对应的消息信息,场景:比如买火车票或者黄牛买演唱会门票,比如第一个黄牛有顾客说要买的演唱会门票,但是没有但是他回去联系其他的黄牛询问,如果有就返回
集群模式5 Master-slave与 Broker-cluster组合的方案
解释:实现多主多从的热备机制来完成消息的高可用以及数据的热备机制,在生产规模达到一定的阶段的时候,这种使用的频率比较高
什么是高可靠机制
所谓高可靠是指:系统可以无故障低持续运行,比如一个系统突然崩溃,报错,异常等等并不影响线上业务的正常运行,出错的几率极低,就称之为:高可靠
在高并发的业务场景中,如果不能保证系统的高可靠,那造成的隐患和损失是非常严重的
如何保证中间件消息的可靠性呢,可以从两个方面考虑:
- 消息的传输:通过协议来保证系统间数据解析的正确性
- 消息的存储区可靠:通过持久化来保证消息的可靠性
二、入门及安装 RabbitMQ
1. RabbitMQ入门及安装
概述
简单概述:
RabbitMQ是一个开源的遵循 AMQP协议实现的基于 Erlang语言编写,支持多种客户端(语言),用于在分布式系统中存储消息,转发消息,具有高可用,高可扩性,易用性等特征
下载RabbitMQ
- 下载地址:https://www.rabbitmq.com/download.html
- 环境准备:CentOS7.x + /Erlang
我使用的虚拟机是Linux centos 7,因此找到对应的版本下载,这里下载的是rmp安装包,
RabbitMQ是采用 Erlang语言开发的,erlang语言是基于开发交换机的语言,性能高
所以系统环境必须提供 Erlang环境,第一步就是安装 Erlang
安装Erlang
查看系统版本号,rabbitmq 对 erlang 有版本要求,不能使用太旧的erlang版本
https://www.rabbitmq.com/which-erlang.html
比如,rabbitmq 的最新版为 3.8.14,他要求 erlang 的最小版本为 22.3
这里我们将 rabbitmq 和 erlang 安装包提前准备好
安装包:
创建一个目录
mkdir -p /usr/rabbitmq
将 rabbitmq 和 erlang 包上传到这个目录中
解压 erlang 语言包
rpm -Uvh erlang-solutions-2.0-1.noarch.rpm
解压完毕,开始安装 erlang
yum install -y erlang
安装需要等待一点时间,安装完毕后,检测erlang版本,出现版本号表示安装成
erl -v
安装socat
rabbitmq 在安装过程中需要依赖这个插件,需要先安装
yum install -y socat
安装rabbitmq
解压 rabbitmq 安装包,注意实际的包名要以我们自己下载的包名
rpm -Uvh rabbitmq-server-3.8.13-1.el8.noarch.rpm
解压完毕,开始安装
yum install rabbitmq-server -y
安装完毕,启动服务
# 启动服务
systemctl start rabbitmq-server
# 查看服务状态,running表示启动成功
systemctl status rabbitmq-server.service
# 开机自启动
systemctl enable rabbitmq-server
# 停止服务
systemctl stop rabbitmq-server
2. RabbitMQWeb管理界面及授权操作
RabbitMQ管理界面
默认情况下,是没有安装web端的客户端插件,需要安装才可以生效
执行命令,开始安装rabbitmq管理界面插件
rabbitmq-plugins enable rabbitmq_management
安装完毕以后,重启服务
systemctl restart rabbitmq-server
访问浏览器,访问地址:服务器 IP+端口号(默认15672)
注意:
- 在对应服务器(阿里云,腾讯云等)的安全组中开放
15672
端口(rabbitmq默认端口号),5672端口后续程序需要使用也要开放 - rabbitmq有一个默认账号和密码都是:
guest
默认情况只能在 localhost本计下访问,所以需要添加一个远程登录的用户
授权账号和密码
新增用户,账号 admin,密码 admin
rabbitmqctl add_user admin admin
设置用户分配操作权限
rabbitmqctl set_user_tags admin administrator
用户操作权限分四种级别:
- administrator:可以登录控制台、查看所有信息、可以对 rabbitmq进行管理
- monitoring:监控者 登录控制台,查看所有信息
- policymaker:策略制定者 登录控制台,指定策略
- managment 普通管理员 登录控制台
为用户添加资源权限(授予访问虚拟机根节点的所有资源,如果已经选择了admin,那么这个命令可以不执行)
rabbitmqctl set_permissions -p / admin ".*"".*"".*"
网页登录成功
其他账户操作命令
# 添加账号、密码
rabbitmqctl add_user
# 设置账号为管理员
rabbitmqctl set_user_tags 账号 administrator
# 修改账号密码
rabbitmqctl change_password Username Newpassword
# 查看用户清单
rabbitmqctl list_users
# 添加账号查看资源的权限
rabbitmqctl set_permissions -p / 用户名 ".*"".*"".*"
3. RabbitMQ之Docker安装
Dokcer 安装 RabbitMQ
首先要在服务器中准备一个 Docker 的环境
虚拟化容器技术 - Docker的安装
# yum 包更新到最新
yum update
# 安装docker依赖的组件,yum-utils提供yum-config-manager功能,另外两个是devicemapper驱动依赖
yum install -y yum-utils device-mapper-persistent-data lvm2
# 设置yum源为阿里云
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装docker
yum install docker-ce -y
# 安装完毕后,检查docker版本
docker -v
# 给docker配置阿里云镜像加速器(可以不安装,看个人情况)
sudo mkdir -p /erc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry mirrors": ["https://0wrdwnn6.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
docker的相关命令
# 启动docker
systemctl start docker
# 停止docker
systemctl stop docker
# 重启docker
systemctl restart docker
# 查看docker状态
systemctl status docker
# 查看当前有哪些镜像
docker images
# 开机自启动
systemctl enable docker
systemctl unenable docker
# 查看docker概要信息
docker info
# 查看docker帮助文档
docker --help
安装 rabbitmq 方法一
# 获取rabbit镜像
docker pull rabbitmq:management
# 创建并运行容器
docker run -id --name=myrabbit -p 15672:15672 rabbitmq:management
# 参数含义
--hostname:指定容器主机名称
--name:指定容器名称
-p:将mq端口号映射到本地
安装完毕之后,还要再单独设置指定账户、密码
我们可以从官网查找到命令,指定在安装的过程中就可以根据提示完成账户、密码的设置
安装 rabbitmq 方法二
访问:https://registry.hub.docker.com/_/rabbitmq/
找到以下文档位置
执行docker安装rabbitmq的命令,图中命令与方法一的命令整合
docker run -di --name myrabbit -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -p 15672:15672 -p 5672:5672 -p 25672:25672 -p 61613:61613 -p 1883:1883 rabbitmq:management
显示启动错误是因为,安装成功后会尝试启动,上面我们手动安装rabbit已经占用端口,所以需要先将rabbitmq关闭,再用docker启动
查看docker容器状态
docker ps -a
镜像当前处于创建状态下,还没有启动
根据容器ID启动rabbitmq
docker start 13493aa7dbb8
启动成功
再次访问浏览器,这次访问的是 Docker 启动的 RabbitMQ
小结
Docker安装RabbitMQ明显比手动安装更加简洁,省去了 erlang、socat、管理界面插件等安装过程,甚至安装时就已经设置好了账户、密码,直接一步到位
注意端口的使用,一定要提前开放好
4. RabbitMQ的角色分类
RabbitMQ的角色分类
none:
- 不能访问mamanement plugin
management:查看自己相关节点信息
- 列出自己可以通过AMQP登入的虚拟机
- 查看自己的虚拟机节点 virtual hosts的queues,exchanges和bingdings信息,查看和关闭自己的channels和connections信息
- 查看有关自己的虚拟机节点 virtual hosts统计信息,包括其他用户在这个节点 virtual hosts中的活动信息
Policymaker:
- 包含management所有权限
- 查看和创建和删除自己的virtual hosts所属的policies和parameters信息
Monitoring:相当于普通管理员
- 包含management所有权限
- 罗列出所有的virtual hosts,包括不能登录的virtual hosts
- 查看其他用户的connections和channels信息
- 查看节点级别的数据如clustering何memory使用情况
- 查看所有的virtual hosts的全局统计信息
Administrator:超级管理员,(学习经常使用)
- 最高权限
- 可以创建和删除 virtual hosts
- 可以查看,创建、删除users
- 查看、创建permissions
- 关闭所有用户的connections
通过管理界面授权
三、入门案例
参考官网快速启动:https://www.rabbitmq.com/getstarted.html
1.2.3.4.5重点掌握
- jdk1.8
- 构建一个 maven工程
- 导入 rabbitmq 的 maven依赖
- 启动 rabbitmq-server服务
- 定义生产者
- 定义消费者
- 观察消息的在 rabbitmq-server 服务中的进程
1. RabbitMQ入门案例 - Simple 简单模式
项目准备
构建一个maven工程,添加rabbitmq依赖
先使用原生 rabbitmq 依赖,后面再整合 Spring
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.10.0</version>
</dependency>
演示代码
在上图的模型中,有以下概念:
- 生产者:也就是要发送消息的程序
- 消费者:消息的接受者,会一直等待消息到来。
- 消息队列:图中红色部分。类似一个邮箱,可以缓存消息;生产者向其中投递消息,消费者从其中取出消息。
生产者
// 简单模式
public class Producer {
public static void main(String[] args) {
// 1.创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("10.15.0.9");
connectionFactory.setPort(5672);
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
connectionFactory.setVirtualHost("/");
Connection connection = null;
Channel channel = null;
try {
// 2.创建链接
connection = connectionFactory.newConnection("生产者");
// 3.获取连接通道
channel = connection.createChannel();
// 4.通过创建交换机,声明队列,绑定关系,路由key,发送消息和接受消息
/*
参数1:队列名称
参数2:是否持久化,非持久化消息会存盘吗?会存盘,但是会随着重启服务器而丢失
参数3:是否独占队列
参数4:是否自动删除,随着最后一个消费者消息完毕消息以后是否把队列自动删除
参数5:携带附属属性
*/
String queueName = "queue1";
channel.queueDeclare(queueName,false,false,false,null);
// 5.发送消息给队列queue,都是由channel来处理
/*
参数1:交换机
参数2:队列、路由key
参数3:消息的状态控制
参数4:消息主题
*/
//面试题:可以存在没有交换机的队列吗?不可能,虽然没有指定交换机但是一定会存在一个默认的交换机
String message = "Hello";
channel.basicPublish("", queueName, null,message.getBytes());
System.out.println("消息发送成功");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (channel != null && channel.isOpen()) {
try {
// 6.关闭通道,注意关闭顺序
channel.close();
// 7.关闭连接
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
启动成功后,查看管理面板,可以看到我们创建的队列,有一条消息没有被消费
随着最后一条消息被消费,非持久化的消息会被删除,持久化消息会被保存
消费者
public class Consumer {
public static void main(String[] args) {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("10.15.0.9");
connectionFactory.setPort(5672);
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
connectionFactory.setVirtualHost("/");
Connection connection = null;
Channel channel = null;
try {
connection = connectionFactory.newConnection("生产者");
channel = connection.createChannel();
// 确保和消费者的队列名一致才可以接收消息
String queueName = "queue1";
channel.queueDeclare(queueName,false,false,false,null);
// 接收消息,必须重写两个方法,消息的处理和异常情况的处理
channel.basicConsume("queue1", true