kafka / / 2023. 1. 20. 09:46

Spring kafka의 concurrency는 높으면 좋은걸까?

Spring Kafka를 사용할 때 아래와 같이 concucrency라는 옵션이 있다. 이 값이 높으면 성능이 좋아질까?

@KafkaListener(
    topics = "kafka-concurrency",
    groupId = "kafka-concurrency-consumer-group",
    concurrency = "1"
)

테스트 방법

concurrency의 동작을 확인하기 위해 아래와 같은 시나리오로 테스트하였다.

  1. producer는 10개의 메시지를 동시에 보낸다.
for (int i = 0; i < 10; i++) {
  TextMessage message = new TextMessage("message " + i);
  log.info("[send] " + message.getText());
  kafkaTemplate.send("kafka-concurrency", i+"", message);
}
  1. consumer는 1개의 메시지를 1초 동안 처리한다.
@KafkaHandler
public void handle(TextMessage textMessage) {
    process(textMessage);
    log.info("processed [" + Thread.currentThread().getId() + "] " + textMessage.getText());
}

private void process(TextMessage textMessage) {
    try {
        Thread.sleep(1000); // 특정 로직이 실행된다고 가정
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
}

테스트 케이스

위의 시나리오를 concurrency의 수를 변경해보고, 또한 파티션 수에 영향이 있는지 확인하기 위해 파티션 수도 변경하면서 테스트해보았다.

  • concurrency: 1개, 3개, 10개
  • 파티션 수: 1개, 3개, 10개

case 1) 파티션 수: 1, concurrency: 1

case 2) 파티션 수: 1, concurrency: 10

case 3) 파티션 수: 3, concurrency: 1

case 4) 파티션 수: 3, concurrency: 3

case 5) 파티션 수: 3, concurrency: 10

case 1) 파티션 수: 1, concurrency: 1

위의 테스트를 실행해보았다.

2023-01-20 09:06:54.642  INFO 28966 --- [nio-8080-exec-2] com.example.MessagePublisher   : [send] message 0
2023-01-20 09:06:54.654  INFO 28966 --- [nio-8080-exec-2] com.example.MessagePublisher   : [send] message 1
2023-01-20 09:06:54.657  INFO 28966 --- [nio-8080-exec-2] com.example.MessagePublisher   : [send] message 2
2023-01-20 09:06:54.657  INFO 28966 --- [nio-8080-exec-2] com.example.MessagePublisher   : [send] message 3
2023-01-20 09:06:54.658  INFO 28966 --- [nio-8080-exec-2] com.example.MessagePublisher   : [send] message 4
2023-01-20 09:06:54.658  INFO 28966 --- [nio-8080-exec-2] com.example.MessagePublisher   : [send] message 5
2023-01-20 09:06:54.671  INFO 28966 --- [nio-8080-exec-2] com.example.MessagePublisher   : [send] message 6
2023-01-20 09:06:54.675  INFO 28966 --- [nio-8080-exec-2] com.example.MessagePublisher   : [send] message 7
2023-01-20 09:06:54.676  INFO 28966 --- [nio-8080-exec-2] com.example.MessagePublisher   : [send] message 8
2023-01-20 09:06:54.678  INFO 28966 --- [nio-8080-exec-2] com.example.MessagePublisher   : [send] message 9
2023-01-20 09:06:55.697  INFO 28966 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 0
2023-01-20 09:06:56.702  INFO 28966 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 1
2023-01-20 09:06:57.734  INFO 28966 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 2
2023-01-20 09:06:58.741  INFO 28966 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 3
2023-01-20 09:06:59.743  INFO 28966 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 4
2023-01-20 09:07:00.751  INFO 28966 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 5
2023-01-20 09:07:01.758  INFO 28966 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 6
2023-01-20 09:07:02.766  INFO 28966 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 7
2023-01-20 09:07:03.768  INFO 28966 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 8
2023-01-20 09:07:04.772  INFO 28966 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 9

10개의 메시지가 전송이 되었고 1개의 쓰레드(0-0-C-1)가 10개의 메시지를 1초 간격으로 처리하는 것을 확인할 수 있다.

총 처리시간: 10초

case 2) 파티션 수: 1, concurrency: 10

다음은 concurrency를 10으로 늘려보자. 뭔가 더 많은 쓰레드가 생성이 되어 처리가 빨라질까?

