๋๊ท๋ชจ ์์คํ
- ๋ฐฉ๋ํ ์์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ณ ์๋ง์ ์ฌ์ฉ์์ ์์ฒญ์ ๋์์ ์ฒ๋ฆฌํ ์ ์๋ ์์คํ
- RabbitMQ, Kafka์ ๊ฐ์ ๋ฉ์์ง ์์คํ ์ ํ์ฉํ์ฌ ๊ฐ ์๋น์ค๊ฐ์ ํจ์จ์ ์ธ ๋ฐ์ดํฐ ํต์ ๊ณผ ํ์ฅ์ฑ ๋ณด์ฅ
๋ฉ์์ง ์์คํ
- Queue ํํ๋ก ๋ฉ์์ง ์ ์ฅ
- Producer๊ฐ ์ ์กํ๊ณ ์ ํ๋ ๋ฉ์์ง๋ฅผ ํ์ ๋ฃ์ผ๋ฉด Consumer๋ ์์ ์ ์๋์ ๋ง์ถฐ Queue์์ ๋ฉ์์ง ์ฒ๋ฆฌ
- Message Broker๋ฅผ ์ฌ์ด์ ๋๊ณ Producer์ Consumer๊ฐ ๊ฐ์ ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ์
๊ธฐ๋ฅ
- ๋น๋๊ธฐ ์ฒ๋ฆฌ
- Producer๊ฐ ๋ฉ์์ง๋ฅผ ๋ฐํํ ํ consumer๊ฐ ๋ฉ์์ง๋ฅผ ์ฒ๋ฆฌํ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์์๋ ๋จ
- ๋ฐ์ดํฐ ์์ค ๋ฐฉ์ง
- ๋ฐ์ดํฐ๋ฅผ ๋ฉ์์ง ํ์ ์์ ํ๊ฒ ๋ณด๊ด
- ๋ถํ ๋ถ์ฐ
- ์ฌ๋ฌ consumer๊ฐ ํ์ ๋ฉ์ธ์ง๋ฅผ ๊ฐ์ ธ๊ฐ์ ์ฒ๋ฆฌ โ ์์คํ ์ ๋ถํ๋ฅผ ๋ถ์ฐ
- ํจ์จ์ ์ธ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๊ฐ๋ฅ
- ์ค์ผ์ผ๋ง
- ์ํ์ ํ์ฅ ์ฉ์ด
RabbitMQ vs Kafka
์ฐจ์ด์ | RabbitMQ | Kafka |
---|---|---|
์ํธ์์ฉ๋ฐฉ์ | Producer๊ฐ ๋ฉ์์ง๋ฅผ ์ ์กํ๊ณ ๋ฉ์์ง๊ฐ ์๋ํ Consumer์๊ฒ ๋์ฐฉํ๋์ง ๋ชจ๋ํฐ๋ง | Producer๋ Consumer ์๋ น ์ฌ๋ถ์ ์๊ด์์ด Queue์ ์ ์ฅ |
์ํคํ ์ณ | - ๋ณต์กํ ๋ฉ์์ง ๋ผ์ฐํ
- ๋ฉ์์ง ํ ๊ธฐ๋ฐ ์ค๊ณ - push ๋ชจ๋ธ ์ฌ์ฉ | - ๋ ๋ณต์กํ ์ํคํ
์ณ(zookeeper) - ํํฐ์ ๊ธฐ๋ฐ ์ค๊ณ (ํ๋์ ์ฃผ์ ์์ ์ฌ๋ฌ๊ฐ์ง queue๋ค์ด ๋ค์ด๊ฐ์์) - pull ๋ชจ๋ธ ์ฌ์ฉ (์ฒ๋ฆฌ ๊ฐ๋ฅํ ๋ ๊ฐ์ ธ๊ฐ๋ ๋ชจ๋ธ) |
๋ฉ์์ง ์ฒ๋ฆฌ ๋ฐฉ์ | - ์ฐ์ ์์ ๋๊ธฐ์ด ์ง์ - ์์๋๋ก ๋ฉ์์ง ์ฒ๋ฆฌ - consumer ๊ฐ ๋ฉ์์ง ์ฒ๋ฆฌ โ ๋ธ๋ก์ปค๊ฐ ํ์ธ ์๋ต (ack) ์ ์ก โ ๋ธ๋ก์ปค๊ฐ ๋๊ธฐ์ด์์ ๋ฉ์์ง ์ญ์ | - ์ฐ์ ์์ ๋๊ธฐ์ด X - ํํฐ์ ๋ด์์ ์์ ๋ณด์ฅ (offset) - ๋ฉ์์ง๋ฅผ ๋ก๊ทธ ํ์ผ์ ์ถ๊ฐ - ๋ณด์กด๊ธฐ๊ฐ์ด ๋ง๋ฃ๋ ๋๊น์ง ๋ณด๊ด |
์ฑ๋ฅ | ์ด๋น ์์ฒ๊ฐ ๋ฉ์์ง ์ฒ๋ฆฌ ์ง์ฐ์๊ฐ ์งง์ | ์ด๋น ์๋ฐฑ๋ง๊ฐ ๋ฉ์์ง ์ฒ๋ฆฌ ๋์ฉ๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ RabbitMQ์ ๋นํด ์ค์๊ฐ ์ฒ๋ฆฌ๋์ ๋จ์ด์ง (consumeํ ์ ์๋ ๋ฉ์์ง๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ๋๋ฌธ) |
rabbit MQ๊ฐ ์ง์ฐ์๊ฐ์ด ์งง์๋ฐ Kafka๊ฐ ์ฒ๋ฆฌ๋์ด ๋ง์ ์ด์ ?
rabbitMQ๋ ํ๋์ฉ ์ฒ๋ฆฌ, Kafka๋ ๋ฒํฌ๋ก ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅ โ ์ด๋น ์ฒ๋ฆฌํ ์ ์๋ ๋ฐ์ดํฐ ์์ด ๋ง์
MSA์์ ์ฐ์ด๋ ์ด์ ?
- ์๋น์ค๊ฐ ๋น๋๊ธฐ ํต์
- ๋น์ฆ๋์ค ๋ก์ง ์์์ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌํ ์ ์๋ ๋ถ๋ถ์ ๋ถ๋ฆฌํ๊ณ kafka/rabbitMQ๋ก ์ฒ๋ฆฌ โ ์ฑ๋ฅ ํฅ์
- ํ์ฅ์ฑ
- ์ฆ๊ฐํ๋ ํธ๋ํฝ์ด๋ ๋ฐ์ดํฐ ์์ ๋์ํ์ฌ ์ฑ๋ฅ์ ์ ์ง์ํค๊ฑฐ๋ ํฅ์์ํฌ ์ ์๋ ํ๊ฒฝ์ด ์ค์
- kafka โ ํํฐ์ ๋, ํด๋ฌ์คํฐ์ ๋ธ๋ก์ปค ์ถ๊ฐ
- Rabbit MQ โ ํด๋ฌ์คํฐ๋ง, ๋ถ์ฐ ํ
- ๋ฐ์ดํฐ ์ผ๊ด์ฑ, ์ ๋ขฐ์ฑ
- ๊ฐ MSA๋ ๋ ๋ฆฝ์ ์ผ๋ก ๋ฐ์ดํฐ ๊ด๋ฆฌ โ ์๋น์ค๊ฐ ๋ฐ์ดํฐ ์ผ๊ด์ฑ ์ค์
- Kafka โ ๋ก๊ทธ, ๋ฉ์์ง ์ ์ฅ ๊ธฐ๋ฅ์ผ๋ก ๋ฐ์ดํฐ ์ผ๊ด์ฑ ์ ์ง
- RabbitMQ โ ๋ฉ์์ง ๋์คํฌ์ ์ ์ฅ, ์คํจํ ๋ฉ์์ง ์ฌ์ฒ๋ฆฌ ์ง์
- ์๋น์ค ๊ฐ ๊ฒฐํฉ๋ โฌ๏ธ
- Kafka โ ์ด๋ฒคํธ ๊ธฐ๋ฐ ์์ผํฑ์ณ ์ง์, ์๋น์ค ๊ฐ ๋ ๋ฆฝ์ ๋์ ๊ฐ๋ฅ
- Rabbit MQ โ ํ ๊ธฐ๋ฐ ๋ฉ์์ง์ ํตํด ์๋น์ค ๊ฐ ๋ฉ์์ง ์ ๋ฌ
Kafka๋ฅผ MSA์ ์ ์ฉํ๊ธฐ
- Event-Driven Architecture
- ๊ฐ MSA๊ฐ ํต์ ์ ์ด๋ฒคํธ ๊ธฐ๋ฐ์ผ๋ก ์ฒ๋ฆฌ, ํต์ ์ฃผ์ฒด๋ Kafka
- ์ค์๊ฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ
- ๋๊ท๋ชจ ๋ฐ์ดํฐ ์คํธ๋ฆฌ๋ฐ ์ฒ๋ฆฌ์ ์ฉ์ด
- ํ๋ ๋ก๊ทธ, ๋ชจ๋ํฐ๋ง ๋ฐ์ดํฐ ์ค์๊ฐ ๋ถ์
- ๋ชจ๋ํฐ๋ง๊ณผ ๋ก๊น
- ์ค์ ์ง์ค์ ๋ก๊ทธ ์์ง
Event-Driven Architecture
์ฝ๋
kafka:
bootstrap-servers: localhost:9092
consumer: # TODO kafka consumer, producer์ ๋ํ ์ค์ ๊ฐ ์์ ์ ์ฌ๊ธฐ์์
group-id: ${spring.application.name}-group
auto-offset-reset: earliest
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
properties:
spring.json.trusted.packages: '*'
producer:
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
์ด๋ฒคํธ ๋ฐ์
- KafkaTemplate์ ์ฌ์ฉํด ์ด๋ฒคํธ ๋ฐ์
- ํ ํฝ๊ณผ ๋ณด๋ด๊ณ ์ ํ๋ ์ด๋ฒคํธ ๋ด์ฉ์ ๋ด์ ์ ์ก
@Service
@RequiredArgsConstructor
public class DeliveryService {
private final DeliveryRepository deliveryRepository;
private final KafkaTemplate<String, Object> kafkaTemplate; // ์๋ ์ฃผ์
@Transactional
public void createDelivery(...) {
Delivery delivery = new Delivery(...);
deliveryRepository.save(delivery);
DeliveryCreatedEvent event = new DeliveryCreatedEvent(...); //์ด๋ฒคํธ์ ํ์ํ ๊ฐ์ ๋ฃ์ด์ฃผ์ธ์
kafkaTemplate.send("delivery-created", EventSerializer.serialize(event));
}
}
์ด๋ฒคํธ ์์
- @KafkaListener๋ฅผ ์ฌ์ฉํด ๋ฉ์์ง ์์
- groupId = yml์ ์ค์ ํ group id
@Transactional
@KafkaListener(topics = "delivery-created", groupId = "notification-group")
public void handleDeliveryCreatedEvent(String message) {
DeliveryCreatedEvent event = EventSerializer.deserialize(message, DeliveryCreatedEvent.class);
// ์ด๋ฒคํธ๋ก ํด์ผํ๋ ํ ์ฒ๋ฆฌ ์งํ (๋น์ฆ๋์ค ๋ก์ง)
// e.g. ๋ฐฐ๋ฌ์๋ฃ ์ด๋ฒคํธ ๋ฐํ
}