我正在运行一个Spring Boot应用程序并且在compile('org.springframework.kafka:spring-kafka:2.1.5.RELEASE')
我正试图反对使用此版本的Cloudera安装:
Cloudera Distribution of Apache Kafka Version 3.0.0-1.3.0.0.p0.40 Version 0.11.0+kafka3.0.0+50
我的KafkaProducerConfig类非常简单:
@Configuration
public class KafkaProducerConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(KafkaProducerConfig.class);
@Value("${spring.kafka.bootstrap-servers}")
private String bootstrapServers;
@Value("${spring.kafka.template.default-topic}")
private String defaultTopicName;
@Value("${spring.kafka.producer.compression-type}")
private String producerCompressionType;
@Value("${spring.kafka.producer.client-id}")
private String producerClientId;
@Bean
public Map<String, Object> producerConfigs() {
Map<String, Object> props = new HashMap<>();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, this.bootstrapServers);
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class);
props.put(ProducerConfig.COMPRESSION_TYPE_CONFIG, this.producerCompressionType);
props.put(ProducerConfig.CLIENT_ID_CONFIG, this.producerClientId);
props.put(JsonSerializer.ADD_TYPE_INFO_HEADERS, false);
return props;
}
@Bean
public ProducerFactory<String, Pdid> producerFactory() {
return new DefaultKafkaProducerFactory<>(producerConfigs());
}
@Bean
public KafkaTemplate<String, Pdid> kafkaTemplate() {
KafkaTemplate<String, Pdid> kafkaTemplate = new KafkaTemplate<>(producerFactory());
kafkaTemplate.setDefaultTopic(this.defaultTopicName);
return kafkaTemplate;
}
@PostConstruct
public void postConstruct() {
LOGGER.info("Kafka producer configuration: " + this.producerConfigs().toString());
LOGGER.info("Kafka topic name: " + this.defaultTopicName);
}
}
当我启动应用程序时,我会收到:
2018-05-01 17:15:41.355 INFO 54674 --- [nio-9000-exec-2] o.a.kafka.common.utils.AppInfoParser : Kafka version : 1.0.1
2018-05-01 17:15:41.356 INFO 54674 --- [nio-9000-exec-2] o.a.kafka.common.utils.AppInfoParser : Kafka commitId : c0518aa65f25317e
然后,我发送有效载荷。它出现在Kafka工具中反对该主题。但是,在尝试摄取数据时,在卡夫卡方面的日志中,我收到:
[KafkaApi-131] Error when handling request {replica_id=-1,max_wait_time=500,min_bytes=1,topics=[{topic=profiles-pdid,partitions=[{partition=0,fetch_offset=7,max_bytes=1048576}]}]}java.lang.IllegalArgumentException: Magic v0 does not support record headers
at org.apache.kafka.common.record.MemoryRecordsBuilder.appendWithOffset(MemoryRecordsBuilder.java:385)
at org.apache.kafka.common.record.MemoryRecordsBuilder.append(MemoryRecordsBuilder.java:568)
at org.apache.kafka.common.record.AbstractRecords.convertRecordBatch(AbstractRecords.java:117)
at org.apache.kafka.common.record.AbstractRecords.downConvert(AbstractRecords.java:98)
at org.apache.kafka.common.record.FileRecords.downConvert(FileRecords.java:245)
at kafka.server.KafkaApis$$anonfun$kafka$server$KafkaApis$$convertedPartitionData$1$1$$anonfun$apply$5.apply(KafkaApis.scala:523)
at kafka.server.KafkaApis$$anonfun$kafka$server$KafkaApis$$convertedPartitionData$1$1$$anonfun$apply$5.apply(KafkaApis.scala:521)
at scala.Option.map(Option.scala:146)
at kafka.server.KafkaApis$$anonfun$kafka$server$KafkaApis$$convertedPartitionData$1$1.apply(KafkaApis.scala:521)
at kafka.server.KafkaApis$$anonfun$kafka$server$KafkaApis$$convertedPartitionData$1$1.apply(KafkaApis.scala:511)
at scala.Option.flatMap(Option.scala:171)
at kafka.server.KafkaApis.kafka$server$KafkaApis$$convertedPartitionData$1(KafkaApis.scala:511)
at kafka.server.KafkaApis$$anonfun$kafka$server$KafkaApis$$createResponse$2$1.apply(KafkaApis.scala:559)
at kafka.server.KafkaApis$$anonfun$kafka$server$KafkaApis$$createResponse$2$1.apply(KafkaApis.scala:558)
at scala.collection.Iterator$class.foreach(Iterator.scala:891)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1334)
at scala.collection.IterableLike$class.foreach(IterableLike.scala:72)
at scala.collection.AbstractIterable.foreach(Iterable.scala:54)
at kafka.server.KafkaApis.kafka$server$KafkaApis$$createResponse$2(KafkaApis.scala:558)
at kafka.server.KafkaApis$$anonfun$kafka$server$KafkaApis$$fetchResponseCallback$1$1.apply$mcVI$sp(KafkaApis.scala:579)
at kafka.server.ClientQuotaManager.recordAndThrottleOnQuotaViolation(ClientQuotaManager.scala:196)
at kafka.server.KafkaApis.sendResponseMaybeThrottle(KafkaApis.scala:2014)
at kafka.server.KafkaApis.kafka$server$KafkaApis$$fetchResponseCallback$1(KafkaApis.scala:578)
at kafka.server.KafkaApis$$anonfun$kafka$server$KafkaApis$$processResponseCallback$1$1.apply$mcVI$sp(KafkaApis.scala:598)
at kafka.server.ClientQuotaManager.recordAndThrottleOnQuotaViolation(ClientQuotaManager.scala:196)
at kafka.server.ClientQuotaManager.recordAndMaybeThrottle(ClientQuotaManager.scala:188)
at kafka.server.KafkaApis.kafka$server$KafkaApis$$processResponseCallback$1(KafkaApis.scala:597)
at kafka.server.KafkaApis$$anonfun$handleFetchRequest$1.apply(KafkaApis.scala:614)
at kafka.server.KafkaApis$$anonfun$handleFetchRequest$1.apply(KafkaApis.scala:614)
at kafka.server.ReplicaManager.fetchMessages(ReplicaManager.scala:639)
at kafka.server.KafkaApis.handleFetchRequest(KafkaApis.scala:606)
at kafka.server.KafkaApis.handle(KafkaApis.scala:98)
at kafka.server.KafkaRequestHandler.run(KafkaRequestHandler.scala:66)
at java.lang.Thread.run(Thread.java:748)
我在Producer应用程序端尝试了以下内容:
我希望我遗漏一些明显的东西。我需要打开/关闭任何其他标题来帮助解决任何人都知道的Magic v0问题吗?
我们有其他应用程序可以成功地在同一环境中写入其他主题,但它们是手工制作必要的Spring bean的旧应用程序。此外,这些应用程序也使用更旧的客户端(0.8.2.2),并且他们使用StringSerializer作为Producer值而不是JSON。我需要我的数据是JSON,当我们在一个应该支持0.11.x的系统上时,我真的不想降级到0.8.2.2。
答案 0 :(得分:1)
问题的解决方案是两件事的混合:
JsonSerializer.ADD_TYPE_INFO_HEADERS to false
,正如Gary Russell建议的那样。答案 1 :(得分:0)
但它们是较旧的应用程序,它们手工制作必要的Spring bean。
在org.apache.kafka.common.record.FileRecords。 downConvert (FileRecords.java:245)
我对kafka经纪人的内部人员并不熟悉,但它&#34;听起来&#34;就像主题是用旧代理创建的,他们的格式不支持头文件,而不是代理版本本身(提示:downConvert)。
您是否尝试过干净的经纪人?
只要您不尝试使用代理不支持的功能,1.0.x客户端就可以与较旧的代理进行通信(回到0.10.2.x IIRC)。您的经纪人是0.11(支持标题)的事实进一步表明它是主题记录格式的问题。
只要您使用公共功能子集,我就已经成功测试了上/下代理/客户端/主题版本没有问题。
JsonSerializer.ADD_TYPE_INFO_HEADERS为false。
这应该阻止框架设置任何标头;您需要显示您的生产者代码(以及所有配置)。
您还可以向生产者配置添加ProducerInterceptor
并检查ProducerRecord
方法中的headers
onSend()
属性,以确定设置标头的内容在输出消息中。
如果您使用的是Spring消息(template.setn(Message<?> m)
,则默认会映射标头)。使用原始template.send()
方法不会设置任何标头(除非您发送带有标头的ProducerRecord
。
答案 2 :(得分:0)
我已将应用程序升级到Spring boot 2x,并且与kafka客户端依赖项存在一些兼容性问题(请参阅Spring-boot and Spring-Kafka compatibility matrix),因此也必须对其进行升级。另一方面,我在服务器上运行了一个较旧的代理(kafka 0.10),然后无法向其发送消息。我还意识到,即使将JsonSerializer.ADD_TYPE_INFO_HEADERS
设置为false,kafka生产者也会在内部设置标头,并且由于魔术是根据kafka的版本(在RecordBatch
中固定的)进行的,因此这是不可能的以免不符合MemoryRecordsBuilder.appendWithOffset
:if (magic < RecordBatch.MAGIC_VALUE_V2 && headers != null && headers.length > 0) throw new IllegalArgumentException("Magic v" + magic + " does not support record headers");
的条件。
最后,我要解决此问题的唯一方法是升级我的kafka服务器。