RabbitMq学习笔记

消息中间件作用:异步解耦

rabbitMq的组成:

producer:生产者,消息的发送方

connection:生产者或消费者和mq的连接,是一种TCP长连接

broker:mq服务器或者叫代理

virtual host:虚拟主机,用来隔离不同环境,比如测试环境和生产环境,或者用户之间的隔离

exchange:交换机,处理消息分配到相应的队列,有四种类型:direct(直接交换机,路由键完全一致,点对点路由)、fanout(广播,路由到所有该交换机绑定的队列)、topic(根据路由键路由,可以模糊匹配)、header(性能不好,很少用)

queue:存放消息,消费者从队列中取消息

binding:交换机和队列的绑定关系,一个交换机可以绑定多个队列,一个队列也可以被多个交换机绑定,交换机还可以绑定交换机

consumer:消费者,消费者主动拉取消息

channel:信道,在connection上建立的虚拟链接,每个线程通过自己的信道连接,就减少了TCP连接销毁的开销。

安装rabbitMq

通过docker安装命令:

docker run -d —name rabbitmq -p 5671:5671 -p 5672:5672 -p 4369:4369 -p 25672:25672 -p 15671:15671 -p 15672:15672 rabbitmq:management

4369,25672(Elang发现和集群端口)

5672,5671(AMQP端口)

15672(web管理后台端口)

61613,61614(STOMP协议端口)

1883,8883(MQTT协议端口)

rabbitmq:management(management版本带可视化界面)

安装完成后 网页输入ip:15672则可打开rabbitmq界面(用户名和密码:guest):

springboot整合rabbitmq

导入依赖:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-amqp</artifactId>
	<version>2.2.6.RELEASE</version>
</dependency>

以下方法在测试类中

创建交换机:

@Test
	void createExchange() {
		// DirectExchange 、 FanoutExchange、 TopicExchange。。。
		//DirectExchange(String name, boolean durable, boolean autoDelete, Map<String, Object> arguments)
		/**
		 * name:交换机名称
		 * durable:是否持久化(默认为true,设为false则重启后销毁)
		 * autoDelete:是否自动删除(默认false)
		 * arguments:
		 */
		DirectExchange directExchange = new DirectExchange("hello-exchange");
		amqpAdmin.declareExchange(directExchange);
		log.info("交换机{}创建成功", "hello-exchange");
	}

执行结果:

下面的是直接在页面新建交换机,参数和代码里的参数一致。 

创建队列:

@Test
	void createQueue() {
		//Queue(String name, boolean durable, boolean exclusive, boolean autoDelete, @Nullable Map<String, Object> arguments)
		/**
		 * name:队列名称
		 * durable:是否持久化(默认为true,设为false则重启后销毁)
		 * exclusive:是否排他,只对首次连接可见(默认false)
		 * autoDelete:是否自动删除(默认false)
		 * arguments:
		 */
		Queue queue = new Queue("hello-queue");
		amqpAdmin.declareQueue(queue);
		log.info("队列{}创建成功", "hello-queue");
	}

执行结果:

 

创建绑定关系:

@Test
	void createBinding() {
		//Binding(String destination, Binding.DestinationType destinationType, String exchange, String routingKey, @Nullable Map<String, Object> arguments)
		/**
		 * 参数:
		 *  destination:目标队列/交换机
		 *  Binding.DestinationType:目标类型:queue/exchange
		 *  exchange:交换机
		 *  routingKey:路由键
		 *  arguments:
		 */
		Binding binding = new Binding("hello-queue", Binding.DestinationType.QUEUE, "hello-exchange", "hello.route", null);
		amqpAdmin.declareBinding(binding);
		log.info("绑定关系{}和{}创建成功", "hello-queue", "hello-exchange");
	}

执行结果:

  

发送消息:

