Spring Kafka를 사용할 때 아래와 같이 concucrency라는 옵션이 있다. 이 값이 높으면 성능이 좋아질까?
@KafkaListener(
topics = "kafka-concurrency",
groupId = "kafka-concurrency-consumer-group",
concurrency = "1"
)
테스트 방법
concurrency의 동작을 확인하기 위해 아래와 같은 시나리오로 테스트하였다.
- 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);
}
- 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 일 경우는 하나의 컨슈머 쓰레드가 하나의 파티션을 처리한다. 즉 최적의 상태라는 의미이다.