Spring Aws Kinesis消息未按顺序使用

时间:2019-04-02 17:27:18

标签: spring-cloud-stream spring-cloud-aws spring-integration-aws

我正在以1 shrad推送100条消息。

spring:
  cloud:
    stream:
      bindings:
        myOutBound:
          destination: my-stream
          contentType: application/json

我出于测试目的而循环推送消息

@EnableBinding(MyBinder.class)
public class MyProcessor {

  @Autowired
  private MyBinder myBinder;

  public void processRollup() {
    List<MyObject> myObjects =  IntStream.range(1, 100)
        .mapToObj(Integer::valueOf)
        .map(s-> new MyObject(s))
        .collect(toList());
    myObjects.forEach(messagePayload ->{
      System.out.println(messagePayload.getId());
      myBinder.myOutBound()
          .send(MessageBuilder.withPayload(messagePayload)
              .build());
        }
    );
  }

}

我正在消费如下消息

spring:
  cloud:
    stream:
      bindings:
        RollUpInboundStream:
          group: my-consumer-group
          destination: my-stream
          content-type: application/json

消息消耗没有排序。

我错过了什么吗?

1 个答案:

答案 0 :(得分:1)

有几件事情要考虑。首先,活页夹中的生产者默认是基于KinesisMessageHandler模式的async模式,

messageHandler.setSync(producerProperties.getExtension().isSync());

因此,即使您以正确的顺序一一发送这些消息,也并不意味着它们以相同的顺序到达AWS流。

即使您以同步模式发送它们,也无法保证它们以相同的顺序在AWS上结算。

参见此处:Amazon Kinesis and guaranteed ordering

您还可以通过显式sequenceNumber在同一个分片中实现订单保证:

  

要保证严格增加排序,请串行写入分片并使用SequenceNumberForOrdering参数。

https://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutRecord.html

不幸的是,Kinesis Binder目前不支持该选项,但是我们可以通过在消息中设置显式AwsHeaders.SEQUENCE_NUMBER来克服它,然后再将其发送到活页夹的output目标中:< / p>

String sequenceNumber = messageHeaders.get(AwsHeaders.SEQUENCE_NUMBER, String.class);
    if (!StringUtils.hasText(sequenceNumber) && this.sequenceNumberExpression != null) {
        sequenceNumber = this.sequenceNumberExpression.getValue(getEvaluationContext(), message, String.class);
    }