[英]How to handle kafka publishing failure in robust way
我正在使用 Kafka,我們有一個用例來構建一個容錯系統,其中一條消息都不應該被遺漏。 所以這里的問題是:如果由於任何原因(ZooKeeper 關閉、Kafka 代理關閉等)發布到 Kafka 失敗,我們如何穩健地處理這些消息並在事情再次恢復后重播它們。 再次正如我所說,我們甚至無法承受一條消息失敗。 另一個用例是我們還需要在任何給定的時間點知道有多少消息由於任何原因而未能發布到 Kafka,例如計數器功能之類的東西,現在這些消息需要再次重新發布。
解決方案之一是將這些消息推送到某個數據庫(例如 Cassandra,其中寫入速度非常快,但我們也需要計數器功能,我猜 Cassandra 計數器功能不是那么好,我們不想使用它。)它可以處理那種負載,還為我們提供了非常准確的計數器設施。
這個問題更多是從架構的角度來看,然后是使用哪種技術來實現這一點。
PS:我們處理一些像 3000TPS 的地方。 因此,當系統開始失敗時,這些失敗的消息會在很短的時間內快速增長。 我們正在使用基於 Java 的框架。
感謝您的幫助!
Kafka采用分布式、容錯的方式構建的原因是為了處理和你一樣的問題,核心組件的多個故障應該避免服務中斷。 為避免 Zookeeper 宕機,請至少部署 3 個 Zookeeper 實例(如果在 AWS 中,請跨可用區部署它們)。 為避免代理失敗,請部署多個代理,並確保在生產者bootstrap.servers
屬性中指定多個代理。 為確保 Kafka 集群以持久的方式寫入您的消息,請確保在生產者中設置acks=all
屬性。 當所有同步副本確認接收到消息(以吞吐量為代價)時,這將確認客戶端寫入。 您還可以設置排隊限制以確保如果寫入代理開始備份,您可以捕獲異常並處理它並可能重試。
使用 Cassandra(另一個經過深思熟慮的分布式容錯系統)來“暫存”您的寫入似乎並沒有為您的架構增加任何可靠性,但確實增加了復雜性,而且 Cassandra 沒有被編寫為消息隊列消息隊列,我會避免這種情況。
正確配置后,Kafka 應該可用於處理您的所有消息寫入並提供適當的保證。
我參加聚會超級遲到。 但我發現上面的答案中缺少一些東西:)
選擇像 Cassandra 這樣的分布式系統的策略是一個不錯的主意。 一旦Kafka啟動並正常,您可以重試寫入其中的所有消息。
我想從“知道有多少消息在給定時間發布失敗”來回答
從標簽中,我看到您正在使用apache-kafka
和kafka-consumer-api
。您可以為您的生產者編寫一個自定義回調,這個回調可以告訴您消息是失敗還是成功發布。 失敗時,記錄消息的元數據。
現在,您可以使用日志分析工具來分析您的故障。 Splunk 就是這樣一種不錯的工具。
下面是一個小代碼片段,可以更好地解釋我正在談論的回調:
public class ProduceToKafka {
private ProducerRecord<String, String> message = null;
// TracerBulletProducer class has producer properties
private KafkaProducer<String, String> myProducer = TracerBulletProducer
.createProducer();
public void publishMessage(String string) {
ProducerRecord<String, String> message = new ProducerRecord<>(
"topicName", string);
myProducer.send(message, new MyCallback(message.key(), message.value()));
}
class MyCallback implements Callback {
private final String key;
private final String value;
public MyCallback(String key, String value) {
this.key = key;
this.value = value;
}
@Override
public void onCompletion(RecordMetadata metadata, Exception exception) {
if (exception == null) {
log.info("--------> All good !!");
} else {
log.info("--------> not so good !!");
log.info(metadata.toString());
log.info("" + metadata.serializedValueSize());
log.info(exception.getMessage());
}
}
}
}
如果你分析"--------> not so good !!"
每個時間單位的日志,您可以獲得所需的見解。
神速!
Chris 已經講過如何保持系統容錯。
Kafka 默認支持at-least once
消息傳遞語義,這意味着當它嘗試發送消息時,它會嘗試重新發送它。
當您創建Kafka Producer
屬性時,您可以通過將retries
選項設置為大於 0 來進行配置。
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:4242");
props.put("acks", "all");
props.put("retries", 0);
props.put("batch.size", 16384);
props.put("linger.ms", 1);
props.put("buffer.memory", 33554432);
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
Producer<String, String> producer = new KafkaProducer<>(props);
有關更多信息,請檢查此。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.