Spring Cloud整合RabbitMQ或Kafka消息驱动(二十二)

Spring Cloud整合RabbitMQ

如图所示,这里将创建一个Eureka集群,其中两个Eureka客户端分别作为消息的生产者和消息的消费者,外部使用RabbitMQ或者Kafka中间件来处理消息。

还是沿用我们以前写的Eureka集群,去Spring Cloud服务管理框架Eureka简单示例(三)这篇博客底部拿到我们的Eureka集群代码。

首先是发送消息,我们让eureka-provider作为我们的消息生产者,首先在pom.xml加入Spring整合RabbitMQ的stream流依赖:

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>

配置文件没有改动,因为Spring Cloud默认使用的是RabbitMQ来作为消息中间件的,所以我们这里省略了RabbitMQ的配置信息:

spring:
  application:
    name: eureka-provider
  #rabbitmq:
  #  host: localhost
  #  port: 5672
  #  username: guest
  #  password: guest

之后是删除com.init.springCloud包下的Person.class类,我们这里不使用这个类(也可以保留,对操作没有影响),新建SendMessageService接口:

package com.init.springCloud;

import org.springframework.cloud.stream.annotation.Output;
import org.springframework.messaging.SubscribableChannel;

public interface SendMessageService {

	@Output(value = "myExchange")
	SubscribableChannel myOutput();
	
}

在这里我们使用了一个@Output的注解,相当于是指定RabbitMQ中接收信息的交换器(Exchange)的名称(没有这个交换器,就创建一个),Exchange的类型默认为Topic类型:

  • Direct: 如果 routing key 匹配, 那么Message就会被传递到相应的queue中。其实在queue创建时,它会自动的以queue的名字作为routing key来绑定那个exchange。
  • Fanout: 会向响应的queue广播。
  • Topic: 对key进行模式匹配,比如ab*可以传递到所有ab*的queue。

之后RabbitMQ会创建一个没有名字的Queue(或者说名称是随机生成的),交换器把消息交给这个Queue来处理分发,当处理完毕,连接断掉的时候,这个Queue就会被销毁。

当然,我们的步骤还没有完成,想要把Exchange内部的消息发送到对应的Queue上,还需要做一个操作:绑定,我们在ProviderApp启动类里面加上这个注解进行绑定:

@EnableBinding(SendMessageService.class)

之后,修改ProviderController.class类,提供一个外部方法发送消息:

package com.init.springCloud;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProviderController {

	@Autowired
	private SendMessageService sendMessageService;
	
	@RequestMapping(value = "/send", method = RequestMethod.GET)
	@ResponseBody
	public String sendMessage(){
		Message<byte[]> message = MessageBuilder.withPayload("Hello World".getBytes()).build();
		sendMessageService.myOutput().send(message);
		return "success";
	}
	
}

完成之后,启动eureka-provider项目(记得要先启动euraka-server项目)。

之后,修改eureka-consumer项目,让它作为消息消费者,在pom.xml中加入相同依赖:

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>

新增ReceiveMessageService接口:

package com.init.springCloud;

import org.springframework.cloud.stream.annotation.Input;
import org.springframework.messaging.SubscribableChannel;

public interface ReceiveMessageService {

	@Input(value = "myExchange")
	SubscribableChannel myInput();
	
}

在ConsumerApp里面也使用注解进行绑定:

@EnableBinding(ReceiveMessageService.class)

为了能够正常收到信息,我们写一个监听方法来侦听RabbitMQ推送过来的消息,完整的ConsumerApp如下:

package com.init.springCloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;

@SpringBootApplication
@EnableEurekaClient
@EnableBinding(ReceiveMessageService.class)
public class ConsumerApp {

	public static void main(String[] args) {
		SpringApplication.run(ConsumerApp.class, args);
	}
	
	@StreamListener("myExchange")
	public void onReceive(byte[] msg){
		System.out.println("接受到的消息:"+ new String(msg));
	}

}

启动eureka-consumer项目,同时注意开启RabbitMQ的服务,之后访问:http://localhost:8080/send,查看eureka-consumer项目的控制台,我们已经侦听到了来自eureka-provider的消息:


同时我们也可以查看一下RabbitMQ控制管理界面的情况,创建了一个我们命令的交换器,还有临时的Queue:



Spring Cloud整合Kafka

其实我们在做绑定的时候,用到了Spring Cloud提供的绑定器,用于联合Spring Cloud与消息中间件,当我们使用RabbitMQ的时候,绑定器用的就是RabbitMQ的绑定器,Kafka用的就是Kafka的绑定器,更换绑定器,其他的配置或者代码都不用做更改,就能实现消息的发送与接收。当然,我们在eureka-provider项目和eureka-consumer项目的pom.xml中还是需要引入Kafka对应的依赖:

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-stream-kafka</artifactId>
</dependency>
启动Eureka集群,之后,把Zookeeper和Kafka都启动起来(启动方法看之前的博客),这里需要提醒的是:Kafka如果有缓存启动不成功的话,可以先把Kafka对应tmp文件下的文件清空,再次启动Kafka。

访问:http://localhost:8080/send,eureka-consumer的控制台打印出了接收到的消息:


和RabbitMQ不同的是,@Output和@Input对应的值是Kafka里面的Topic,这个可以通过在命令行进入Kafka的kafka_2.11-1.1.0\bin\windows目录,运行kafka-topics --list --zookeeper localhost:2181查看:


在Spring Cloud中,同样使用到了消费者组的概念:当A和B两个项目使用的是同一个消费者组的时候,消息只会由其中一个接受到;若消费者组不相同,则A和B都能接收到消息,只需要在消息消费者对应项目的application.yml的配置文件中为它指定消费者组就OK了,配置如下:

spring:
  cloud:
    stream:
      bindings:
        input:
          group: myGroup
源码点击这里

猜你喜欢

转载自blog.csdn.net/mrspirit/article/details/80574164