Presentar la integración de Spring Cloud Stream y RabbitMQ
Prefacio
Spring Cloud Stream es un marco creado en Spring Boot y Spring Integration para ayudar a crear microservicios impulsados por eventos o mensajes. En este artículo, presentaremos el concepto y la estructura de Spring Cloud Stream a través de algunos ejemplos simples.
- Enlaces: una colección de interfaces que declaran canales de entrada y salida.
- Binder: implementación de middleware de mensajes, como Kafka o RabbitMQ
- Canal: representa el canal de comunicación entre el middleware de mensajes y la aplicación.
- StreamListeners - el método de procesamiento de mensajes en el bean. Después de que se realiza la serialización / deserialización del objeto en el evento específico MessageConverter del middleware, el método de procesamiento de mensajes se llamará automáticamente en el mensaje en el canal.
- Esquemas de mensajes: se utilizan para la serialización y deserialización de mensajes. Estos esquemas se pueden leer de forma estática o cargada dinámicamente y son compatibles con la evolución de los tipos de objetos.
confiar:
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-stream-rabbit'
Fin de producción:
1.completo
spring:
application:
name: rabbitmq-springcloudstream-producer
cloud:
stream:
instanceCount: 3
bindings:
output_channel: #输出 生产者
group: queue-1 #指定相同的exchange-1和不同的queue 表示广播模式 #指定相同的exchange和相同的queue表示集群负载均衡模式
destination: exchange-1 # kafka:发布订阅模型里面的topic rabbitmq: exchange的概念(但是exchange的类型那里设置呢?)
binder: local_rabbit
binders:
local_rabbit:
type: rabbit
environment:
spring:
rabbitmq:
host: 10.0.0.22
port: 5672
username: xiefei
password: xiefei
virtual-host: /
2.Barista
/**
* 这里的Barista接口是定义来作为后面类的参数,这一接口定义来通道类型和通道名称。
* 通道名称是作为配置用,通道类型则决定了app会使用这一通道进行发送消息还是从中接收消息。
*
* @author: 谢飞
*/
public interface Barista {
String INPUT_CHANNEL = "input_channel";
String OUTPUT_CHANNEL = "output_channel";
//注解@Input声明了它是一个输入类型的通道,名字是Barista.INPUT_CHANNEL,也就是position3的input_channel。这一名字与上述配置app2的配置文件中position1应该一致,表明注入了一个名字叫做input_channel的通道,它的类型是input,订阅的主题是position2处声明的mydest这个主题
@Input(Barista.INPUT_CHANNEL)
SubscribableChannel loginput();
//注解@Output声明了它是一个输出类型的通道,名字是output_channel。这一名字与app1中通道名一致,表明注入了一个名字为output_channel的通道,类型是output,发布的主题名为mydest。
@Output(Barista.OUTPUT_CHANNEL)
MessageChannel logoutput();
}
3.RabbitmqSender
/**
* @author: 谢飞
*/
@Service
public class RabbitmqSender {
@Autowired
private Barista source;
// 发送消息
public String sendMessage(Object message){
try{
source.logoutput().send(MessageBuilder.withPayload(message).build());
System.out.println("发送数据:" + message);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
4.aplicación
/**
* @author 谢飞
*/
@SpringBootApplication
@EnableBinding(Barista.class)
public class ProducerApplication {
public static void main(String[] args) {
SpringApplication.run(ProducerApplication.class, args);
}
}
5. Prueba
/**
* @author: 谢飞
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestRabbitMQ {
@Autowired
private RabbitmqSender rabbitmqSender;
/**
* 发送到集群队列
*/
@Test
public void sendHelloQueue() {
rabbitmqSender.sendMessage("这是发送的消息");
}
}
Lado del consumidor
1.completo
spring:
application:
name: rabbitmq-springcloudstream-consumer
cloud:
stream:
instanceCount: 3
bindings:
input_channel: #输出 生产者
destination: exchange-1 # kafka:发布订阅模型里面的topic rabbitmq: exchange的概念(但是exchange的类型那里设置呢?)
group: queue-1 #指定相同的exchange-1和不同的queue 表示广播模式 #指定相同的exchange和相同的queue表示集群负载均衡模式
binder: rabbit_local
consumer:
concurrency: 1
rabbit:
bindings:
input_channel:
consumer:
transacted: true
txSize: 10
acknowledgeMode: MANUAL
durableSubscription: true
maxConcurrency: 20
recoveryInterval: 3000
binders:
rabbit_local:
type: rabbit
environment:
spring:
rabbitmq:
host: 10.0.0.22
port: 5672
username: xiefei
password: xiefei
virtual-host: /
2.Barista
/**
* 这里的Barista接口是定义来作为后面类的参数,这一接口定义来通道类型和通道名称。
* 通道名称是作为配置用,通道类型则决定了app会使用这一通道进行发送消息还是从中接收消息。
*
* @author: 谢飞
*/
public interface Barista {
String INPUT_CHANNEL = "input_channel";
String OUTPUT_CHANNEL = "output_channel";
//注解@Input声明了它是一个输入类型的通道,名字是Barista.INPUT_CHANNEL,也就是position3的input_channel。这一名字与上述配置app2的配置文件中position1应该一致,表明注入了一个名字叫做input_channel的通道,它的类型是input,订阅的主题是position2处声明的mydest这个主题
@Input(Barista.INPUT_CHANNEL)
SubscribableChannel loginput();
//注解@Output声明了它是一个输出类型的通道,名字是output_channel。这一名字与app1中通道名一致,表明注入了一个名字为output_channel的通道,类型是output,发布的主题名为mydest。
@Output(Barista.OUTPUT_CHANNEL)
MessageChannel logoutput();
}
3.RabbitmqReceiver
/**
* @author: 谢飞
*/
@EnableBinding(Barista.class)
@Service
public class RabbitmqReceiver {
@StreamListener(Barista.INPUT_CHANNEL)
public void receiver(Message message) {
//广播通道
//PublishSubscribeChannel psc = new PublishSubscribeChannel();
//确认通道
//RendezvousChannel rc = new RendezvousChannel();
Channel channel = (com.rabbitmq.client.Channel) message.getHeaders().get(AmqpHeaders.CHANNEL);
Long deliveryTag = (Long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
System.out.println("Input Stream 1 接受数据:" + message);
try {
channel.basicAck(deliveryTag, false);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Resumen: Lo anterior es una aplicación simple de Spring Cloud Stream que integra RabbitMQ, con demasiado código.
Dirección de código: https://gitee.com/zoo-plus/springboot-learn/tree/2.x/springboot-middleware