Avatar
0
Hihi Teacher
Hihi Teacher
Đa luồng với Kafka Consumer
Tks a vì câu trả lời !

Em có dùng @KafkaListener để nhận tin nhắn sau đó gửi gmail (tốn nhiều thời gian) cho user.Em dùng đa luồng cho chức năng này để giải quyết vấn đề treo thread khi xử lý trong listener (do listener mặc định có 1 thread )

Em có 2 lựa chọn :

  1. Như em nói ở trên dùng @AsyncThreadPool
  2. Cấu hình số luồng của listener thông qua setConcurrency (như bên dưới)
<span>@Bean</span>
public KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<<span>String</span>, <span>String</span>>> kafkaListenerContainerFactory() {
    ConcurrentKafkaListenerContainerFactory<<span>String</span>, <span>String</span>> <span>factory</span> = <span>new</span> ConcurrentKafkaListenerContainerFactory<>();
    <span>factory</span>.setConsumerFactory(consumerFactory());
    <span>factory</span>.setConcurrency(<span>5</span>);
    ......
}

Anh cho em hỏi 2 cách này có em nên dùng cách nào hiệu quả hơn và vì sao ạ hoặc n ếu anh có cách nào hay hơn  thì mong anh recommend cho em với ạ.

  • Answer
kafka
Remain: 5
2 Answers
Avatar
tvd12 Teacher
tvd12 Teacher
  1. Anh vẫn chưa tưởng tượng ra em dùng @Async và ThreadPool kiểu gì, nhưng theo tư duy của anh thì sẽ kiểu thế này: record sẽ được liên tục lấy ra và nhồi vào ThreadPool, như anh đã nói là nếu như việc xử lý message của em bị chậm, thì queue sẽ bị đầy, RAM sẽ liên tục tăng và giả sử server bị start thì có thể các bản ghi ở trong queue (RAM) sẽ chưa được xử lý và mất hết. Trừ khi spring đã xử lý là nếu trong queue vẫn còn record thì sẽ lấy từ kafka nữa. Thực tế thì anh cũng đang dùng cách này bởi vì mục tiêu của anh là muốn giảm tải cho kafka broker, và các consumer của anh cũng sẽ hướng đến việc xử lý I/O tương đối nhanh. Nếu có xử lý logic nặng, có lẽ anh sẽ lưu tạm dữ liệu vào DB và sau đó có luồng xử lý riêng.

  1. Em có thể nhìn vào đây và thấy rằng cái concurrency này về bản chất sẽ luôn nhỏ hơn hoặc bằng số lượng partition của 1 topic như vậy cho dù em có set lớn bao nhiêu cũng không có tác dụng gì. Anh thấy cách này cũng ổn, mỗi 1 thread sẽ care 1 partition, và nếu chưa xử lý xong record thì nó có thể chưa lấy record mới từ kafka và dữ liệu sẽ an toàn đổi lại thì kafka broker sẽ chịu áp lực rất lớn khi phải lưu giữ record.
  • 0
  • Reply
Cảm ơn anh vì câu trả lời rất chi tiết ạ !

Ví dụ : Em có 1 con Kafka hay RabbitMQ (em gọi chung là MQ) và có 1 service sẽ nhận message từ MQ đó => gửi mail.

Vấn đề:  Theo luồng thông thường thì mail service sẽ nhận từng tin nhắn một => sau đó bắt đầu  gửi mail (giả định mất 1 phút để gửi thành công) => Nếu số lượng message lớn thì các message gửi sau sẽ rất lâu mới được gửi xử lý.

=> Vì ấn đề em nêu trên nên em đưa ra cách xử lý là sẽ tận dụng cơ chế đa luồng trong Java để có thể gửi mail trên nhiều thread cùng 1 lúc (2 hướng đi của đa luồng em nghĩ ra em có nêu ở trên phần câu hỏi này) => vì việc gửi mail mỗi thread là xử lý riêng biệt nên không ảnh hưởng, liên quan đến nhau  => cách này em thấy oke.
  1. Vấn đề ở trên em nghĩ là trên thực tế các project sẽ phải gặp thì hướng giải quyết người ta sẽ là như thế nào ạ ?
  2. Có phải tư dưy của người ta là sẽ config đa luồng như em đã làm hay không ?
  3. Hay thêm 1 con Consumer mới ở 1 server khác (chung group_id với Consumer ban đầu ) để 2 các Consumer này cùng xử lý việc gửi mail.Hay bất cứ 1 cách nào khác mong anh chia sẻ.

Do em ko có nhiều kinh nghiệm nên câu hỏi có hơi loằn ngoằn xíu, mong anh thông cảm.

 –  Hihi 1664250589000
Avatar
tvd12 Teacher
tvd12 Teacher
  1. Như dự án anh làm thực tế thì anh sẽ lưu mail vào trong db trước, để lấy nhanh mail và giải phóng tài nguyên cho kafka broker (thực tế có những dự án anh còn chẳng dùng kafka cho đơn giản). Sau đó anh sẽ có 1 thread lấy mail ra và dùng kiểu này để gửi mail:

mails.parallelStream().forEach(sendMail);

public void sendMail(mail) {
  try {
    send mail
  } catch(e) {
   lưu lại mail lỗi để retry sau
  }
}

  1. Mỗi người có 1 cách suy nghĩ khác nhau, nhưng anh thấy là sẽ có người tư duy như em thôi, tuỳ thuộc vào bài toán thực tế.

  1. Thực tế sinh ra nhiều consumer để cùng làm 1 nhiệm vụ là gửi mail cũng không phải là 1 thiết kế tốt, vì như anh nói, khi mail lỗi, thì việc xử lý sẽ phức tạp, trong khi đó gửi mail đơn thuần là I/O vậy nên nhiều consumer chưa chắc đã nhanh hơn 1 consumer em ạ.
  • 0
  • Reply
Wow.Cảm ơn những chia sẻ của anh, đối với em thì nó rất quý báu a ạ !.  –  Hihi 1664266054000
Ok em, tiếp tục hỏi em nhé.  –  tvd12 1664266373000