Làm cách nào để gửi các tin nhắn lớn với Kafka (trên 15MB)?


118

Tôi gửi tin nhắn chuỗi tới Kafka V. 0.8 bằng Java Producer API. Nếu kích thước thư khoảng 15 MB, tôi nhận được a MessageSizeTooLargeException. Tôi đã cố gắng đặt message.max.bytesthành 40 MB, nhưng tôi vẫn nhận được ngoại lệ. Các tin nhắn nhỏ hoạt động mà không có vấn đề gì.

(Ngoại lệ xuất hiện trong nhà sản xuất, tôi không có người tiêu dùng trong ứng dụng này.)

Tôi có thể làm gì để thoát khỏi ngoại lệ này?

Cấu hình nhà sản xuất mẫu của tôi

private ProducerConfig kafkaConfig() {
    Properties props = new Properties();
    props.put("metadata.broker.list", BROKERS);
    props.put("serializer.class", "kafka.serializer.StringEncoder");
    props.put("request.required.acks", "1");
    props.put("message.max.bytes", "" + 1024 * 1024 * 40);
    return new ProducerConfig(props);
}

Nhật ký lỗi:

4709 [main] WARN  kafka.producer.async.DefaultEventHandler  - Produce request with correlation id 214 failed due to [datasift,0]: kafka.common.MessageSizeTooLargeException
4869 [main] WARN  kafka.producer.async.DefaultEventHandler  - Produce request with    correlation id 217 failed due to [datasift,0]: kafka.common.MessageSizeTooLargeException
5035 [main] WARN  kafka.producer.async.DefaultEventHandler  - Produce request with   correlation id 220 failed due to [datasift,0]: kafka.common.MessageSizeTooLargeException
5198 [main] WARN  kafka.producer.async.DefaultEventHandler  - Produce request with correlation id 223 failed due to [datasift,0]: kafka.common.MessageSizeTooLargeException
5305 [main] ERROR kafka.producer.async.DefaultEventHandler  - Failed to send requests for topics datasift with correlation ids in [213,224]

kafka.common.FailedToSendMessageException: Failed to send messages after 3 tries.
at kafka.producer.async.DefaultEventHandler.handle(Unknown Source)
at kafka.producer.Producer.send(Unknown Source)
at kafka.javaapi.producer.Producer.send(Unknown Source)

5
Bản năng đầu tiên của tôi là yêu cầu bạn chia thông điệp khổng lồ này thành nhiều tin nhắn nhỏ hơn: - / Tôi đoán là điều này không thể xảy ra vì lý do nào đó nhưng bạn có thể muốn xem xét lại: Thông báo lớn thường có nghĩa là có một lỗ hổng thiết kế một nơi nào đó thực sự nên được sửa chữa.
Aaron Digulla

1
Cảm ơn, nhưng nó sẽ làm cho logic của tôi phức tạp hơn rất nhiều. Tại sao lại là một ý tưởng tồi khi sử dụng Kafka cho các tin nhắn có dung lượng khoảng 15MB? 1 MB có phải là giới hạn kích thước thư tối đa có thể được sử dụng không? Tôi không tìm thấy nhiều thông tin về giới hạn kích thước thư trong tài liệu Kafka.
Sonson123

2
Điều này hoàn toàn không liên quan đến Kafka hay bất kỳ hệ thống xử lý tin nhắn nào khác. Lý do của tôi: Nếu có vấn đề gì xảy ra với tệp 15MB của bạn, thì việc dọn dẹp đống lộn xộn sau đó sẽ rất tốn kém. Đó là lý do tại sao tôi thường chia các tệp lớn thành nhiều công việc nhỏ hơn (sau đó cũng có thể được thực hiện song song).
Aaron Digulla

bạn đã sử dụng bất kỳ nén nào chưa? bạn có thể vui lòng chia sẻ một số chi tiết, kinda của nó khó có thể đoán một cái gì đó ra khỏi chỉ là một từ duy nhất
user2720864

Câu trả lời:


181

