美文网首页
kafka服务端0.10.2,客户端2.0 如何发送消息

kafka服务端0.10.2,客户端2.0 如何发送消息

作者: 味道_3a01 | 来源:发表于2021-06-10 10:32 被阅读0次

项目中用到kafka,应用作为生产者,发送消息时,报错:

Magic v1 does not support record headers

网上也有很多同样的博客记录这个错误,如:https://zhuanlan.zhihu.com/p/205676507

原因是 Kafka服务端和客户端的版本不兼容导致了报错;

应用环境:spring boot 版本:2.1.6.RELEASE

查看客户端kafka版本:2.2.7.RELEASE


spring-kafka-2.7.0.png

服务端版本:0.10.2


kafka-server.png

到这里确定是版本不一致导致的,如何解决呢?

方案一:

服务端升级到2.0

由于使用的是 阿里云的消息队列kafka,2.0费用比当前版本贵很多,故该方案pass

方案二:

客户端版本使用1.0的

使用原生的kafka,即自己写kafka configuration,由于我们还要消费kafka的消息,故还需要写一个监听器,用来消费消息,比较麻烦;换个思路:消费消息仍然使用 spring-kafka,发送消息使用kafka原生API

  1. maven依赖
<!--kafka-->
<dependency>
     <groupId>org.springframework.kafka</groupId>
     <artifactId>spring-kafka</artifactId>
</dependency>

没有version,查看maven依赖,发现spring boot 帮我们管理了spring-kafka的版本


spring-kafka.png

Ctrl + f 查找 spring-kafka.version,如下图:


spring-kafka-2.png
  1. KafkaConfig配置类
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;
import java.util.Properties;

/**
 * kafka 配置
 *   由于kafka服务端使用的是 0.10.2版本,而我们的框架使用的spring boot版本为2.4.5,
 *   kafka starter版本中kafka-clients版本为2.6.0;kafka客户端作为生产者发送消息
 *   时,会增加请求头,而服务端不支持,导致无法正常生产消息,故kafka作为生产者,不能直
 *   接使用boot starter,需使用kafka原生客户端
 * @author guodong.zhang
 */
@Configuration
public class KafkaConfig {

    @Value("#{'${spring.kafka.consumer.bootstrap-servers}'.split(',')}")
    private List<String> bootstrapServers;

    @Bean
    public KafkaProducer<String, String> initKafkaTemplate() {
        Properties props = new Properties();
        //设置接入点,请通过控制台获取对应Topic的接入点
        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);

        //Kafka消息的序列化方式
        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
        //请求的最长等待时间
        props.put(ProducerConfig.MAX_BLOCK_MS_CONFIG, 30 * 1000);
        //设置客户端内部重试次数
        props.put(ProducerConfig.RETRIES_CONFIG, 5);
        //设置客户端内部重试间隔
        props.put(ProducerConfig.RECONNECT_BACKOFF_MS_CONFIG, 3000);
        //构造Producer对象,注意,该对象是线程安全的,一般来说,一个进程内一个Producer对象即可;
        //如果想提高性能,可以多构造几个对象,但不要太多,最好不要超过5个
        KafkaProducer<String, String> producer = new KafkaProducer<>(props);
        return producer;
    }
}
  1. 生产消息类

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.Future;

/**
 * 生产者,推送消息至kafka
 *
 * @author guodong.zhang
 */
@Slf4j
@Component
public class MessageSenderClient {


    @Resource
    private KafkaProducer kafkaProducer;

    /**
     * 消息发送至 kafka
     *
     * @param topic 路由
     * @param data 消息内容
     */
    public void send(String topic, Object data) {
        if (StringUtils.isEmpty(topic) || data == null) {
            throw new IllegalStateException("发送消息参数不能为空");
        }
        try {
            ProducerRecord<String, String> kafkaMessage =  new ProducerRecord<>(topic, JSON.toJSONString(data));
            Future<RecordMetadata> metadataFuture = kafkaProducer.send(kafkaMessage);
            RecordMetadata recordMetadata = metadataFuture.get();
            log.info("MessageSenderClient kafka send Produce ok:{}", recordMetadata.toString());
        } catch (Exception e) {
            log.info("MessageSenderClient kafka send error,", e);
        }
    }

