简体   繁体   English

EnableBinding, Output, Input deprecated since version of 3.1 of Spring Cloud Stream

[英]EnableBinding, Output, Input deprecated Since version of 3.1 of Spring Cloud Stream

Since version 3.1 the major API for working with queues is deprecated.从 3.1 版开始,主要的 API 用于处理队列已被弃用。 In the class comment it says:在 class 评论中它说:

Deprecated as of 3.1 in favor of functional programming model自 3.1 起弃用,支持函数式编程 model

I searched a lot in the web for a solution but didn't find a solid E2E explanation on how I should migrate.我在 web 中搜索了很多解决方案,但没有找到关于我应该如何迁移的可靠的 E2E 解释。

Looking for examples for:寻找以下示例:

  1. read from queue从队列中读取
  2. write to queue写入队列

If there are a few ways to do that (as I saw in web) I'd be glad for an explanation and the typical use case for each option as well.如果有几种方法可以做到这一点(正如我在网上看到的那样),我很高兴得到解释以及每个选项的典型用例。

  1. I'm assuming you are already familiar with the main concepts, and will focus on the migration.我假设您已经熟悉主要概念,并将专注于迁移。
  2. I'm using kotlin for the demo code, to reduce verbosity我使用 kotlin 作为演示代码,以减少冗长

First, some references which may help:首先,一些可能有帮助的参考资料:

  • Here is the initial relevant doc: link这是最初的相关文档: 链接
  • This is an explanation for the naming scheme in the new functional format: link这是对新功能格式中命名方案的解释: 链接
  • This is a more detailed explanation with some more advanced scenarios: link这是一些更高级的场景的更详细的解释: 链接

TL;DR TL;博士

Instead of working with annotation-based configuration, spring now uses detected beans of Consumer / Function / Supplier to define your streams for you. spring 现在不再使用基于注释的配置,而是使用检测到的Consumer / Function / Supplier bean 为您定义流。

Input/Consumer输入/消费者

Whereas before you had code looking like this:而在您的代码看起来像这样之前:

interface BindableGradesChannel {
    @Input
    fun gradesChannel(): SubscribableChannel

    companion object {
        const val INPUT = "gradesChannel"
    }
}

and the usage was similar to:用法类似于:

@Service
@EnableBinding(BindableGradesChannel::class)
class GradesListener {
    private val log = LoggerFactory.getLogger(GradesListener::class.java)
    
    @StreamListener(BindableScoresChannel.INPUT)
    fun listen(grade: Grade) {
        log.info("Received $grade")
        // do something
    }
}

now the entire definition is irrelevant, and can be done like so:现在整个定义是无关紧要的,可以这样做:

@Service
class GradesListener {
    private val log = LoggerFactory.getLogger(GradesListener::class.java)

    @Bean
    fun gradesChannel(): Consumer<Grade> {
        return Consumer { listen(grade = it) }
    }
    
    fun listen(grade: Grade) {
        log.info("Received $grade")
        // do something
    }
}

notice how the Consumer bean replaced the @StreamListener and the @Input .注意Consumer bean 是如何替换了@StreamListener@Input的。

Regarding the configuration, if before in order to configure you had an application.yml looking like so:关于配置,如果之前为了配置你有一个application.yml看起来像这样:

spring:
  cloud:
    stream:
      bindings:
        gradesChannel:
          destination: GradesExchange
          group: grades-updates
          consumer:
            concurrency: 10
            max-attempts: 3

now it should be like so:现在应该是这样的:

spring:
  cloud:
    stream:
      bindings:
        gradesChannel-in-0:
          destination: GradesExchange
          group: grades-updates
          consumer:
            concurrency: 10
            max-attempts: 3

notice how gradesChannel was replaced by gradesChannel-in-0 - to understand the full naming convention please see the naming convention link at the top.请注意gradesChannel是如何被gradesChannel-in-0替换的——要了解完整的命名约定,请查看顶部的命名约定链接。

Some details:一些细节:

  1. If you have more than one such bean in your application, you need to define the spring.cloud.function.definition property.如果您的应用程序中有多个此类 bean,则需要定义spring.cloud.function.definition属性。
  2. You have the option to give your channels custom names, so if you'd like to continue using gradesChannel you can set spring.cloud.stream.function.bindings.gradesChannel-in-0=gradesChannel and use everywhere in the configuration gradesChannel . You have the option to give your channels custom names, so if you'd like to continue using gradesChannel you can set spring.cloud.stream.function.bindings.gradesChannel-in-0=gradesChannel and use everywhere in the configuration gradesChannel .