2023-01-20 09:09:10.608  INFO 28999 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 1
2023-01-20 09:09:10.609  INFO 28999 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 2
2023-01-20 09:09:10.609  INFO 28999 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 3
2023-01-20 09:09:10.609  INFO 28999 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 4
2023-01-20 09:09:10.609  INFO 28999 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 5
2023-01-20 09:09:10.610  INFO 28999 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 6
2023-01-20 09:09:10.610  INFO 28999 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 7
2023-01-20 09:09:10.610  INFO 28999 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 8
2023-01-20 09:09:10.611  INFO 28999 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 9
2023-01-20 09:09:11.706  INFO 28999 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 0
2023-01-20 09:09:12.715  INFO 28999 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 1
2023-01-20 09:09:13.717  INFO 28999 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 2
2023-01-20 09:09:14.723  INFO 28999 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 3
2023-01-20 09:09:15.726  INFO 28999 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 4
2023-01-20 09:09:16.727  INFO 28999 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 5
2023-01-20 09:09:17.731  INFO 28999 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 6
2023-01-20 09:09:18.737  INFO 28999 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 7
2023-01-20 09:09:19.741  INFO 28999 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 8
2023-01-20 09:09:20.748  INFO 28999 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 9

테스트 결과를 보면 10개의 쓰레드가 10개의 메시지를 처리할 것으로 기대했지만 실제로는 하나의 쓰레드(0-0-C-1)만이 메시지를 처리하는 것을 알 수 있다. 10개로 생성은 했지만 하나만 동작하고 나머지 쓰레드는 유휴상태가 된다. 즉, 동작은 하지 않고 리소스만 잡아먹는 쓰레드가 9개가 더 있다는 뜻이다.

여기서 생성한 토픽의 파티션 수는 1개 이므로 "즉, 1개의 컨슈머 쓰레드는 1개의 파티션에만 동작한다" 이다. 여기서 파티션 수가 1개 이므로 최대 1개의 concurrency만 사용하는 것이 좋다는 결과를 얻을 수 있다.

총 처리시간: 10초

case 3) 파티션 수: 3, concurrency: 1

그럼 파티션 수를 3으로 설정하면 어떨까?

2023-01-20 09:13:53.344  INFO 29038 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 1
2023-01-20 09:13:53.346  INFO 29038 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 2
2023-01-20 09:13:53.347  INFO 29038 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 3
2023-01-20 09:13:53.347  INFO 29038 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 4
2023-01-20 09:13:53.348  INFO 29038 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 5
2023-01-20 09:13:53.356  INFO 29038 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 6
2023-01-20 09:13:53.356  INFO 29038 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 7
2023-01-20 09:13:53.357  INFO 29038 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 8
2023-01-20 09:13:53.357  INFO 29038 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 9
2023-01-20 09:13:54.450  INFO 29038 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 0
2023-01-20 09:13:55.461  INFO 29038 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 2
2023-01-20 09:13:56.467  INFO 29038 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 3
2023-01-20 09:13:57.481  INFO 29038 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 9
2023-01-20 09:13:58.487  INFO 29038 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 4
2023-01-20 09:13:59.491  INFO 29038 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 6
2023-01-20 09:14:00.499  INFO 29038 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 1
2023-01-20 09:14:01.503  INFO 29038 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 5
2023-01-20 09:14:02.507  INFO 29038 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 7
2023-01-20 09:14:03.511  INFO 29038 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 8

1개의 쓰레드(0-0-C-1)가 3개의 파티션에 대해 1초 간격으로 메시지가 처리되는 것을 확인할 수 있다. 위의 테스트 결과와 동일하다.

총 처리시간: 10초

case 4) 파티션 수: 3, concurrency: 3

파티션 수가 3일 때 concurrency를 3으로 늘리면 쓰레드가 3개로 동작할까?

2023-01-20 09:17:02.514  INFO 29250 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 1
2023-01-20 09:17:02.517  INFO 29250 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 2
2023-01-20 09:17:02.519  INFO 29250 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 3
2023-01-20 09:17:02.520  INFO 29250 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 4
2023-01-20 09:17:02.520  INFO 29250 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 5
2023-01-20 09:17:02.520  INFO 29250 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 6
2023-01-20 09:17:02.520  INFO 29250 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 7
2023-01-20 09:17:02.521  INFO 29250 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 8
2023-01-20 09:17:02.523  INFO 29250 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 9
2023-01-20 09:17:03.667  INFO 29250 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 1
2023-01-20 09:17:03.667  INFO 29250 --- [ntainer#0-2-C-1] com.example.MessageSubscriber   : processed [33] message 0
2023-01-20 09:17:03.667  INFO 29250 --- [ntainer#0-1-C-1] com.example.MessageSubscriber   : processed [31] message 4
2023-01-20 09:17:04.677  INFO 29250 --- [ntainer#0-2-C-1] com.example.MessageSubscriber   : processed [33] message 2
2023-01-20 09:17:04.677  INFO 29250 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 5
2023-01-20 09:17:04.677  INFO 29250 --- [ntainer#0-1-C-1] com.example.MessageSubscriber   : processed [31] message 6
2023-01-20 09:17:05.684  INFO 29250 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 7
2023-01-20 09:17:05.683  INFO 29250 --- [ntainer#0-2-C-1] com.example.MessageSubscriber   : processed [33] message 3
2023-01-20 09:17:06.691  INFO 29250 --- [ntainer#0-2-C-1] com.example.MessageSubscriber   : processed [33] message 9
2023-01-20 09:17:06.691  INFO 29250 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 8

3개의 쓰레드(0-0-C-1, 0-1-C-1, 0-2-C-1)가 3개의 파티션에 대해 각 쓰레들별 1초 간격으로 메시지가 처리되는 것을 확인할 수 있다.

Case 2에서는 concurrency를 늘려도 동작하지 않았지만 파티션 수를 3개로 늘리니 concurrency도 동작하는 것을 알 수 있다.

총 처리시간: 4초

case 5) 파티션 수: 3, concurrency: 10

그럼 concurrency를 10으로 설정하면 어떨까?

2023-01-20 09:21:02.175  INFO 29298 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 1
2023-01-20 09:21:02.177  INFO 29298 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 2
2023-01-20 09:21:02.178  INFO 29298 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 3
2023-01-20 09:21:02.179  INFO 29298 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 4
2023-01-20 09:21:02.180  INFO 29298 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 5
2023-01-20 09:21:02.180  INFO 29298 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 6
2023-01-20 09:21:02.181  INFO 29298 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 7
2023-01-20 09:21:02.186  INFO 29298 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 8
2023-01-20 09:21:02.186  INFO 29298 --- [nio-8080-exec-1] com.example.MessagePublisher   : [send] message 9
2023-01-20 09:21:03.314  INFO 29298 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 1
2023-01-20 09:21:03.315  INFO 29298 --- [ntainer#0-9-C-1] com.example.MessageSubscriber   : processed [47] message 4
2023-01-20 09:21:03.315  INFO 29298 --- [ntainer#0-1-C-1] com.example.MessageSubscriber   : processed [31] message 0
2023-01-20 09:21:04.323  INFO 29298 --- [ntainer#0-1-C-1] com.example.MessageSubscriber   : processed [31] message 2
2023-01-20 09:21:04.323  INFO 29298 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 5
2023-01-20 09:21:04.324  INFO 29298 --- [ntainer#0-9-C-1] com.example.MessageSubscriber   : processed [47] message 6
2023-01-20 09:21:05.325  INFO 29298 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 7
2023-01-20 09:21:05.327  INFO 29298 --- [ntainer#0-1-C-1] com.example.MessageSubscriber   : processed [31] message 3
2023-01-20 09:21:06.334  INFO 29298 --- [ntainer#0-0-C-1] com.example.MessageSubscriber   : processed [29] message 8
2023-01-20 09:21:06.337  INFO 29298 --- [ntainer#0-1-C-1] com.example.MessageSubscriber   : processed [31] message 9

3개의 쓰레드(0-0-C-1, 0-9-C-1-1, 0-1-C-1)가 3개의 파티션에 대해 각 쓰레들별 1초 간격으로 메시지가 처리되는 것을 확인할 수 있다.

총 처리시간: 4초

Case 4번과 동일한 결과를 나타낸다. 즉 concurrency를 3을 설정한 것과 10으로 설정한 것이 처리 속도는 동일하다는 의미이다.

결론

  • kafka의 파티션 수와 동일한 값으로 concurrency를 설정해야 최적의 성능을 낼 수 있다.
  • 컨슈머 쓰레드가 1대일 때는 concurrency를 1로 하는 것이 좋다.
  • 파티션 수 > concurrency 일 경우는 하나의 컨슈머 쓰레드가 여러 개의 파티션을 처리한다.
  • 파티션 수 < concurrency 일 경우는 파티션 수보다 많은 컨슈머 쓰레드는 유휴상태가 된다. 즉, 아무작업도 하지 않는다는 의미다.
  • 파티션 수 = concurrency 일 경우는 하나의 컨슈머 쓰레드가 하나의 파티션을 처리한다. 즉 최적의 상태라는 의미이다.
반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유