    /**
     * 消息发送至 kafka
     *
     * @param topic
     * @param partition 分区
     * @param data
     */
    public void send(String topic, Integer partition, Object data) {
        if (StringUtils.isEmpty(topic) || data == null) {
            throw new IllegalStateException("发送消息参数不能为空");
        }
        if (partition == null) {
            send(topic, data);
        }
        try {
            ProducerRecord<String, String> kafkaMessage =  new ProducerRecord<>(topic, partition, null, JSON.toJSONString(data));
            Future<RecordMetadata> metadataFuture = kafkaProducer.send(kafkaMessage);
            RecordMetadata recordMetadata = metadataFuture.get();
            log.info("MessageSenderClient kafka send Produce ok:{}", recordMetadata.toString());
        } catch (Exception e) {
            log.info("MessageSenderClient kafka send error,", e);
        }
    }
}
  1. 需要发送消息的地方调用该方法

    @Value("${kafka.producer.job_collection_es_topic}")
    private String topic;

    @Autowired
    private MessageSenderClient kafkaProducer;

    private void sendMsg(Object target) {
        if (target == null || ((JSONObject) target).get(BIZ_ID) == null) {
            throw new BusinessException("发送消息参数不能为空");
        }
        String bizId = ((JSONObject) target).get(BIZ_ID).toString();
        int partition = Integer.parseInt(bizId) % PARTITION_NUM;
        // 推送到kafka
        kafkaProducer.send(topic, partition, target);
    }
  1. 测试验证


    msg.png

    疑问:

kafka客户端与服务端版本需要对应,而我这里kafka-clients使用的版本是 2.0.1,却可以正常发送消息


kafka-client-2.0.1.jpg

相关文章

  • kafka服务端0.10.2,客户端2.0 如何发送消息

    项目中用到kafka,应用作为生产者,发送消息时,报错: 网上也有很多同样的博客记录这个错误,如:https://...

  • Kafka——消息的发送流程

    前言 本文将介绍kafka的一条消息的发送流程,从消息的发送到服务端的存储。上文说到kafak分为客户端与服务端,...

  • Zuul 消息推送

    Zuul 2.0 支持消息推送,例如送服务端发送消息给客户端。自持两种协议,WebSockets和Server S...

  • 08-Kafka如何实现高性能IO?

    Kafka如何实现高性能IO? 一、使用批量消息提升服务端处理能力 虽然kafka的sdk提供了单条消息发送,但实...

  • Kafka源码分析

    1 消息处理入口 以下是Kafka消息处理的入口,即客户端发送到服务端消息处理方法。 2 内存中offset信息来...

  • 基于socket的进程通信

    实现目标实现服务端与客户端的连接实现多个客户端向服务端发送消息,并由服务端将消息发送给每个客户端 涉及的Java类...

  • golang如何使用sarama访问kafka

    golang如何使用sarama访问kafka 下面一个客户端代码例子访问kafka服务器,来发送和接受消息。 使...

  • iOS字符串哈希

    应用场景 客户端向服务端发送消息 服务端收到后向客户端发送应答如果客户端超时时间内没有收到应答 则重发消息消息间需...

  • Kafka生产者:写消息到Kafka

    本章我们将会讨论Kafka生产者是如何发送消息到Kafka的。Kafka项目有一个生产者客户端,我们可以通过这个客...

  • [kafka系列]之producer端消息发送

    本小节我们来讨论Kafka生产者是如何发送消息到Kafka的, Kafka项目有一个生产者客户端,我们可以通过这个...

网友评论

      本文标题:kafka服务端0.10.2,客户端2.0 如何发送消息

      本文链接:https://www.haomeiwen.com/subject/tyzosltx.html