Spring Cloud 学习笔记6——消息总线

消息总线和配置中心是微服务架构的两个重要组件

Spring Cloud Bus目前仅支持两款中间件产品:RabbitMQ和Kafka

RabbitMQ及Kafka安装请看消息队列相关笔记

整合RabbitMQ

1、引入AMQP依赖

pom.xml文件中加入:

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

可看到多了一个jar包amqp-client-4.0.3.jar

2、在application.properties中配置RabbitMQ的连接和用户信息

#RabbitMQ配置
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=user1
spring.rabbitmq.password=123456

spring.rabbitmq.host指定RabbitMQ host

spring.rabbitmq.port指定RabbitMQ的端口

addresses与host+port的区别:

spring.rabbitmq.addresses指定client连接到的server的地址,可以配置多个服务地址,以逗号分隔,如host1:9999,host2:1111。host+port的方式只能配置一个服务地址。

3、创建消息生产者

通过AmqpTemplate接口发送消息,Spring Boot会根据配置来注入其具体实现,我们采用默认配置即可,

@Component
public class MqSender {
	@Autowired
	private AmqpTemplate amqpTemplate;
	public void sendUserPojo(UserPojo userPojo) {
		amqpTemplate.convertAndSend("queue1", userPojo);
	}
	
	public void sendStr(UserPojo userPojo) {
		String str = JSON.toJSONString(userPojo);
		amqpTemplate.convertAndSend("queue2", str);
	}
}

convertAndSend有多个重载方法,如:

  • convertAndSend(String routingKey, Object message)
  • convertAndSend(String exchange, String routingKey, Object message)

 

为了方便测试可以在controller加上一个http接口:

	@Autowired
	private MqSender mqSender;
	@RequestMapping(value = "/sendUserPojoToMQ", method = RequestMethod.POST)
	public String sendUserPojoToMQ(@RequestBody UserPojo userPojo) {
		mqSender.sendUserPojo(userPojo);
		return "success";
	}
	
	@RequestMapping(value = "/sendStringToMQ", method = RequestMethod.POST)
	public String sendStringToMQ(@RequestBody UserPojo userPojo) {
		mqSender.sendStr(userPojo);
		return "success";
	}

可以通过http://localhost:15672的queue Tab查看队列详细信息,如果没有队列,可以手动创建一个,即使不创建,消息也能存放到队列中,只是在页面上看不到该队列的详细信息。

4、创建消息消费者

通过@RabbitListener修饰方法,对queue1队列进行监听,并用@RabbitHandler注解来指定对消息的处理方法,注意这两个注解都是用于方法,书上说@RabbitListener用于类,测试这样是会报错的。

@Component
public class MqReceiver {
	@RabbitListener(queues="queue1")
	@RabbitHandler
	public void process1(@Payload UserPojo userPojo) {
		System.out.println("收到消息:name="+userPojo.getName()+",age="+userPojo.getAge());
	}
	
	@RabbitListener(queues="queue2",exclusive = true)
	@RabbitHandler
	public void process2(String string) {
		System.out.println("收到消息:"+string);
	}
}

@RabbitListener有多个属性可以配置的,比较常用的是queues和exclusive,queues用于指定监听的队列。exclusive如果为true,则消费者排他式地使用队列,若多个消费者监听同一个队列,其中一个消费者取出了某条消息,则这条消息就不存在队列中了,其它消费者只能取下一条消息,默认为false,即每个消费者是独立的,队列中的每条消息都能被所有消费者一起使用。可以理解为,当为true时,是取出消息,当为false时,消费者仅仅把自己在队列中的下标移动而已。

消费者常见启动报错情况:

1、无限循环抛出以下异常:

Caused by: org.springframework.amqp.AmqpException: No method found for class [B

这种情况是@RabbitListener修饰的对象搞错了,书上说用于修饰类,实际上却是用于修饰方法的。

2、报错:Payload value must not be empty

1)方法的参数中加上注解@Payload

2)UserPojo要序列化(生产者、消费者的UserPojo都要序列化)

3)报错说找不到UserPojo类

从错误信息可看出,消费者的UserPojo所在的位置要和生产者一样,真是绑得好死,所以还要改一下消费者的UserPojo位置。所以,尽量还是不要用自定义的对象,最好是用json字符串

4)报错说找不到队列,消费者要能启动的前提是队列已存在,如果队列还没创建,消费者启动是会报错的。

 

5、配置队列、交换器、路由等信息

以上代码都是默认配置,我们可以根据需要自定义配置,如下是一个最小化的配置:

    /**
     * 定义队列
     */ 
	@Bean
	public Queue queue1Queue() {
		return new Queue("queue1");
	}

    /**
     * 定义交换机
     */
    @Bean
    TopicExchange exchange() {
        return new TopicExchange("exchange1");
    }

    /**
     * 定义绑定
     * @param queue
     * @param exchange
     */
    @Bean
    Binding binding(Queue queue, TopicExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("bind-key-1");
    }

注解方式如何灵活访问不同队列?

 

非注解方式

 

RabbitMQ配置项

 

 

整合Kafka

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值