Java message service的基本概念及RabbitMQ的实现

  • 一、JMS(Java message service)的概念
  • 1、producer 生产者
  • 2、consumer 消费者
  • 3、JMP的可靠性
  • 三、RabbitMQ
  • 1、RabbitMQ的概念
  • 2、Springboot集成RabbitMQ
  • 3、定义JMSService接口
  • 四、用RabbitMQ实现收发送消息
  • 目标
  • 知识点
  • 1、定义api模块
  • 2、定义jms-rabbitmq模块
  • 2.1、定义RabbitMQDeclare实现
  • 2.2、定义SMSConfig配置类
  • 2.3、定义发送实现
  • 2.4 定义接收实现
  • 2.5 RabbitMQ自定义配置类


一、JMS(Java message service)的概念

1、producer 生产者

  producer指的是消息发起方,要投递消息的那端,如果投递的是一对一的队列消息,那么它就是队列发送人,如果投递的是一对多的发布/订阅类型,那么它就是主题发布者

2、consumer 消费者

  就是消息的接收方,如果递交的是一对一的队列,那么它是队列的接收者,如果投资的是一对多的发布/订阅类型,那么它就是主题订阅者

3、JMP的可靠性

  持久化:服务器宕机时会将数据保存到本地,可保证未被发送的消息在消费前不会丢失,亦不会重复发送、重复消费

  事务支持ACID:

    producer的事务发送:发送一组消息直止commit为止,如果中途有故障或某些原因产生rollback则这批消息不会被发送,从而保证事务完整性

    consumer的事务接收:consumer要么整批接收要么一条也不收。

  ACK确认机制: 事务和ack都是消息确认的方式,同时存在时事务的优先级要高一些,开启事务时ack是无效的,非事务的模式下,ack开启才有效。

三、RabbitMQ

  JMS只是消息服务的一个协议,而实现却有好几家,如ActiveMQ,RabbitMQ,RocketMQ等。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fAJ2936E-1641777846170)(https://static01.imgkr.com/temp/e0415dc61159447e989a41955956b6d4.png)]

1、RabbitMQ的概念

  RabbitMQ的核心概念包括:生产者、消费者、消息模型(虚拟主机、消息通道、交换机、路由、队列),生产者、消费者前面已讲过,现在讲一下消息模型里面的三个概念:

  虚拟主机(vhost):

   虚拟主机:一个虚拟主机持有一组交换机、队列和绑定。虚拟主机的作用在于进行权限管控,rabbitmq默认有一个虚拟主机"/"。可以使用rabbitmqctl add_vhost命令添加虚拟主机,然后使用rabbitmqctl set_permissions命令设置指定用户在指定虚拟主机下的权限,以此达到权限管控的目的。

  消息通道(channel):

   消息通道: 在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务。

  交换机: 消息的运输者(快递员)

交换机: exchange的功能是用于消息分发,它负责接收消息并转发到与之绑定的队列,exchange不存储消息,如果一个exchange没有binding任何Queue,那么当它会丢弃生产者发送过来的消息,在启用ACK机制后,如果exchange找不到队列,则会返回错误。一个exchange可以和多个Queue进行绑定。

交换机有四种类型:

路由模式(Direct):

direct 类型的行为是"先匹配, 再投送"。即在绑定时设定一个 routing_key, 消息的routing_key 匹配时, 才会被交换器投送到绑定的队列中去。direct是rabbitmq的默认交换机类型。

通配符模式(Topic):

类似路由模式,但是routing_key支持模糊匹配,按规则转发消息(最灵活)。符号“#”匹配一个或多个词,符号“*”匹配不多不少一个词。

发布订阅模式(Fanout):

转发消息到所有绑定队列,忽略routing_key。

Headers:

设置header attribute参数类型的交换机。相较于 direct 和 topic 固定地使用 routing_key , headers 则是一个自定义匹配规则的类型,忽略routing_key。在队列与交换器绑定时, 会设定一组键值对规则, 消息中也包括一组键值对( headers 属性), 当这些键值对有一对, 或全部匹配时, 消息被投送到对应队列。
在绑定Queue与Exchange时指定一组键值对,当消息发送到RabbitMQ时会取到该消息的headers与Exchange绑定时指定的键值对进行匹配。如果完全匹配则消息会路由到该队列,否则不会路由到该队列。headers属性是一个键值对,可以是Hashtable,键值对的值可以是任何类型。

匹配规则x-match有下列两种类型:

x-match = all :表示所有的键值对都匹配才能接受到消息
x-match = any :表示只要有键值对匹配就能接受到消息

  路由: 消息的运输途径(列车?汽车?飞机?)

  队列: 消息的运输路线(从东莞到武汉)

以快递为例,陈大文要从东莞快递一套13香给武汉的小明,那么:
陈大文(producer)把13香(消息)打包给快递员(交换机),快递员把包裹拿回总部然后根据要求选择了从东莞送到武汉(队列)的飞机(路由)路线,
最终小明(consumer)收到包裹。

2、Springboot集成RabbitMQ

  加上依赖:

<!-- rabbit mq -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

3、定义JMSService接口

  因为要考虑到日后可以会将RabbitMQ换成其他厂的MQ,所以一定要采用接口方式

四、用RabbitMQ实现收发送消息

  上面已经搭好框架,现在基于这个框架做一个自定义类SMS的发送与接收例子。
  原理:先在application.yml里面定义

目标

  1、rabbitmq的集成;
  2、定义两组rabbitmqtemplate,一组名为AckRabbitTemplate的发送时会触发confirm/return回调(用于严谨事务处理);
别一组RabbitTemplate则不触发回调,自动ack.
  3、消费端亦能实现某些消费可以自动ack,某些消费要手动ack

知识点

  application.yml里面的publisher-returns、publisher-confirm-type只是针对producer的参数;listener参数只是针对consumer端
  RabbitTemplate.waitForConfirms和rabbitmq的confirm、return回调只是针对producer->broker端,但凡它将消息送至broker的交换机就会call confirm,
如果交换机没能将消息投入队列,则会call return. 这一切讲的是producer和broker的事,和consumer没一毛钱关系
  Consumer的ack也是同样道理,它只是consumer和mq broker之间的确认,和producer没一毛钱关系
  consumer方需要ack的若没有ack确认,则在Broker界面会看到unacked累加,一旦consumer方关闭,这个unacked就会转成ready(待发到consumer),consumer重启后就会又收到这批未ack的消息
  @RabbitListener可以通过参数指明是自动ack还是手动ack,这个参数比application.yml的listener设置的优先度高
  若同一消息发出能多条队列同时接收,用direct方式的交换机也能实现,那就是将多个队列绑定到同一个交换机同一个routerkey即可

1、定义api模块

  将调用规范、api接口、pojo数据结构还有一些常量类抽离放在api 模块中。

2、定义jms-rabbitmq模块

  此模块是用RabbitMQ方式收发sms消息

2.1、定义RabbitMQDeclare实现

  这个是JMSService接口的RabbitMQ实现,包括交换机、队列的通用操作。

2.2、定义SMSConfig配置类

  它的作用是app初始化后,用来创建收发SMS所需要的交换机、队列

2.3、定义发送实现

com.freestyle.jmssample.rabbitmq.service.SendSMSServiceImp

2.4 定义接收实现

com.freestyle.jmssample.rabbitmq.service.ReceiveSMSServiceImp

2.5 RabbitMQ自定义配置类

com.freestyle.jms.common.RabbitMQConfig

代码链接,觉得有用的话请点个Star: https://gitee.com/tigera15/jms-samples/tree/master