我已经建立了一个实验性的Kafka环境,其中包含3个代理和一个包含3个分区的主题。我有一个生产者和一个消费者。我想修改特定消费者的分区偏移量。我在kafka文档中读到kafka中的使用者提交/获取API可以提交特定的偏移量或获取消费者读取的最新偏移量。这是API的链接:
我已经使用下面页面中的代码编写了我的代码,以便从特定的消费者那里获取偏移量。但是,fetch API返回" -1"的值。对于请求的偏移量。这是示例代码:
https://cwiki.apache.org/confluence/display/KAFKA/Committing+and+fetching+consumer+offsets+in+Kafka
我还在第一个链接中读到"如果没有与该使用者组下的主题分区相关联的偏移量,则代理不会设置错误代码(因为它实际上不是错误) ,但返回空元数据并将偏移字段设置为-1。"
但是我已经生成了一些消息,我的消费者已经消费了消息并输出了每条读取消息的偏移量。
如果有人能帮忙解决这个问题我真的很感激。我想知道我的代码的哪一部分是错的。或者API可能有问题。请不要犹豫,发表任何有用的评论。我的代码与我提供的链接中的代码完全一样。但是,如果您需要查看我的代码,请告诉我将其放在此处。
kafka版本为0.10.2.0
我的卡夫卡的配置是:
经纪人1:港口9093
经纪人2:港口9094
经纪人3:港口9095
主题:" testpic3"
......................
消费者配置:
props.put("group.id", "test");
props.put("client.id", "MyConsumer");
................
这是我的代码:
public class KafkaOffsetManage {
public static void main(String[] args) {
BlockingChannel channel = new BlockingChannel("localhost", 9095,
BlockingChannel.UseDefaultBufferSize(),
BlockingChannel.UseDefaultBufferSize(),
5000 /* read timeout in millis */);
channel.connect();
final String MY_GROUP = "test";
final String MY_CLIENTID = "MyConsumer";
int correlationId = 0;
final TopicAndPartition testPartition0 = new TopicAndPartition("testpic3",0);
final TopicAndPartition testPartition1 = new TopicAndPartition("testpic3",1);
final TopicAndPartition testPartition2 = new TopicAndPartition("testpic3",2);
channel.send(new ConsumerMetadataRequest(MY_GROUP, ConsumerMetadataRequest.CurrentVersion(), correlationId++, MY_CLIENTID));
ConsumerMetadataResponse metadataResponse = ConsumerMetadataResponse.readFrom(channel.receive().buffer());
System.out.println("+++++++++++++++++++++++++++");
System.out.println(metadataResponse.errorCode());
if (metadataResponse.errorCode() == ErrorMapping.NoError()) {
Broker offsetManager = metadataResponse.coordinator();
// if the coordinator is different, from the above channel's host then reconnect
channel.disconnect();
channel = new BlockingChannel(offsetManager.host(), offsetManager.port(),
BlockingChannel.UseDefaultBufferSize(),
BlockingChannel.UseDefaultBufferSize(),
5000 /* read timeout in millis */);
channel.connect();
System.out.println("Connected to Offset Manager");
System.out.println(offsetManager.host() + ", Port:"+ offsetManager.port());
} else {
// retry (after backoff)
}
// How to fetch offsets
List<TopicAndPartition> partitions = new ArrayList<TopicAndPartition>();
partitions.add(testPartition0);
//partitions.add(testPartition1);
OffsetFetchRequest fetchRequest = new OffsetFetchRequest(
MY_GROUP,
partitions,
(short) 2 /* version */, // version 1 and above fetch from Kafka, version 0 fetches from ZooKeeper
correlationId,
MY_CLIENTID);
try {
channel.send(fetchRequest.underlying());
OffsetFetchResponse fetchResponse = OffsetFetchResponse.readFrom(channel.receive().buffer());
OffsetMetadataAndError result = fetchResponse.offsets().get(testPartition0);
short offsetFetchErrorCode = result.error();
if (offsetFetchErrorCode == ErrorMapping.NotCoordinatorForConsumerCode()) {
channel.disconnect();
// Go to step 1 and retry the offset fetch
} else if (offsetFetchErrorCode == ErrorMapping.OffsetsLoadInProgressCode()) {
// retry the offset fetch (after backoff)
} else {
long retrievedOffset = result.offset();
String retrievedMetadata = result.metadata();
System.out.println("The retrieved offset is:"+ Long.toString(retrievedOffset));
System.out.println(retrievedMetadata);
System.out.println(result.toString());
}
}
catch (Exception e) {
channel.disconnect();
// Go to step 1 and then retry offset fetch after backoff
}
}
}
代码的输出在这里:
+++++++++++++++++++++++++++
0
Connected to Offset Manager
user-virtual-machine, Port:9093
------------------------
The retrieved offset is:-1
OffsetMetadataAndError[-1,,3]
Process finished with exit code 0
一个奇怪的事情是Kafka依赖。当我添加这个依赖项时,我的代码无法识别程序中的某些类:
<artifactId>kafka_2.10</artifactId>
<version>0.10.2.0</version>
类&#34; ConsumerMetadataRequest&#34;和&#34; ConsumerMetadataResponse&#34;不被承认。
所以我添加了这个依赖项:
<artifactId>kafka_2.10</artifactId>
<version>0.8.2.0</version>
谢谢,
答案 0 :(得分:1)
这种情况是由于偏移量过期而发生的。 kafka中有两个参数可控制此行为。首先是“ __consumer_offsets”主题的“ retention.ms”设置。它应等于-1以禁用该主题内的记录到期。我假设使用kafka版本1.1.x。使用以下命令检查主题配置:
$ ./kafka-configs.sh --entity-type topics \
--entity-name __consumer_offsets \
--zookeeper localhost:2181 \
--describe
Configs for topic '__consumer_offsets' are compression.type=producer,cleanup.policy=compact,min.insync.replicas=2,segment.bytes=104857600,retention.ms=-1,unclean.leader.election.enable=false
如果不符合配置设置,请使用以下命令进行更改:
$ ./kafka-configs.sh --entity-type topics \
--entity-name __consumer_offsets \
--zookeeper localhost:2181 \
--alter \
--add-config retention.ms=-1
假设设置了保留策略,接下来需要检查主题中是否有任何已提交的消息。默认情况下,kafka不允许阅读内部主题。要更改此行为,请使用使用者设置创建一个文件:
$ echo exclude.internal.topics=false > consumer.properties
之后,使用命令阅读“ __consumer_offsets”主题:
$ ./kafka-console-consumer.sh --consumer.config consumer.properties \
--from-beginning \
--topic __consumer_offsets \
--zookeeper localhost:2181 \
--formatter "kafka.coordinator.group.GroupMetadataManager\$OffsetsMessageFormatter"
如果主题中有内容,输出将如下所示:
[test_client,Test.Purposes,2]::[OffsetMetadata[13,NO_METADATA],CommitTime 1534165245681,ExpirationTime 1534251645681]
[test_client,Test.Purposes,0]::[OffsetMetadata[14,NO_METADATA],CommitTime 1534165245776,ExpirationTime 1534251645776]
[test_client,Test.Purposes,1]::[OffsetMetadata[8,NO_METADATA],CommitTime 1534165690946,ExpirationTime 1534252090946]
此处ExpirationTime值有意义。组协调器将在加载偏移量时(即now() ExpirationTime是在客户端使用公式提交偏移量时计算的: offsets.retention.minutes是代理级设置,默认情况下等于1440(24小时)。从命令输出中解码CommitTime和ExpirationTime,我们看到 恰好是24小时。 因此,不正确的偏移量问题的解决方案是增加“ offsets.retention.minutes”设置,同时要记住,当系统中存在许多无效的使用者组并且定期提交时,这会影响代理内存使用率不变的偏移量以增加到期时间。ExpirationTime = CommitTime + offsets.retention.minutes
$ date -d @1534165245
Mon Aug 13 16:00:45 UTC 2018
$ date -d @1534251645
Tue Aug 14 16:00:45 UTC 2018
答案 1 :(得分:-1)
我假设您已添加
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>0.10.2.0</version>
</dependency>
作为你的依赖。这是卡夫卡本身。消费/生产Kafka 0.10.2所需的是:
List<TopicAndPartition> partitions = new ArrayList<TopicAndPartition>();
partitions.add(testPartition0);
对于消费(和操纵给定消费者的偏移量),使用类defaultProps
它具有详细的javadoc并且比KafkaConsumer
更方便。
除此之外,如果您仍想使用您链接的示例中的代码,您可能遇到以下问题:
{{1}}
您只添加一个分区,并且在此分区上可能没有消息(您有3个分区,因此您发送的消息可能已经转到其他两个分区)。在Kafka中,每个分区都是独立的,而消费者组对每个分区都有不同的偏移量。