Java Spring云流运动绑定器-并发

Java Spring云流运动绑定器-并发,java,spring-integration,spring-cloud-stream,amazon-kinesis,cloud-foundry,Java,Spring Integration,Spring Cloud Stream,Amazon Kinesis,Cloud Foundry,我用以下组件构建了一个spring boot kinesis consumer: spring启动(版本-2.1.2.发行版) SpringCloud(版本-Greenwich.RELEASE) spring cloud stream kinesis活页夹(版本-1.1.0.发行版) 我使用带有1个碎片的运动流中的事件。这个spring boot消费者应用程序也运行在关键的Cloud Foundry平台上 在发布这个问题之前,我在本地(使用了kinesalite)和PCF(使用了kinesi

我用以下组件构建了一个spring boot kinesis consumer:

  • spring启动(版本-2.1.2.发行版)
  • SpringCloud(版本-Greenwich.RELEASE)
  • spring cloud stream kinesis活页夹(版本-1.1.0.发行版)
我使用带有1个碎片的运动流中的事件。这个spring boot消费者应用程序也运行在关键的Cloud Foundry平台上

在发布这个问题之前,我在本地(使用了kinesalite)和PCF(使用了kinesis流)尝试了这个场景。你能确认一下我的理解是否正确吗?我浏览了SpringCloudStream文档(和)。尽管文档非常详尽,但没有详细解释并发性和高可用性

假设我有3个消费者实例部署到PCF(通过在cf push期间使用的manifest.yml文件中将instances属性设置为3)

所有3个实例都具有以下属性

spring.cloud.stream.bindings..consumer.concurrency=5

spring.cloud.stream.bindings..group=我的消费者组

spring.cloud.stream.kinesis.binder.checkpoint.table=我的元数据dynamodb表

spring.cloud.stream.kinesis.binder.locks.table=我的锁dynamodb表格

假设事件由制作人按此顺序发送给kinesis

event5(流中最近的事件)-event4-event3-event2-event1(流中的第一个事件)

对于这种配置,我在下面解释了我的理解。你能证实这是否正确吗

  • 在给定的时间点,只有一个消费者实例处于活动状态,它将处理发送到kinesis流的所有事件(因为该流只有一个碎片)。只有当主实例关闭时,其他两个实例中的一个才会控制。此配置用于确保高可用性并保留消息的顺序
  • 因为PCF的实例数是在manifest.yml中设置的,所以我不必担心设置spring.cloud.stream.instanceCount或spring.cloud.stream.bindings..consumer.instanceCount属性
  • 启动/启动spring引导使用者时,5个使用者线程处于活动状态(因为并发性设置为5)。现在,按照上面解释的顺序使用事件。线程1拾取事件1。当thread1仍在积极处理event1时,另一个线程只是从流中拾取并开始处理下一个事件(thread2处理event2等等…)。虽然在这种情况下事件的顺序会保留(事件1总是在事件2之前拾取,等等……),但不能保证thread1会在线程2之前完成对事件1的处理
  • 当所有5个线程都忙于处理流中的5个事件时,如果出现新的事件(比如event6和event7),使用者必须等待线程可用。比如说,thread3已完成处理event3,而其他线程仍在忙于处理事件,thread3将拾取event6并开始处理,但由于没有可用线程,因此仍未拾取event7
  • 默认情况下,并发性设置为1。如果您的业务需求要求您在处理下一个事件之前完成第一个事件的处理,那么并发性应为1。在这种情况下,您正在降低吞吐量。一次只能使用一个事件。但是,如果吞吐量很重要,并且您希望在给定的时间点处理多个事件,那么并发性应该设置为所需的值。增加碎片数量也是一种选择,但作为消费者,如果您不能要求增加碎片数量,这是实现并行性/吞吐量的最佳选择

  • 请参见
    kinesismsessagedrivenchanneladapter
    中的
    concurrency
    选项JavaDocs:

    /**
     * The maximum number of concurrent {@link ConsumerInvoker}s running.
     * The {@link ShardConsumer}s are evenly distributed between {@link ConsumerInvoker}s.
     * Messages from within the same shard will be processed sequentially.
     * In other words each shard is tied with the particular thread.
     * By default the concurrency is unlimited and shard
     * is processed in the {@link #consumerExecutor} directly.
     * @param concurrency the concurrency maximum number
     */
    public void setConcurrency(int concurrency) {
    
    因此,由于在一个流中只有一个shard,因此只有一个活动线程在单个shard上迭代
    ShardIterator
    s

    关键是,我们总是必须在单个线程中处理来自单个碎片的记录。通过这种方式,我们保证了正确的顺序,并且对最高的序列号执行了检查点


    请进一步调查什么是AWS运动以及它是如何工作的。

    感谢您的回复。当kinesis流有1个碎片时,将使用者并发性设置为大于1的值有什么意义?没有什么?另外,如果instanceCount是一个PCF应用程序,并且实例数设置在清单级别,您能告诉我我是否应该担心它吗?只要这三个实例都使用相同的使用者组名称、检查点表和锁表,我就可以从高可用性角度进行设置,对吗?是的,如果您只使用一个碎片,则会忽略并发性。在PCF上使用
    instanceCount
    的情况下,正如您所注意到的,它只对高可用性有意义,仅此而已。当您有多个碎片或使用多个流进行消费时,
    并发性
    开始发挥作用。谢谢Artem。这回答了我所有的问题。从AWS Kinesis的角度来看,我知道只有当您有超过1个碎片时,才能实现并行性或高吞吐量。活页夹中的并发属性让我有点不舒服。它给了我一个错误的假设,即多个线程将并行处理单个碎片,如果顺序不重要,我可以使用它。您的详细解释澄清了,对我来说,并发性没有任何意义,因为我有一个碎片。无论如何,我需要HA,我知道它与并发无关。我将在清单级别设置实例并删除并发性。这是一个计划!看来是时候接受这个答案了:是的。再次感谢