Bạn cần điều chỉnh ba (hoặc bốn) thuộc tính:

  • Phía người tiêu dùng: fetch.message.max.bytes- điều này sẽ xác định kích thước lớn nhất của một thông điệp mà người tiêu dùng có thể lấy được.
  • Phía nhà môi giới: replica.fetch.max.bytes- điều này sẽ cho phép các bản sao trong các nhà môi giới gửi thông điệp trong cụm và đảm bảo các thông điệp được sao chép chính xác. Nếu điều này quá nhỏ, thì thông điệp sẽ không bao giờ được tái tạo và do đó, người tiêu dùng sẽ không bao giờ nhìn thấy thông điệp bởi vì thông điệp sẽ không bao giờ được cam kết (sao chép hoàn toàn).
  • Bên môi giới: message.max.bytes - đây là kích thước lớn nhất của thông điệp mà nhà môi giới có thể nhận được từ nhà sản xuất.
  • Bên môi giới (mỗi chủ đề): max.message.bytes- đây là kích thước lớn nhất của thông điệp mà nhà môi giới sẽ cho phép được thêm vào chủ đề. Kích thước này được xác nhận trước khi nén. (Mặc định là của nhà môi giới message.max.bytes.)

Tôi đã tìm ra một cách khó khăn về số 2 - bạn không nhận được BẤT KỲ ngoại lệ, tin nhắn hoặc cảnh báo nào từ Kafka, vì vậy hãy chắc chắn xem xét điều này khi bạn đang gửi tin nhắn lớn.


3
Ok, bạn và người dùng2720864 đã chính xác. Tôi đã chỉ thiết lập message.max.bytestrong mã nguồn. Nhưng tôi phải đặt các giá trị này trong cấu hình của máy chủ Kafka config/server.properties. Bây giờ các tin nhắn lớn hơn cũng hoạt động :).
Sonson123

3
Có bất kỳ nhược điểm nào đã biết khi đặt các giá trị này quá cao không?
Ivan Balashov

7
Đúng. Về phía người tiêu dùng, bạn phân bổ fetch.message.max.bytesbộ nhớ cho MỖI phân vùng. Điều này có nghĩa là nếu bạn sử dụng một số lượng lớn để fetch.message.max.byteskết hợp với một số lượng lớn các phân vùng, nó sẽ tiêu tốn rất nhiều bộ nhớ. Trên thực tế, vì quá trình sao chép giữa các nhà môi giới cũng là một người tiêu dùng chuyên biệt, điều này cũng sẽ tiêu tốn bộ nhớ của các nhà môi giới.
laughing_man

3
Lưu ý rằng cũng có một max.message.bytescấu hình cho mỗi chủ đề có thể thấp hơn cấu hình của nhà môi giới message.max.bytes.
Peter Davis

1
Theo tài liệu chính thức, các thông số về phía người tiêu dùng và những thông số liên quan đến việc sao chép giữa các nhà môi giới /.*fetch.*bytes/dường như không phải là giới hạn cứng: "Đây không phải là mức tối đa tuyệt đối, nếu [...] lớn hơn giá trị này, lô kỷ lục sẽ vẫn được trả lại để đảm bảo rằng có thể đạt được tiến độ. "
Bluu

56

Cần có những thay đổi nhỏ đối với Kafka 0.10người tiêu dùng mới so với câu trả lời của Laughing_man :

  • Người môi giới: Không có thay đổi, bạn vẫn cần tăng thuộc tính message.max.bytesreplica.fetch.max.bytes. message.max.bytesphải bằng hoặc nhỏ hơn (*) hơn replica.fetch.max.bytes.
  • Nhà sản xuất: Tăng max.request.sizeđể gửi thông điệp lớn hơn.
  • Người tiêu dùng: Tăng max.partition.fetch.bytesđể nhận được tin nhắn lớn hơn.

(*) Đọc các bình luận để tìm hiểu thêm về message.max.bytes<=replica.fetch.max.bytes


2
Bạn có biết tại sao message.max.bytescần phải nhỏ hơn replica.fetch.max.byteskhông?
Kostas

