消息中间件-RabbitMQ

消息中间件-RabbitMQ

rabbitmq分布式消息队列,即用来使不同的服务间消息传递,在此过程中分为发送者、接收者。

优点:

  • 异步处理: 相比于传统的串行、并行方式,提高了系统吞吐量。
  • 应用解耦 :系统间通过消息通信,不用关心其他系统的处理。
  • 流量削锋 : 可以通过消息队列长度控制请求量;可以缓解短时间内的高并发请求。
  • 日志处理:解决大量日志传输。
  • 消息通讯:消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等。

详情:https://blog.csdn.net/thinkwon/article/details/104588612/

在这里插入图片描述

详图:来自 https://blog.csdn.net/qq_35387940/article/details/100514134
在这里插入图片描述
使用RabbitMQ,服务将进行如下几个步骤:

  • 建立连接:可以使用ConnectionFactory来构建Connection。
  • 创建通道:Channel
  • 发送 / 接收消息:此过程使用队列
  • 关闭通道、关闭连接

RabbitMQ 发送消息时(消息有很多),将消息放在队列(先进先出)中,接收者从队列获取发送者发送的消息。

接收者接收完毕后,会为发送者发送一个成功信号,发送者收到信号后才将消息从队列中删除。

因为不加此机制的话,如果在接收者在接收消息时挂了,发送者删除消息将导致消息无法被处理。加了此机制后,挂掉的接收者无法向发送者发送成功消息,所以发送者不会删除消息。
在这里插入图片描述

当然如果当前接收者挂了,一定时间后,它会将消息交给另一个服务来处理。

发布订阅者模式:发送者发送一条消息后,所以可以接收消息的服务都能收到。

在这里插入图片描述

消息分组

默认情况下,rabbitmq采用发布-定阅模式,所有启动的服务都能收到消息,但是不是所有服务都需要这个消息,因此我们需要进行消息分组,组外的服务就无法收到这个消息了。

springboot整合RabbitMQ

首先我们需要安装并启动RabbitMQ server,服务既可以收消息又可以发消息,下面就已仅收、仅发来讲解rabbitmq的使用。
启动后可访问:http://127.0.0.1:15672 进入控制台,用户密码均为:guest

1.服务引入RabbitMQ

1.项目依赖:

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

2.yml配置:

spring:
 rabbitmq:
   host: localhost
   port: 5672
   username: rabbit
   password: rabbit
   virtual-host: myhost	#虚拟机名,如果没添加,直接用 / 即可
   

注意:账号rabbit是在控制台新加的,默认账号不支持远程连接

2.发送者(仅发送):

1.交换机配置:注意是amqp包下的

@Configuration
public class RabbitConfig {

   /**
    * new Queue():
    *  参数一:队列名称
    *  参数二:是否持久化队列,默认true
    *  参数三:是否为当前连接专属,连接关闭后销毁,默认false
    *  参数四:是否自动删除,无服务使用时自动删除,默认false
    *
    */
   @Bean//队列
   public Queue theQueue(){
       return new Queue("theQueue",true);
   }

   @Bean//交换机
   public DirectExchange theDirectExchange(){
       return new DirectExchange("theDirectExchange",true,false);//名字、持久化、自动删除
   }

   @Bean//绑定队列、交换机,匹配值为key
   public Binding bindingDirect() { //监听key的服务会收到消息
       return BindingBuilder.bind(theQueue()).to(theDirectExchange()).with("key");
   }
   
   @Bean
   public Binding bindingDirectAll() { //监听Key开头的服务会收到消息
       return BindingBuilder.bind(theQueue()).to(theDirectExchange()).with("key.#");
   }
}

最后2个方法是绑定队列和交换机并指定一个可被监听的key,因此可以实现多个组合。

2.消息发送:

@RestController
@RequestMapping("/rabbit")
public class RabbitController {
   
   @Autowired
   private RabbitTemplate rabbitTemplate;
   
   @PostMapping
   public void sendMessage(){//交换机、绑定键、消息
       rabbitTemplate.convertAndSend("theDirectExchange","key","hello world!");
   }
}

接收者(仅接收):

队列监听,并接收

@Component
@RabbitListener(queues = "theQueue")//监听的队列名
public class RabbitListen {

   @RabbitHandler
   public void getMessage(String message){
       System.out.println(message);
   }
}

使用注解 @RabbitListener 监听指定队列,使用 @RabbitHandler 标记接收方法。

Stream整合RabbitMQ(SpringCloud)

1.项目依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-stream</artifactId>
</dependency>
<!--生产者-->
<dependency>
    <groupId>org.sshengcpringframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
<!--消费者-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>

2.yml配置

spring:
  application:
    name: rabbitmq-service #指定服务名
  rabbitmq:
    addresses: 127.0.0.1
    username: itcast
    password: itcast
    virtual-host: myhost
  cloud:
    stream:
      bindings:
        output: #发送通道
          destination: itcast-default #指定消息发送目的地
        input: #消费通道
          destination: itcast-default #指定消息来源
          #contentType: text/plain #消息类型
      binders:	#配置绑定器
        defaultRabbit:
          type: rabbit

发送:

1.定义发送通道:output

public interface Source {	

	@Output("output")//发送通道接口
	MessageChannel myoutput();
}

2.发送:

@Component
@EnableBinding(Source.class)//绑定通道
public class MessageSender {

	@Autowired
	private MessageChannel messageChannel ;

	//发送消息
	public void send(Object o) {
		messageChannel.send(MessageBuilder.withPayload(o).build());
	}
}

2.接收:

1.接收通道

public interface Sink {
 @Input("input")
 SubscribableChannel input();
}

2.接收

@Component
@EnableBinding(Sink.class)//绑定通道
public class GetMessageSender {

	@StreamListener("input")//监听通道
	private MessageChannel messageChannel ;

	//接收消息
	public void getMessage(String message) {
		 System.out.println( message);
	}
}

几种消息模式

1.收发模式:

生产者将消息放入队列,消费者从队列消费。如果消费者消费后向队列发送ack,队列收到ack后才删除消息。
在这里插入图片描述
多个消费者存在资源竞争,可以加锁解决。

2.发布订阅模式:

每个消费者监听自己的队列,生产者的消息通过交换机发送给每个队列。
在这里插入图片描述

3.路由模式

交换机根据路由字符串来匹配决定将消息发送到哪个队列。
在这里插入图片描述
主体模式
在这里插入图片描述
也是路由模式,只不过是根据表达式来匹配。

RabbitMQ 高可用集群

单台RabbitMQ服务到达瓶颈后,需要开启多个RabbitMQ server来分摊压力。
在这里插入图片描述

RabbitMQ不支持负载均衡,可以通过nginx实现负载均衡。

RabbitMQ集群各节点之间共享队列,但各队列之间默认数据不同步,仅收到消息的队列有消息,所以需要开启镜像模式,才能同步并实现高可用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值