/**
	 * 发送消息为对象时需要序列化:
	 * import lombok.Data;
	 * import java.io.Serializable;
	 *
	 * // 消息传递的对象必须继承Serializable,实现序列化
	 * @Data
	 * public class Person implements Serializable {
	 *     private String name;
	 *
	 *     private int id;
	 *
	 *     private int age;
	 * }
	 *
	 * 收到的消息也是序列化之后的数据
	 *
	 * 可以在容器中注入MessageConverter,则可以使用我们定义的MessageConverter
	 *
	 * import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
	 * import org.springframework.amqp.support.converter.MessageConverter;
	 * import org.springframework.context.annotation.Bean;
	 * import org.springframework.context.annotation.Configuration;
	 *
	 * @Configuration
	 * public class MyRabbitConfig {
	 *
	 *     @Bean
	 *     public MessageConverter messageConverter() {
	 *         // 转换成json
	 *         return new Jackson2JsonMessageConverter();
	 *     }
	 * }
	 */
	@Test
	void setMessage(){
		Person person = new Person();
		person.setAge(19);
		person.setId(1);
		person.setName("haha");
		rabbitTemplate.convertAndSend("hello-exchange", "hello-queue", person);
	}

执行结果:

 

  

监听消息:

@EnableRabbit:开启基于注解的rabbit

@RabbitListener:指定监听的队列,可以标注在方法上也可以标注在类上(标注在类上和@RabbitHander一起使用,用于接收多种返回体的消息)

调用发送消息接口:


    @GetMapping("/sendMessage")
    @ApiOperation(value = "发送消息", notes = "发送i条消息")
    public String sendMessage(@RequestParam(defaultValue = "10") Integer i) {
        return producer.senMessage(i);
    }

发送消息:

import com.example.gpy.provider.vo.Person;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class Producer {

    @Autowired
    RabbitTemplate rabbitTemplate;

    public String senMessage(Integer num) {
        log.info("发送消息开始:" + num);
        for(int i = 0; i < num; i++) {
            Person person = new Person();
            person.setAge(19);
            person.setId(i);
            person.setName("haha" + i);
            rabbitTemplate.convertAndSend("hello-exchange", "hello-queue", person);
        }
        return "OK";
    }
}

监听消息: 

import com.example.gpy.provider.vo.Person;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Slf4j
// 监听消息的组件需要在容器中
@Component
public class customer {

    @RabbitListener(queues = "hello-queue")
    public void getMessageHello(Message message, Person person) throws InterruptedException {
        log.info("接收消息:{}", person);
        Thread.sleep(1000);
        log.info("消息处理完成,用户id::{}", person.getId());
    }
}

结果:

后台起了两个服务,看的出来一条消息只能被处理一次,并且消息是依次处理的。 

 

使用@RabbitHander接收消息

@Slf4j
@Service
public class Producer {

    @Autowired
    RabbitTemplate rabbitTemplate;

    public String senMessage(Integer num) {
        log.info("发送消息开始:" + num);
        for(int i = 0; i < num; i++) {
            if(i%2==0) {
                Person person = new Person();
                person.setAge(19);
                person.setId(i);
                person.setName("person" + i);
                rabbitTemplate.convertAndSend("hello-exchange", "hello-queue", person);
            } else {
                Student student = new Student();
                student.setBanJi(2);
                student.setId(i);
                student.setName("xuesheng" + i);
                rabbitTemplate.convertAndSend("hello-exchange", "hello-queue", student);
            }
        }
        return "OK";
    }
}
@Slf4j
// 监听消息的组件需要在容器中
@Component
@RabbitListener(queues = "hello-queue")
public class customer {

    @RabbitHandler
    public void getMessageHello(Message message, Person person) throws InterruptedException {
        log.info("接收消息Person:{}", person);
        Thread.sleep(1000);
        log.info("消息处理完成,用户id::{}", person.getName());
    }

    @RabbitHandler
    public void getMessageHello(Message message, Student student) throws InterruptedException {
        log.info("接收消息Student:{}", student);
        Thread.sleep(1000);
        log.info("消息处理完成,用户id::{}", student.getName());
    }
}

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值