2
" replica.fetch.max.bytes (mặc định: 1MB) - Kích thước dữ liệu tối đa mà nhà môi giới có thể sao chép. Dữ liệu này phải lớn hơn message.max.bytes , nếu không nhà môi giới sẽ chấp nhận các thông báo và không thể sao chép chúng. Dẫn đến mất dữ liệu tiềm ẩn. " Nguồn: Xử lý-lớn-tin-nhắn-kafka
Sascha Vetter

2
Cảm ơn bạn đã liên hệ lại với tôi bằng một liên kết. Điều này dường như cũng lặp lại những gì mà hướng dẫn Cloudera gợi ý. Tuy nhiên, cả hai điều này đều sai - lưu ý rằng chúng không đưa ra bất kỳ lý do kỹ thuật nào về lý do tại sao replica.fetch.max.bytes phải lớn hơn message.max.bytes. Ngày hôm nay, một nhân viên của Confluent đã xác nhận điều tôi nghi ngờ: rằng trên thực tế, hai đại lượng có thể bằng nhau.
Kostas

2
Có bất kỳ cập nhật nào liên quan đến message.max.bytes<replica.fetch.max.byteshoặc message.max.bytes=replica.fetch.max.bytes@Kostas không?
Sascha Vetter

2
Có, chúng có thể ngang nhau: mail-archive.com/users@kafka.apache.org/msg25494.html (Ismael làm việc cho Confluent)
Kostas

13

Bạn cần ghi đè các thuộc tính sau:

Cấu hình nhà môi giới ($ KAFKA_HOME / config / server.properties)

  • replica.fetch.max.bytes
  • message.max.bytes

Cấu hình người tiêu dùng ($ KAFKA_HOME / config / Consumer.properties)
Bước này không phù hợp với tôi. Tôi thêm nó vào ứng dụng dành cho người tiêu dùng và nó hoạt động tốt

  • fetch.message.max.bytes

Khởi động lại máy chủ.

xem tài liệu này để biết thêm thông tin: http://kafka.apache.org/08/configuration.html


1
đối với người dùng dòng lệnh, tôi cần sử dụng cờ --fetch-size = <bytes>. Có vẻ như nó không đọc tệp Consumer.properties (kafka 0.8.1). Tôi cũng khuyên bạn nên bật tính năng nén từ phía nhà sản xuất bằng cách sử dụng tùy chọnression.codec.
Ziggy Eunicien

Nhận xét của Ziggy đã làm việc cho tôi kafka 0.8.1.1. Cảm ơn bạn!
James

có thể là fetch.message.max.bytes được thay thế bằng max.partition.fetch.bytes trong ConsumerConfig không?
s_bei

12

Ý tưởng là có kích thước thông điệp bằng nhau được gửi từ Nhà sản xuất Kafka đến Nhà môi giới Kafka và sau đó được Người tiêu dùng Kafka, tức là

Nhà sản xuất Kafka -> Kafka Broker -> Kafka Consumer

Giả sử nếu yêu cầu là gửi 15MB tin nhắn, thì Nhà sản xuất , Nhà môi giớiNgười tiêu dùng , cả ba, cần phải đồng bộ.

Kafka Producer gửi 15 MB -> Kafka Broker Allows / Stores 15 MB -> Kafka Consumer nhận 15 MB

Do đó, cài đặt phải là:

a) trên Broker:

message.max.bytes=15728640 
replica.fetch.max.bytes=15728640

b) về Người tiêu dùng:

fetch.message.max.bytes=15728640

2
có thể là fetch.message.max.bytes được thay thế bằng max.partition.fetch.bytes trong ConsumerConfig không?
s_bei

7

Một điều quan trọng cần nhớ rằng message.max.bytesthuộc tính phải đồng bộ với thuộc tính của người tiêu dùng fetch.message.max.bytes. kích thước tìm nạp ít nhất phải lớn bằng kích thước tin nhắn tối đa, nếu không có thể xảy ra trường hợp nhà sản xuất có thể gửi tin nhắn lớn hơn mức mà người tiêu dùng có thể sử dụng / tìm nạp. Nó có thể đáng để xem xét nó.
Bạn đang sử dụng phiên bản Kafka nào? Đồng thời cung cấp thêm một số dấu vết chi tiết mà bạn đang nhận được. Có điều gì đó giống như ... payload size of xxxx larger than 1000000xuất hiện trong nhật ký?