Output/Supplier输出/供应商

The concept here is similar, you replace config and code looking like this:这里的概念是相似的,你替换配置和代码看起来像这样:

interface BindableStudentsChannel {
    @Output
    fun studentsChannel(): MessageChannel
}

and

@Service
@EnableBinding(BindableStudentsChannel::class)
class StudentsQueueWriter(private val studentsChannel: BindableStudentsChannel) {
    fun publish(message: Message<Student>) {
        studentsChannel.studentsChannel().send(message)
    }
}

can now be replaced by:现在可以替换为:

@Service
class StudentsQueueWriter {
    @Bean
    fun studentsChannel(): Supplier<Student> {
        return Supplier { Student("Adam") }
    }
}

As you can see, we have a major difference - when is it called and by who?如您所见,我们有一个主要区别 - 它何时以及由谁调用?

Before we could trigger it manually, but now it is triggered by spring, every second (by default).之前我们可以手动触发它,但现在它由 spring 触发,每秒触发一次(默认情况下)。 This is fine for use cases such as when you need to publish a sensor data every second, but this is not good when you want to send the message on an event.这对于用例来说很好,例如当您需要每秒发布传感器数据时,但是当您想要在事件上发送消息时这并不好。 Besides using Function for whatever reason, spring offers 2 alternatives:除了出于任何原因使用Function之外,spring 还提供 2 种选择:

StreamBridge - link StreamBridge - 链接

Using StreamBridge you can.使用StreamBridge可以。 define the target explicitly like so:像这样明确定义目标:

@Service
class StudentsQueueWriter(private val streamBridge: StreamBridge) {
    fun publish(message: Message<Student>) {
        streamBridge.send("studentsChannel-out-0", message)
    }
}

This way you don't define the target channel as a bean, but you can still send the message.这样您就不会将目标通道定义为 bean,但您仍然可以发送消息。 The downside is that you have some explicit configuration in your class.缺点是您在 class 中有一些明确的配置。

Reactor API - link反应堆 API - 链接

The other way is to use some kind of reactive mechanism such as EmitterProcessor , and to return it.另一种方法是使用某种反应机制,例如EmitterProcessor ,并返回它。 Using this your code will look similar to:使用它,您的代码将类似于:

@Service
class StudentsQueueWriter {
    val students: EmitterProcessor<Student> = EmitterProcessor.create()
    @Bean
    fun studentsChannel(): Supplier<Flux<Student>> {
        return Supplier { students }
    }
}

and the usage may be similar to:用法可能类似于:

class MyClass(val studentsQueueWriter: StudentsQueueWriter) {
    fun newStudent() {
        studentsQueueWriter.students.onNext(Student("Adam"))
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 StreamBridge binding 代替 EnableBinding 和 Output 注解,自 Spring Cloud Stream 3.1 版本起弃用 - StreamBridge binding instead of EnableBinding and Output annotations which are deprecated since 3.1 version of Spring Cloud Stream EnableBinding 在 Spring Cloud Stream 3.x 中被弃用 - EnableBinding is deprecated in Spring Cloud Stream 3.x 不推荐使用 EnableBinding 类型,不推荐使用 StreamListener 类型 - Spring Cloud Stream - The type EnableBinding is deprecated, The type StreamListener is deprecated - Spring Cloud Stream Spring 6: Spring 云 Stream Kafka - 替代@EnableBinding - Spring 6: Spring Cloud Stream Kafka - Replacement for @EnableBinding @EnableBinding @deprecated 自 3.1 起支持函数式编程 model - @EnableBinding @deprecated as of 3.1 in favor of functional programming model Cloud Stream 中的@EnableBinding 在后面是做什么的? - What does @EnableBinding in Cloud Stream do in the back? Spring Cloud Stream Processor单输入多行输出 - Spring Cloud Stream Processor Single Input, Multiple Row Output Spring Cloud Data Flow @EnableBinding注释中断构造函数注入 - Spring Cloud Data Flow @EnableBinding annotation breaks constructor injection 如何使用 Spring Cloud Stream 只生成一条消息而没有弃用 @Output,或者关闭轮询? - How do I produce just one message using Spring Cloud Stream w/o deprecated @Output, or turn off polling? 春云-输入与输出 - Spring cloud - Input vs Output
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM