SpringCloudStream之绑定器详解




写在前面

本节结合Spring cloud stream文档以及个人的理解,详细分析关于绑定器SPI背后的主要概念、主要组件和特定于实现细节的信息。

学习微服务最好使用容器来搭建,对于正在学习编程的小伙伴推荐买上属于自己的一台服务器,用来练练手,也顺带学习 Docker,这很重要。最近,阿里在搞活动,新用户 1C2G 只要 98 一年,我也比较了很多,还是比较划算的,我自己也入手了,可以点进来看看,对了,最便宜的一款在 【全部必抢爆款】 里面: 阿里云服务器,助力云上云!

Spring Cloud Stream提供了一个绑定器抽象,用于连接外部中间件上的物理目的地。


1. 生产者、消费者

下图展示了一般的生产者和消费者关系:

生产者和消费者关系

一个生产者是能够发送消息到通道的任何组件。通过 Binder 实现,通道能够绑定到外部的消息中间件。Binder 接口能够在 Spring Cloud Stream 包中找到:

public interface Binder<T, C extends ConsumerProperties, P extends ProducerProperties> {
    	
    	Binding<T> bindConsumer(String name, String group, T inboundBindTarget,
			C consumerProperties);
    
		Binding<T> bindProducer(String name, T outboundBindTarget, P producerProperties);
}

当调用bindProducer() 方法时,第一个参数是代理中的目的地的名称,第二个参数是生产者向其发送消息的本地通道实例,第三个参数包含要在为该通道创建的适配器中使用的属性(例如分区键表达式)。


消费者是从通道接收消息的任何组件。与生产者一样,消费者的通道可以绑定到外部消息代理。在调用bindConsumer()方法时,第一个参数是目标名称,第二个参数提供逻辑使用者组的名称。由给定目的地的使用者绑定表示的每个组接收生产者发送到该目的地的每个消息的副本(也就是说,它遵循正常的发布-订阅语义)。如果有多个消费者实例绑定了相同的组名,则这些消费者实例对消息进行负载平衡,以便每个组中只有一个消费者实例使用生产者发送的每个消息(也就是说,它遵循正常的队列语义)


2. 绑定器SPI

绑定器SPI由许多接口、开箱即用的实用程序类和发现策略组成,这些发现策略为连接外部中间件提供了可插拔的机制。

SPI的关键点是绑定器接口,它是将输入和输出连接到外部中间件的策略。

接口是支持泛型的,提供了一些扩展点:

  • 输入和输出绑定目标。从1.0版开始,只支持MessageChannel,但将来打算将其用作扩展点。

  • 扩展的使用者和生产者属性,允许特定的绑定器实现添加可以类型安全方式支持的补充属性。

典型的绑定器实现包括以下内容:

  • 实现绑定器接口的类;

  • 一个Spring @Configuration类,它创建绑定器类型的bean以及中间件连接基础设施。

  • 一个META-INF/spring.binders。在类路径中找到一个或多个绑定器定义的绑定器文件,如下例所示:

    kafka:\
    org.springframework.cloud.stream.binder.kafka.config.KafkaBinderConfiguration
    

Binder 的具体注册可以参考 BinderFactoryConfiguration 类的 binderTypeRegistry()方法

	@Bean
	public BinderTypeRegistry binderTypeRegistry(
			ConfigurableApplicationContext configurableApplicationContext) {
		Map<String, BinderType> binderTypes = new HashMap<>();
		ClassLoader classLoader = configurableApplicationContext.getClassLoader();
		// the above can never be null since it will default to
		// ClassUtils.getDefaultClassLoader(..)
		try {
			Enumeration<URL> resources = classLoader
					.getResources("META-INF/spring.binders");
			if (!Boolean.valueOf(this.selfContained)
					&& (resources == null || !resources.hasMoreElements())) {
				this.logger.debug(
						"Failed to locate 'META-INF/spring.binders' resources on the classpath."
								+ " Assuming standard boot 'META-INF/spring.factories' configuration is used");
			}
			else {
				while (resources.hasMoreElements()) {
					URL url = resources.nextElement();
					UrlResource resource = new UrlResource(url);
					for (BinderType binderType : parseBinderConfigurations(classLoader,
							resource)) {
						binderTypes.put(binderType.getDefaultName(), binderType);
					}
				}
			}

		}
		catch (IOException | ClassNotFoundException e) {
			throw new BeanCreationException("Cannot create binder factory:", e);
		}
		return new DefaultBinderTypeRegistry(binderTypes);
	}

3. 绑定器检测

Spring Cloud Stream依赖于绑定器SPI的实现来执行将通道连接到消息代理的任务。每个绑定器实现通常连接到一种类型的消息传递系统。

默认情况下,Spring Cloud Stream依赖于Spring Boot的自动配置来配置绑定过程。如果在类路径中找到一个绑定器实现,Spring Cloud Stream将自动使用它。例如,一个只绑定到RabbitMQSpring cloud stream可以添加以下依赖项:

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

参考前面描述的绑定器实现内容,我们能够在 Spring cloud stream binder rabbitMETA-INF中找到spring.binders文件:

spring.binders

rabbit:\
org.springframework.cloud.stream.binder.rabbit.config.RabbitServiceAutoConfiguration

键表示绑定器实现的一个标识名,而值是一个逗号分隔的配置类列表,每个配置类都包含且只有一个org.springframe .cloud.stream.binder.Binder类型的bean定义。

有关SPI的服务发现机制可以去百度下,个人认为,Spring 在这里的实现还是和Java原生有区别的。


4. 多绑定器

当类路径上存在多个绑定时,应用程序必须指出每个通道绑定将使用哪个绑定。

绑定器的选择可以全局执行,使用spring.cloud.stream.defaultBinder属性(例如,spring.cloud.stream.defaultBinder=rabbit),也可以单独执行,方法是在每个通道绑定上配置绑定器。例如,从Kafka读取和从RabbitMQ写入的处理器应用程序(它有分别为读写指定输入和输出的通道)可以指定以下配置:

spring.cloud.stream.bindings.input.binder=kafka
spring.cloud.stream.bindings.output.binder=rabbit

5. 连接到同类型绑定器的多个实例

默认情况下,绑定器共享应用程序的Spring引导自动配置,这样就创建了类路径上找到的每个绑定器的一个实例。如果应用程序应该连接到同一类型的多个代理,则可以指定多个绑定器配置,每个绑定器配置具有不同的环境设置。

打开显式绑定器配置将完全禁用默认绑定器配置过程。如果这样做,则必须在配置中包含所使用的所有绑定器。希望透明地使用Spring Cloud Stream的框架可以创建可以通过名称引用的绑定器配置,但是它们不会影响默认的绑定器配置。为此,绑定器配置可以将其defaultCandidate标记设置为false(例如,spring.cloud.stream.binder.<configurationName>.defaultCandidate=false)。这表示独立于缺省绑定器配置过程而存在的配置。


以下示例显示连接到两个RabbitMQ代理实例的处理器应用程序的典型配置:

spring:
  cloud:
    stream:
      bindings:
        input:
          destination: thing1
          binder: rabbit1
        output:
          destination: thing2
          binder: rabbit2
      binders:
        rabbit1:
          type: rabbit
          environment:
            spring:
              rabbitmq:
                host: <host1>
        rabbit2:
          type: rabbit
          environment:
            spring:
              rabbitmq:
                host: <host2>

特定绑定的Environment属性也可以用于任何Spring Boot属性,包括这个Spring .main.sources可用于为特定绑定添加额外配置的源,例如覆盖自动配置的bean。

environment:
    spring:
        main:
           sources: com.acme.config.MyCustomBinderConfiguration

要激活特定绑定环境的特定配置文件,使用spring.profiles.active属性:

environment:
    spring:
        profiles:
           active: myBinderProfile

6. 绑定可视化和控制

2.0 版本以来,Spring Cloud Stream 支持 Binding 通过 actuator 端点可视化和控制(我们需要添加Spring Bootwebactuator 的依赖)。

端点实现可以在Spring Cloud Streamendpoint 包下找到。该包下还有一个 channels 端点,也可以暴露该端点获取信息。

通过以下命令启用端点:management.endpoints.web.exposure.include=bindings

查看当前绑定,访问http://<host>:<port>/actuator/bindings

另外,要查看单个绑定,访问 http://<host>:<port>/actuator/bindings/<bindingName>;

还可以停止、启动、暂停和恢复单个绑定,方法是在提供JSON状态参数的同时将其提交到相同的URL,如下面的示例所示:

curl -d '{"state":"STOPPED"}' -H "Content-Type: application/json" -X POST http://<host>:<port>/actuator/bindings/myBindingName
curl -d '{"state":"STARTED"}' -H "Content-Type: application/json" -X POST http://<host>:<port>/actuator/bindings/myBindingName
curl -d '{"state":"PAUSED"}' -H "Content-Type: application/json" -X POST http://<host>:<port>/actuator/bindings/myBindingName
curl -d '{"state":"RESUMED"}' -H "Content-Type: application/json" -X POST http://<host>:<port>/actuator/bindings/myBindingName

只有当相应的绑定器及其底层技术支持它时,才会PAUSEDRESUMED工作。否则,您将在日志中看到警告消息。目前,只有Kafka binder支持暂停和恢复状态。

如果你觉得我的文章对你有所帮助,欢迎关注我的公众号。赞!我与风来
认认真真学习,做思想的产出者,而不是文字的搬运工。错误之处,还望指出!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值