1
Tôi đã cập nhật câu hỏi của mình với nhiều thông tin hơn: Kafka Phiên bản 2.8.0-0.8.0; bây giờ tôi chỉ cần nhà sản xuất.
Sonson123

6

Câu trả lời từ @launking_man là khá chính xác. Nhưng tôi vẫn muốn đưa ra một khuyến nghị mà tôi đã học được từ chuyên gia Kafka Stephane Maarek từ Quora.

Kafka không có nghĩa là xử lý các tin nhắn lớn.

API của bạn nên sử dụng lưu trữ đám mây (Ví dụ AWS S3) và chỉ cần đẩy tới Kafka hoặc bất kỳ nhà môi giới thông báo nào một tham chiếu của S3. Bạn phải tìm một nơi nào đó để duy trì dữ liệu của mình, có thể đó là ổ đĩa mạng, có thể là bất cứ thứ gì, nhưng nó không nên là môi giới tin nhắn.

Bây giờ, nếu bạn không muốn sử dụng giải pháp trên

Kích thước tối đa của thư là 1MB (cài đặt trong nhà môi giới của bạn được gọi là message.max.bytes) Apache Kafka . Nếu bạn thực sự cần nó, bạn có thể tăng kích thước đó và đảm bảo tăng bộ đệm mạng cho nhà sản xuất và người tiêu dùng của bạn.

Và nếu bạn thực sự quan tâm đến việc tách thư của mình, hãy đảm bảo mỗi phần tách thư có cùng một khóa chính xác để nó được đẩy vào cùng một phân vùng và nội dung thư của bạn phải báo cáo một “id phần” để người tiêu dùng của bạn có thể tạo lại đầy đủ thông điệp .

Bạn cũng có thể khám phá tính năng nén, nếu tin nhắn của bạn là dạng văn bản (nén gzip, snappy, lz4) có thể làm giảm kích thước dữ liệu, nhưng không kỳ diệu.

Một lần nữa, bạn phải sử dụng một hệ thống bên ngoài để lưu trữ dữ liệu đó và chỉ cần đẩy một tham chiếu bên ngoài tới Kafka. Đó là một kiến ​​trúc rất phổ biến, và bạn nên đi theo và được chấp nhận rộng rãi.

Hãy ghi nhớ rằng Kafka chỉ hoạt động tốt nhất nếu các tin nhắn có số lượng lớn nhưng không có kích thước.

Nguồn: https://www.quora.com/How-do-I-send-Large-messages-80-MB-in-Kafka


4
Bạn có thể muốn lưu ý rằng đề xuất "của bạn" là bản sao gần như từng chữ của đề xuất Quora của Stéphane Maarek tại quora.com/How-do-I-send-Large-messages-80-MB-in-Kafka
Mike

Kafka làm việc với các tin nhắn lớn, hoàn toàn không có vấn đề. Trang giới thiệu trên trang chủ của Kafka thậm chí còn tham chiếu nó như một hệ thống lưu trữ.
calloc_org

3

Đối với những người sử dụng landoop kafka: Bạn có thể chuyển các giá trị cấu hình trong các biến môi trường như:

docker run -d --rm -p 2181:2181 -p 3030:3030 -p 8081-8083:8081-8083  -p 9581-9585:9581-9585 -p 9092:9092
 -e KAFKA_TOPIC_MAX_MESSAGE_BYTES=15728640 -e KAFKA_REPLICA_FETCH_MAX_BYTES=15728640  landoop/fast-data-dev:latest `

Và nếu bạn đang sử dụng rdkafka thì hãy chuyển message.max.bytes trong cấu hình producer như:

  const producer = new Kafka.Producer({
        'metadata.broker.list': 'localhost:9092',
        'message.max.bytes': '15728640',
        'dr_cb': true
    });

Tương tự, đối với người tiêu dùng,

  const kafkaConf = {
   "group.id": "librd-test",
   "fetch.message.max.bytes":"15728640",
   ... .. }                                                                                                                                                                                                                                                      
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.