SpringCloudStream中的消息分區數

一、前言

本文僅針對 Kafka 來聊消息分區數相關的話題。SpringCloudStream 中的消息分區數如何配置?或者說消息分區數會受到哪些配置的影響。

  • SpringCloudStream:Greenwich.SR2
  • Kafka:kafka_2.12-2.3.0

二、影響因素

2.1 Kafka服務端

首先應該想到的,Kafka 配置文件server.properties中默認每一個 topic 的分區數 num.partitions=1

# The default number of log partitions per topic. More partitions allow greater
num.partitions=1

2.2 生產者端

SpringCloudStream的配置中可以看到,生產者可以指定分區數,默認1:

spring.cloud.stream.bindings.<channelName>.partitionCount.producer=n

【說明】:當分區功能開啓時,使用該參數來配置消息數據的分區數。如果消息生產者已經配置了分區鍵的生成策略,那麼它的值必須大於1。

2.3 消費者端

SpringCloudStream 允許通過配置,使得消費者能夠自動創建分區。

#輸入通道消費者的併發數,默認1
spring.cloud.stream.bindings.<channelName>.consumer.concurrency=2

若想以上配置生效,還需添加如下通用配置:

#Kafka綁定器允許在需要的時候自動創建分區。默認false
spring.cloud.stream.kafka.binder.autoAddPartitions=true

消費者端如此配置以後,將表現爲一個消費者服務或進程中,會有2個線程各自消費1個分區,即2個消費者線程同時消費。

以下是該配置的效果驗證步驟:

消費者代碼:

1個 @StreamListener 消費自己的 topic 或自己的輸出channel:

@EnableBinding(SpiderSink.class)
@Slf4j
public class SpiderSinkReceiver {

    @Autowired
    private SpiderMessageService spiderMessageService;

    @StreamListener(SpiderSink.INPUT)
    public void receive(Object payload) {
        log.info("SPIDER-SINK received: {}", payload);
    }
}

方式一:通過日誌驗證:

通過在 log4j 日誌中,打印線程名稱的方式,驗證 spring.cloud.stream.bindings.<channelName>.consumer.concurrency 的配置確確實實會新增1個消費者線程。

[INFO ] 2020-05-09 01:19:34,700 [thread: [Ljava.lang.String;@5b40de43.container-1-C-1] com.cjia.spidersink.sink.SpiderSinkReceiver.receive(SpiderSinkReceiver.java:50)
[INFO ] 2020-05-09 01:19:35,888 [thread: [Ljava.lang.String;@5b40de43.container-0-C-1] com.cjia.spidersink.sink.SpiderSinkReceiver.receive(SpiderSinkReceiver.java:50)

方式二:直接查看分區數來驗證:

另外,也可在啓動一個生產者服務時,等待自動創建一個新 topic 後(此時默認分區數爲1),比如我們創建的 topic 爲“topic-spider-dev”,此時通過kafka命令查看分區數,此時分區數爲1:

[root@bi-zhaopeng01 kafka]# ./bin/kafka-topics.sh --zookeeper localhost:2181 --describe --topic topic-spider-dev
Topic:topic-spider-dev  PartitionCount:1        ReplicationFactor:1     Configs:
        Topic: topic-spider-dev Partition: 0    Leader: 1       Replicas: 1     Isr: 1

然後,配置消費者服務的 spring.cloud.stream.bindings.<channelName>.consumer.concurrency=2,啓動一個消費者服務,再次查看分區數,已經變爲2了:

[root@bi-zhaopeng01 kafka]# ./bin/kafka-topics.sh --zookeeper localhost:2181 --describe --topic topic-spider-dev
Topic:topic-spider-dev  PartitionCount:2        ReplicationFactor:1     Configs:
        Topic: topic-spider-dev Partition: 0    Leader: 1       Replicas: 1     Isr: 1
        Topic: topic-spider-dev Partition: 1    Leader: 2       Replicas: 2     Isr: 2

同時查看消費者端的應用日誌,看到2個消費者線程各自分配了一個分區:

[INFO ] 2020-05-12 17:22:43,940 [thread: [Ljava.lang.String;@299dd381.container-0-C-1] org.springframework.kafka.listener.AbstractMessageListenerContainer$1.onPartitionsAssigned(AbstractMessageListenerContainer.java:363)
partitions assigned: [topic-spider-dev-0]
[INFO ] 2020-05-12 17:22:44,004 [thread: [Ljava.lang.String;@299dd381.container-1-C-1] org.springframework.kafka.listener.AbstractMessageListenerContainer$1.onPartitionsAssigned(AbstractMessageListenerContainer.java:363)
partitions assigned: [topic-spider-dev-1]

最終,確確實實地驗證了 concurrency 配置對消費者線程數和分區數的影響。

2.4 其他因素

比如,SpringCloudStream 中 Kafka 綁定器的配置中,也有一個相關的影響因素:

#最小分區數,默認1
spring.cloud.stream.kafka.binder.minPartitionCount=n

【說明】:該參數僅在設置了 autoCreateTopics 和 autoAddPartitions 時生效,用來設置該綁定器所使用主題的全局分區最小數量。如果當生產者的 partitionCount 參數或 instanceCount * concurrency 設置大於該參數配置時,該參數值將被覆蓋。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章