0、常见的面试题
消息队列的使用并不是难点,难的是我们怎么合理高效地使用,这里先对常见的面试题进行整理,再讨论使用问题。
1.为什么使用消息队列?(消息队列的应用场景?)
首先消息队列就是一种先进先出的数据结构,常用的应用场景就是:解耦、异步和削锋。
解耦:因为系统的耦合性越高则容错性就会越低,在编程中我们都希望“高内聚、低耦合”,
以某个电商系统为例子,用户创建订单后如果耦合调用(利用RPC远程调用)支付系统、库存系统和物流系统,任何一个子系统出现故障或者进行升级时,都会导致支付系统出现问题,影响用户体验。
这时可以用消息队列进行解耦,这时比如物流系统出现问题的时候,物流系统要处理的数据会缓存在消息中间件中,当物流系统恢复后补充处理MQ中的数据即可。用户感知不到物流系统出现的问题。
异步:比如A系统接收到一个请求后,需要对A B C D四个库进行写操作,比对对A B C D进行写库消耗的时间分别为:200ms 300ms 100ms 400ms,那么总的延迟就是1s,过分用户不友好,我们一般希望每个请求在200ms内完成。
如果使用MQ则用户向A系统中进行写操作,然后再让A系统向三个MQ中进行写操作,这种异步的方式可以提升效率。(但是要注意业务场景,比如说用户的请求结果依赖于B C D那么就不能采用这种方式)
流量削锋:一般情况下,为了保证系统的稳定性,当系统负载超过阈值的时候,就会阻止用户请求非常影响用户体验,那么我们就可采用消息队列的方式将请求放进队列,再建立一个系统每隔一秒钟从队列中拉出部分数据,以实现流量削锋。
2、各种消息队列产品的比较?
ActiveMQ:早些年使用比较广泛,没有经过大规模的吞吐量场景验证,社区也不是很活跃,现在用的比较少。
RabbitMQ:erLang语言开发,阻止了大量Java工程师深入研究,如果不考虑二次开发,追求高性能和稳定性则推荐使用。
Rocket:阿里的产品,java语言开发,性能和稳定性斗不错,如果考虑二次开发则推荐使用
kafka:常用于大数据领域的实时计算和日志采集等。
3、消息队列的优缺点?
优点:解耦、异步和削锋;
缺点:系统可用性降低、系统的复杂性变高和一致性问题;
系统可用性降低:系统引入的外部依赖越多,系统的稳定性越差,一旦MQ宕机就会对业务造成影响。可以采用集群的方式保证MQ的高可用。
系统的复杂度提高:MQ的引入大大增加了系统的复杂度,以前是远程同步调用,现在要通过MQ进行异步调用。
系统的一致性问题:比如A系统处理完后,通过MQ给B C D三个系统发送消息,但是B C处理成功了,而D处理失败了,这就出现了一致性问。可以通过分布式事务来解决。
4、如何保证消息队列的高可用?
RabbitMQ的解决方案:普通集群&镜像集群;
普通集群
普通集群就是在多台机器上启动多个实例。我们创建的queue只会存在其中的一个实例上,但是每个实例都同步 queue 的元数据(元数据可以认为是 queue 的一些配置信息,通过元数据,可以找到 queue 所在实例)。消费者在进行消费的时候,如果连接的实例上恰好不是队列所在的实例,就会根据队列的元数据去队列所在实例上拉取数据。
由此可知,集群模式并没做到分布式,如果队列所在的实例宕机了,会导致接下来其他实例就无法从那个实例拉取消息,同时影响吞吐量。
镜像集群
这种模式,才是所谓的 RabbitMQ 的高可用模式。跟普通集群模式不一样的是,在镜像集群模式下,你创建的 queue,无论元数据还是 queue 里的消息都会存在于多个实例上,就是说,每个 RabbitMQ 节点都有这个 queue 的一个完整镜像,包含 queue 的全部数据的意思。然后每次你写消息到 queue 的时候,都会自动把消息同步到多个实例的 queue 上。
好处在于,你任何一个机器宕机了,没事儿,其它机器(节点)还包含了这个 queue 的完整数据,别的 consumer 都可以到其它节点上去消费数据。坏处在于,第一,这个性能开销也太大了吧,消息需要同步到所有机器上,导致网络带宽压力和消耗很重!RabbitMQ 一个 queue 的数据都是放在一个节点里的,镜像集群下,也是每个节点都放这个 queue 的完整数据。
5、如何保证信息不丢失?
&ensp**;首先我们看看导致信息丢失的原因:**
情况一:消息生产者没有将消息成功发送到MQ;
;情况二:MQ的服务器宕机;
情况三:消费者消费到了消息,但是处理的过程中抛出了异常,导致消息丢失。
怎么处理才能保证数据不丢失?
1 消息发送者发送消息给MQ后,如果MQ成功收到,则给生产者发送确认信息,表示已经收到;
2 MQ收到消息以后,对消息进行持久化处理;
3 消费者消费消息并处理完毕后,给MQ发送确认消息;
4 MQ收到确认消息后,删除持久化的消息;
6、如何保证消息不被重复消费?如何保证消息的幂等性?
产生消息被重复消费的原因是什么?
原因一:当一条消息被发送到MQ以后,MQ返回的确认信息丢失了,即服务器对客户端应答失败了,此时生产者以为上一条信息发送失败了,则尝试了再次发送,此时消费者就会接受到两条一模一样的数据。
原因二:消息消费的场景下,消息已经投递到消费者,消费者也完成了业务,但是网络故障导致消费者的应答信息丢失了,MQ会在网络恢复以后再次投递刚刚已经消费的消息,这就导致消费者收到了两条一模一样的消息。
怎么解决?
消息重复一般都是由网络不可达造成的,不可避免,所以我们要解决的问题就是在信息重复的情况下如何保证幂等性。
1、消息发送者发送消息时,会携带一个全局唯一的id;
2、消费者获取消息后先到redis中根据id查询是否存在记录;
3、如果不存在则对消息进行消费,消费完成后将消息的id放入redis;
4、如果redis中存在消息id说明被消费过,直接丢弃;
7、如何保证消息消费的顺序性?
消息的有序性是指:
按照消息的发送顺序进行消费。例如一笔订单产生三个消息,分别是创建订单、订单付款、订单完成,按顺序依次消费才有意义。于此同时要保证多笔订单之间并行消费。
https://www.bilibili.com/video/BV1FE411A7AA?from=search&seid=18058018167668760145
8、当出现大量的消息堆积的时候如何处理?
为什么会出现大量的堆积?
消费方出现了故障,导致消息没有正常消费:网络故障或消费者进行消费后没有给出正确的应答。
1、检查并修复消费方的正常消费速度;
2、将堆积转移到更大的MQ;
3、增加多个消费节点,对堆积消息进行消费;
4、消费完毕后恢复原始框架;
9、消息过期了怎么办?
消息设置了过期时间,如果超时还未被消费,则视为消息过期,过期的消息可以转存到死信队列;
方案:
1 过期消息先存放到死信队列;
2 启动专门的消费者消费死信队列中的消息,并写入到数据库记录日志;
3 查询数据库消息日志,重新发送消息到MQ;
1 什么是消息中间件
1.1消息中间件(MQ)的定义
一般认为,消息中间件属于分布式系统中一个子系统,关注于数据的发送和接收,利用高效可靠的异步消息传递机制对分布式系统中的其余各个子系统进行集成。
高效:对于消息的处理处理速度快。
可靠:一般消息中间件都会有消息持久化机制和其他的机制确保消息不丢失。
异步:指发送完一个请求,不需要等待返回,随时可以再发送下一个请求,既不需要等待。
消息中间件不生产消息,只是消息的搬运工。
1.2 消息中间件的组成
1) Broker
消息服务器,作为server提供消息核心服务
2) Producer
消息生产者,业务的发起方,负责生产消息传输给broker,
3) Consumer
消息消费者,业务的处理方,负责从broker获取消息并进行业务逻辑处理
4) Topic
主题,发布订阅模式下的消息统一汇集地,不同生产者向topic发送消息,由MQ服务器分发到不同的订阅者,实现消息的广播
5) Queue
队列,PTP模式下,特定生产者向特定queue发送消息,消费者订阅特定的queue完成指定消息的接收
6) Message
消息体,根据不同通信协议定义的固定格式进行编码的数据包,来封装业务数据,实现消息的传输
1.3 消息中间件模式分类
点对点
PTP点对点:使用queue作为通信载体,消息生产者生产消息发送到queue中,然后消息消费者从queue中取出并且消费消息。 消息被消费以后,queue中不再存储,所以消息消费者不可能消费到已经被消费的消息。 Queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费。
发布/订阅
Pub/Sub发布订阅(广播):使用topic作为通信载体,消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到topic的消息会被所有订阅者消费。
2 消息中间件的优势和使用场景
2.1 消息中间件的优势
1)系统解耦
交互系统之间没有直接的调用关系,只是通过消息传输,故系统侵入性不强,耦合度低。
2)提高系统响应时间
3)流量削锋
比如在秒杀系统中,一般会建立消息中间件,客户的秒杀请求会放在消息中间件中
4.3 为大数据处理架构提供服务
通过消息作为整合,大数据的背景下,消息队列还与实时处理架构整合,为数据处理提供性能支持
3 kafka
kafka是分布式系统中基于发布订阅模式的消息队列,主要应用于大数据实时处理领域。
Questions、面试中的一些问题
https://blog.csdn.net/ThinkWon/article/details/104588612?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase
一、关于CAP原则的取舍
1、什么是CAP
CAP定理是指分布式WEB服务无法同时满足以下3个属性
数据一致性:如果系统对一个写操作返回成功,那么之后的读请求都必须读到这个新数据;如果返回失败,那么所有读操作都不能读到这个数据,对调用者而言数据具有强一致性
服务可用性:所有读写请求在一定时间内得到响应,可终止、不会一直等待
分区容错性:在网络分区的情况下,被分隔的及诶单仍然正常对外服务。
二、使用了消息队列会有什么缺点
系统可用性降低:你想啊,本来其他系统只要运行好好的,那你的系统就是正常的。现在 你非要加个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因此,系统可用性降低。
系统复杂性增加:要多考虑很多方面的问题,比如一致性问题、如何保证消息不被重复消费,如何保证保证消息可靠传输。因此,需要考虑的东西更多,系统复杂性增大
三、如何保证消息不被重复消费
分析:这个问题其实换一种问法就是,如何保证消息队列的幂等性?这个问题可以认为是消息队列领域的基本问题。
回答:先来说一下为什么会造成重复消费?
其实无论是那种消息队列,造成重复消费原因其实都是类似的。正常情况下,消费者在消费消息时候,消费完毕后,会发送一个确认信息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除。只是不同的消息队列发送的确认信息形式不同,例如RabbitMQ是发送一个ACK确认消息,让消息队列知道自己已经消费过了。那造成重复消费的原因?,就是因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将该消息分发给其他的消费者。
如何解决?这个问题针对业务场景来答分以下几点
(1)比如,你拿到这个消息做数据库的insert操作。那就容易了,给这个消息做一个唯一主键,那么就算出现重复消费的情况,就会导致主键冲突,避免数据库出现脏数据。
(2)再比如,你拿到这个消息做redis的set的操作,那就容易了,不用解决,因为你无论set几次结果都是一样的,set操作本来就算幂等操作。
(3)如果上面两种情况还不行,上大招。准备一个第三方介质,来做消费记录。以redis为例,给消息分配一个全局id,只要消费过该消息,将<id,message>以K-V形式写入redis。那消费者开始消费前,先去redis中查询有没消费记录即可。
以下内容来源于B站up主
https://www.bilibili.com/video/BV1dE411K7MG
RabbitMQ 实战教程
1.MQ引言
1.1 什么是MQ
MQ
(Message Quene) : 翻译为 消息队列
,通过典型的 生产者
和消费者
模型,生产者不断向消息队列中生产消息,消费者不断的从队列中获取消息。因为消息的生产和消费都是异步的,而且只关心消息的发送和接收,没有业务逻辑的侵入,轻松的实现系统间解耦。别名为 消息中间件
通过利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。
1.2 MQ有哪些
当今市面上有很多主流的消息中间件,如老牌的ActiveMQ
、RabbitMQ
,炙手可热的Kafka
,阿里巴巴自主开发RocketMQ
等。
1.3 不同MQ特点
# 1.ActiveMQ
ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。它是一个完全支持JMS规范的的消息中间件。丰富的API,多种集群架构模式让ActiveMQ在业界成为老牌的消息中间件,在中小型企业颇受欢迎!
# 2.Kafka
Kafka是LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache顶级项目。Kafka主要特点是基于Pull的模式来处理消息消费,
追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,
适合产生大量数据的互联网服务的数据收集业务。
# 3.RocketMQ
RocketMQ是阿里开源的消息中间件,它是纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。RocketMQ思路起
源于Kafka,但并不是Kafka的一个Copy,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消
息推送、日志流式处理、binglog分发等场景。
# 4.RabbitMQ
RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和
发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在
其次。
RabbitMQ比Kafka可靠,Kafka更适合IO高吞吐的处理,一般应用在大数据日志处理或对实时性(少量延迟),可靠性(少量丢数据)要求稍低的场景使用,比如ELK日志收集。
2.RabbitMQ 的引言
2.1 RabbitMQ
基于
AMQP
协议,erlang语言开发,是部署最广泛的开源消息中间件,是最受欢迎的开源消息中间件之一。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DjaFVGLR-1597111037184)(RibbitMQ 实战教程.assets/image-20190925215603036-9419777.png)]
官网
: https://www.rabbitmq.com/
官方教程
: https://www.rabbitmq.com/#getstarted
# AMQP 协议
AMQP(advanced message queuing protocol)`在2003年时被提出,最早用于解决金融领不同平台之间的消息传递交互问题。顾名思义,AMQP是一种协议,更准确的说是一种binary wire-level protocol(链接协议)。这是其和JMS的本质差别,AMQP不从API层进行限定,而是直接定义网络交换的数据格式。这使得实现了AMQP的provider天然性就是跨平台的。以下是AMQP协议模型:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zXH3TWWD-1597111037187)(RibbitMQ 实战教程.assets/image-20200311182438041.png)]
2.2 RabbitMQ 的安装
2.2.1 下载
官网下载地址
: https://www.rabbitmq.com/download.html[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AmSo6Kzf-1597111037190)(RibbitMQ 实战教程.assets/image-20190925220115235.png)]
最新版本
: 3.7.18
2.2.2 下载的安装包[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HkLmC1MS-1597111037193)(RibbitMQ 实战教程.assets/image-20190925220343521.png)]
注意
:这里的安装包是centos7安装的包
2.2.3 安装步骤
# 1.将rabbitmq安装包上传到linux系统中
erlang-22.0.7-1.el7.x86_64.rpm
rabbitmq-server-3.7.18-1.el7.noarch.rpm
# 2.安装Erlang依赖包
rpm -ivh erlang-22.0.7-1.el7.x86_64.rpm
# 3.安装RabbitMQ安装包(需要联网)
yum install -y rabbitmq-server-3.7.18-1.el7.noarch.rpm
注意:默认安装完成后配置文件模板在:/usr/share/doc/rabbitmq-server-3.7.18/rabbitmq.config.example目录中,需要
将配置文件复制到/etc/rabbitmq/目录中,并修改名称为rabbitmq.config
# 4.复制配置文件
cp /usr/share/doc/rabbitmq-server-3.7.18/rabbitmq.config.example /etc/rabbitmq/rabbitmq.config
# 5.查看配置文件位置
ls /etc/rabbitmq/rabbitmq.config
# 6.修改配置文件(参见下图:)
vim /etc/rabbitmq/rabbitmq.config
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4xfnWlSP-1597111037197)(RibbitMQ 实战教程.assets/image-20190925222230260-3836271.png)]
将上图中配置文件中红色部分去掉%%
,以及最后的,
逗号 修改为下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nI1sseOI-1597111037200)(RibbitMQ 实战教程.assets/image-20190925222329200-3836312.png)]
# 7.执行如下命令,启动rabbitmq中的插件管理
rabbitmq-plugins enable rabbitmq_management
出现如下说明:
Enabling plugins on node rabbit@localhost:
rabbitmq_management
The following plugins have been configured:
rabbitmq_management
rabbitmq_management_agent
rabbitmq_web_dispatch
Applying plugin configuration to rabbit@localhost...
The following plugins have been enabled:
rabbitmq_management
rabbitmq_management_agent
rabbitmq_web_dispatch
set 3 plugins.
Offline change; changes will take effect at broker restart.
# 8.启动RabbitMQ的服务
systemctl start rabbitmq-server
systemctl restart rabbitmq-server
systemctl stop rabbitmq-server
# 9.查看服务状态(见下图:)
systemctl status rabbitmq-server
● rabbitmq-server.service - RabbitMQ broker
Loaded: loaded (/usr/lib/systemd/system/rabbitmq-server.service; disabled; vendor preset: disabled)
Active: active (running) since 三 2019-09-25 22:26:35 CST; 7s ago
Main PID: 2904 (beam.smp)
Status: "Initialized"
CGroup: /system.slice/rabbitmq-server.service
├─2904 /usr/lib64/erlang/erts-10.4.4/bin/beam.smp -W w -A 64 -MBas ageffcbf -MHas ageffcbf -
MBlmbcs...
├─3220 erl_child_setup 32768
├─3243 inet_gethost 4
└─3244 inet_gethost 4
.........
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HUFjookQ-1597111037202)(RibbitMQ 实战教程.assets/image-20190925222743776-3836511.png)]
# 10.关闭防火墙服务
systemctl disable firewalld
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
systemctl stop firewalld
# 11.访问web管理界面
http://10.15.0.8:15672/
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DjLVVlaX-1597111037204)(RibbitMQ 实战教程.assets/image-20190926194738708-3836601.png)]
# 12.登录管理界面
username: guest
password: guest
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zE7EdAin-1597111037206)(RibbitMQ 实战教程.assets/image-20190926194954822-3836665.png)]
3. RabiitMQ 配置
3.1RabbitMQ 管理命令行
# 1.服务启动相关
systemctl start|restart|stop|status rabbitmq-server
# 2.管理命令行 用来在不使用web管理界面情况下命令操作RabbitMQ
rabbitmqctl help 可以查看更多命令
# 3.插件管理命令行
rabbitmq-plugins enable|list|disable
3.2 web管理界面介绍
3.2.1 overview概览
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yobMoCHI-1597111037207)(RibbitMQ 实战教程.assets/image-20191126162026720.png)]
-
connections:无论生产者还是消费者,都需要与RabbitMQ建立连接后才可以完成消息的生产和消费,在这里可以查看连接情况
-
channels:通道,建立连接后,会形成通道,消息的投递获取依赖通道。
-
Exchanges:交换机,用来实现消息的路由
-
Queues:队列,即消息队列,消息存放在队列中,等待消费,消费后被移除队列。
3.2.2 Admin用户和虚拟主机管理
1. 添加用户
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WrKaL4sz-1597111037208)(RibbitMQ 实战教程.assets/image-20191126162617280.png)]
上面的Tags选项,其实是指定用户的角色,可选的有以下几个:
-
超级管理员(administrator)
可登陆管理控制台,可查看所有的信息,并且可以对用户,策略(policy)进行操作。
-
监控者(monitoring)
可登陆管理控制台,同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等)
-
策略制定者(policymaker)
可登陆管理控制台, 同时可以对policy进行管理。但无法查看节点的相关信息(上图红框标识的部分)。
-
普通管理者(management)
仅可登陆管理控制台,无法看到节点信息,也无法对策略进行管理。
-
其他
无法登陆管理控制台,通常就是普通的生产者和消费者。
2. 创建虚拟主机
# 虚拟主机
为了让各个用户可以互不干扰的工作,RabbitMQ添加了虚拟主机(Virtual Hosts)的概念。其实就是一个独立的访问路径,不同用户使用不同路径,各自有自己的队列、交换机,互相不会影响。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-obDNso0x-1597111037209)(RibbitMQ 实战教程.assets/image-20191126163023153.png)]
3. 绑定虚拟主机和用户
创建好虚拟主机,我们还要给用户添加访问权限:
点击添加好的虚拟主机:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6jNVQCSt-1597111037211)(RibbitMQ 实战教程.assets/image-20191126163506795.png)]
进入虚拟机设置界面:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pvrRETQf-1597111037212)(RibbitMQ 实战教程.assets/image-20191126163631889.png)]
4.RabbitMQ 的第一个程序
4.0 AMQP协议的回顾
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FR9EEXB7-1597111037213)(RibbitMQ 实战教程.assets/image-20200312140114784.png)]
4.1 RabbitMQ支持的消息模型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xPFcmeN9-1597111037214)(RibbitMQ 实战教程.assets/image-20191126165434784.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hHgoJ7bU-1597111037216)(RibbitMQ 实战教程.assets/image-20191126165459282.png)]
4.2 引入依赖
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.7.2</version>
</dependency>
4.3 第一种模型(直连)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tgg6lmA8-1597111037217)(RibbitMQ 实战教程.assets/image-20191126165840602.png)]
在上图的模型中,有以下概念:
- P:生产者,也就是要发送消息的程序
- C:消费者:消息的接受者,会一直等待消息到来。
- queue:消息队列,图中红色部分。类似一个邮箱,可以缓存消息;生产者向其中投递消息,消费者从其中取出消息。
1. 开发生产者
//创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory()