Spring Cloud Stream

本文介绍了如何使用Spring Cloud Stream将应用程序与各种消息中间件(如Kafka、RabbitMQ)集成,包括Binder的概念、不同类型的Bindings、Consumer Groups、PartitioningSupport,以及生产消费模型的详细配置和错误处理机制。

核心概念

应用模型

应用通过Binder与消息队列绑定在一起,Binder由SpringCloud实现或第三方实现,例如:Spring Cloud Alibaba RocketMQ Binder, 你的代码通过inputs和outputs(它们都称为bindings,下文做详细介绍)与Binder相连接。
在这里插入图片描述

destination binder

与外部消息系统通信的组件,为构造 Binding提供了 2 个方法,分别是 bindConsumer 和 bindProducer ,它们分别用于构造生产者和消费者。Binder使Spring Cloud Stream应用程序可以灵活地连接到中间件,目前spring为kafka、rabbitmq提供binder。

destination binding

Binding 是连接应用程序跟消息中间件的桥梁,用于消息的消费和生产,由binder创建。

Consumer Groups

组内只有1个实例消费。如果不设置group,则stream会自动为每个实例创建匿名且独立的group——于是每个实例都会消费。
组内单次只有1个实例消费,并且会轮询负载均衡。通常,在将应用程序绑定到给定目标时,最好始终指定consumer group。
使用spring.cloud.stream.bindings.<bindingName>.group属性来指定它所属的组名称。例如下图所示的属性配置为:spring.cloud.stream.bindings.<bindingName>.group=hdfsWritespring.cloud.stream.bindings.<bindingName>.group=average
在这里插入图片描述

Partitioning Support

所有订阅同一源的消费者组都会收到同一份数据,但每个组中只有一个消费者可以接受到消息。也就是说,各个组之间不存在竞争关系,但同一个组中的消费者存在竞争关系。

一个或多个生产者将数据发送到多个消费者,并确保有共同特征标识的数据由同一个消费者处理。默认是对消息进行hashCode,然后根据分区个数取余,所以对于相同的消息,总会落到同一个消费者上。

编程模型

在这里插入图片描述

Binders

参考RocketMQ的Binder

Bindings

Bindings用来将你的代码与消息队列连接,下面例子中展示了如何接受消息并转换成大写发送消息:

@SpringBootApplication
public class SampleApplication {

	public static void main(String[] args) {
		SpringApplication.run(SampleApplication.class, args);
	}

	@Bean
	public Function<String, String> uppercase() {
	    return value -> {
	        System.out.println("Received: " + value);
	        return value.toUpperCase()
	    };
	}
}

在Spring容器中,Function (支持input和output)、Supplier(支持output)、Consumer(支持input)类型的bean都会作为消息处理器,并且为它们提过了一个约定式的binding names:
input: <functionName>-in-<index>
output: <functionName>-out-<index>
index的下标从0开始
通过 spring.cloud.stream.bindings.<bindingName>.destination=myTopic 来将它们与topic绑定。
上面的代码的配置如下:

spring.cloud.stream.bindings.uppercase-in-0.destination=my-topic

消费者拉模式名称

下面例子显示如何绑定一个拉模式的消费者,它的名称为bindingName为orders

public interface PolledBarista {

    @Input
    PollableMessageSource orders();
	. . .
}

生产消费消息

函数式生产者

@SpringBootApplication
public static class SupplierConfiguration {

	@Bean
	public Supplier<String> stringSupplier() {
		return () -> "Hello from Supplier";
	}
}

上面生产者返回一个字符串,它的bindingName为stringSupplier-out-0, 但问题是,这个方法谁调用它,多久调用一次?框架提供了一个默认的轮询机制,默认每秒触发一次,如何自定义轮询参考:Polling Configuration Properties

函数式消费者(推模式)

函数式消费者的bean类型为 Consumer 或者 Function, 它们都是推模式

拉模式消费者

也称为轮询式消费者,按需轮询PollableMessageSource ,使用spring.cloud.stream.pollable-source属性配置轮询消费者,例如:

spring.cloud.stream.pollable-source=myDestination

一个轮询消费者的例子:

@Bean
public ApplicationRunner poller(PollableMessageSource destIn, MessageChannel destOut) {
    return args -> {
        while (someCondition()) {
            try {
                if (!destIn.poll(m -> {
                    String newPayload = ((String) m.getPayload()).toUpperCase();
                    // 将消息发送到destOut
                    destOut.send(new GenericMessage<>(newPayload));
                })) {
                	// 未拉取到消息,等待1s再拉取
                    Thread.sleep(1000);
                }
            }
            catch (Exception e) {
                // handle failure
            }
        }
    };
}

一个scheduled任务bean例子:

@Scheduled(fixedDelay = 5_000)
public void poll() {
	System.out.println("Polling...");
	this.source.poll(m -> {
		System.out.println(m.getPayload());

	}, new ParameterizedTypeReference<Foo>() { });
}

PollableMessageSource.poll() 该方法结接收一个MessageHandler参数,通常是一个lambda表达式,如果接收到消息该方法返回true。
和推模式的消费者一样,如果MessageHandler抛出异常,消息会进入error channels,详细参考错误处理。
poll还有一个重载方法,如下定义:

poll(MessageHandler handler, ParameterizedTypeReference<?> type)

type允许message payload被转换为指定类型。

错误处理

当MessageHandler抛出异常,ErrorMessage就会被发送到error channels, 也就是<destination>.<group>.errors,该错误也与全局异常errorChannel桥接
你可以通过@ServiceActivator订阅error channel 去处理异常,如果没有任何订阅,该错误将会简单的打印,并认为消息成功确认。如果@ServiceActivator的方法抛出异常,该消息将会被拒绝,而不会重投。如果@ServiceActivator的方法抛出RequeueCurrentMessageException,该消息将会在broker中重新排队。如果在MessageHandler中直接抛出RequeueCurrentMessageException,该消息就像上面所说的一样,重新排队,不会进入到error channels。

参考

https://docs.spring.io/spring-cloud-stream/docs/3.1.2/reference/html/spring-cloud-stream.html
http://www.imooc.com/article/290489
https://spring-cloud-alibaba-group.github.io/github-pages/hoxton/zh-cn/index.html#_spring_cloud_alibaba_rocketmq_binder

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值