私はkafka 2人のブローカーと1人の飼育係がいる環境を持っています。
Kafkaへのメッセージを生成しようとしているときに、ブローカー1(リーダー1)を停止すると、クライアントはメッセージングの生成を停止し、ブローカー2がトピックとパーティションの新しいリーダーとして選出されますが、以下のエラーが表示されます。
org.Apache.kafka.common.errors.TimeoutException:60000ミリ秒後にメタデータの更新に失敗しました。
10分が経過した後、ブローカー2が新しいリーダーであるため、プロデューサーがブローカー2にデータを送信することを期待しましたが、上記の例外を指定して失敗し続けました。 lastRefreshMsとlastSuccessfullRefreshMsは同じですが、metadataExpireMsはプロデューサーの場合は300000です。
私はkafkaプロデューサー側で新しいプロデューサー実装を使用しています。
プロデューサーが開始されると、1つのブローカーにバインドされ、そのブローカーがダウンした場合、クラスター内の別のブローカーに接続しようとさえしないようです。
しかし、私の期待は、ブローカーがダウンした場合、利用可能な別のブローカーのメタデータを直接チェックして、それらにデータを送信する必要があるということです。
ところで、私のトピックは4パーティションで、レプリケーション係数は2です。意味がある場合に備えてこの情報を提供します。
構成パラメーター。
{request.timeout.ms=30000, retry.backoff.ms=100, buffer.memory=33554432, ssl.truststore.password=null, batch.size=16384, ssl.keymanager.algorithm=SunX509, receive.buffer.bytes=32768, ssl.cipher.suites=null, ssl.key.password=null, sasl.kerberos.ticket.renew.jitter=0.05, ssl.provider=null, sasl.kerberos.service.name=null, max.in.flight.requests.per.connection=5, sasl.kerberos.ticket.renew.window.factor=0.8, bootstrap.servers=[10.201.83.166:9500, 10.201.83.167:9500], client.id=rest-interface, max.request.size=1048576, acks=1, linger.ms=0, sasl.kerberos.kinit.cmd=/usr/bin/kinit, ssl.enabled.protocols=[TLSv1.2, TLSv1.1, TLSv1], metadata.fetch.timeout.ms=60000, ssl.endpoint.identification.algorithm=null, ssl.keystore.location=null, value.serializer=class org.Apache.kafka.common.serialization.ByteArraySerializer, ssl.truststore.location=null, ssl.keystore.password=null, key.serializer=class org.Apache.kafka.common.serialization.ByteArraySerializer, block.on.buffer.full=false, metrics.sample.window.ms=30000, metadata.max.age.ms=300000, security.protocol=PLAINTEXT, ssl.protocol=TLS, sasl.kerberos.min.time.before.relogin=60000, timeout.ms=30000, connections.max.idle.ms=540000, ssl.trustmanager.algorithm=PKIX, metric.reporters=[], compression.type=none, ssl.truststore.type=JKS, max.block.ms=60000, retries=0, send.buffer.bytes=131072, partitioner.class=class org.Apache.kafka.clients.producer.internals.DefaultPartitioner, reconnect.backoff.ms=50, metrics.num.samples=2, ssl.keystore.type=JKS}
使用事例:
1- BR1およびBR2のデータ生成を開始します(リーダーはBR1です)
2-BR2がデータを生成するのを停止します(細かい)
3- BR1を停止し(これは、現時点でクラスター内にアクティブな作業ブローカーがないことを意味します)、次にBR2を開始してデータを生成します(リーダーはBR2ですが失敗しました)
4-BR1生成データを開始します(リーダーはBR2のままですが、データは細かく生成されます)
5-BR2を停止します(現在、BR1がリーダーです)
6- BR1を停止します(BR1はまだリーダーです)
7- BR1生成データを開始します(メッセージは再び正常に生成されます)
プロデューサーが最新の成功したデータをBR1に送信し、その後すべてのブローカーがダウンした場合、プロデューサーは、BR2が稼働していて新しいリーダーであるにもかかわらず、BR1が再び稼働することを期待します。これは予想される動作ですか?
何時間も費やした後、私は自分の状況でkafkaの動作を理解しました。これはバグであるか、内部にある理由のためにこの方法で行う必要があるかもしれませんが、実際にはそのような実装をするだろう私はこの方法をしないだろう:)
すべてのブローカーがダウンしたときに、1つのブローカーしか起動できない場合、メッセージを正常に生成するには、これが最後にダウンしたブローカーである必要があります。
5つのブローカーがあるとしましょう。 BR1、BR2、BR3、BR4およびBR5。すべてがダウンし、最後に死んだブローカーがBR3(最後のリーダーでした)の場合、すべてのブローカーBR1、BR2、BR4、およびBR5を開始しても、BR3を開始しない限り意味がありません。
再試行回数を増やす必要があります。あなたの場合、それを> = 5に設定する必要があります。
これが、プロデューサーがクラスターに新しいリーダーがいることを知る唯一の方法です。
それ以外に、すべてのブローカーがパーティションのコピーを持っていることを確認してください。そうでなければ、あなたは新しいリーダーを得るつもりはありません。
最新のkafkaバージョンでは、ブローカーがダウンしていて、プロデューサーが使用するリーダーパーティションがある場合。プロデューサーは再試行可能な例外をキャッチするまで再試行し、プロデューサーはメタデータを更新する必要があります。新しいメタデータlessLoadNodeからフェッチできるため、新しいリーダーが更新され、プロデューサーはそこに書き込むことができます。