kafka系列7——第2章1——消息发送

 🌈hello,你好鸭,我是Ethan,西安电子科技大学大三在读,很高兴你能来阅读。

✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。
🏃人生之义,在于追求,不在成败,勤通大道。加油呀!

🔥个人主页:Ethan Yankang
🔥推荐:史上最强八股文||一分钟看完我的几百篇博客

🔥温馨提示:划到文末发现专栏彩蛋   点击这里直接传送

🔥本篇概览:详细讲解了kafka系列7——第2章1——消息发送。🌈⭕🔥


【计算机领域一切迷惑的源头都是基本概念的模糊,算法除外】


🔥   微服务全集

🔥   kafka全集

🔥   前一篇章


🌈引出

Apache的kafka是一个分布式的消息发布订阅中间件。具有高吞吐、可扩展和容错性等特点。主要用于处理大规模的流式数据

本博客从各个方面详细讲解了kafka的机制,并实际上手使用之,好好学完定会习得大功。(bushi,上一次面试就噶在kafka上了,好好对待之。)


2.1.1 Kafka Java客户端数据生产流程解析

①、首先要构造一个 ProducerRecord 对象,该对象可以声明主题 Topic、分区Partition、键 Key以及 值 Value 主题和值是必须要声明的 ,分区和键可以不用指定。
②、调用 send() 方法进行消息发送。
③、因为消息要到网络上进行传输, 所以必须进行序列化(因为网络传输的基础单位是字节 序列化器的作用就是把消息的 key[确认分区]  value对象[实际消息] 序列化成字节数组后,生产者就知道该往哪个主题和分区发送记录了
④、接下来数据传到分区器,如果之间的 ProducerRecord 对象指定了分区,那么分区器将不再做
任何事,直接把指定的分区返回;如果没有,那么分区器会根据 Key [hash运算] 来选择一个分区,选择好分区之后,生产者就知道该往哪个主题和分区发送记录了。
⑤、接着这条记录会被添加到一个记录批次里面,这个批次里所有的消息会被发送到相同的主题和
分区。会有一个独立的线程来把这些记录批次发送到相应的 Broker 上。
⑥、 Broker 成功接收到消息,表示发送成功, 返回消息的元数据 (包括 主题和分区信息以及记录在
分区里的偏移量 )。发送失败,可以选择重试或者直接抛出异常。


2.1.2 发送源码

package com.itheima.kafka.chapter1;
 
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
 
import java.util.Properties;
 
public class ProducerFastStart {
//    kafka集群地址
    public static final String brokerList= "192.168.137.128:9092";
//    主题名称,之前在控制台创建了
    public static final String topic="heima";
 
    public static void main(String[] args) {
/*        注意这里的properties是线程安全的Map类 */
//        一般设置生产者的时候,直接使用properties来设置属性
        Properties properties = new Properties();
        /* 设置key序列化器 */
//       kafka提供了封装类
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
 
        // 设置重试次数
        properties.put(ProducerConfig.RETRIES_CONFIG, 10);

        // 设置值序列化器
        properties.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

        // 设置集群地址
        properties.put("bootstrap.servers", brokerList);

        // KafkaProducer 线程安全
        KafkaProducer<String, String> producer = new KafkaProducer<>(properties);
        ProducerRecord<String, String> record = new ProducerRecord<>(topic, "Kafka-demo-001", "hello, Kafka!");
        try {
            producer.send(record);
            //RecordMetadata recordMetadata = producer.send(record).get();
            //System.out.println("part:" + recordMetadata.partition() + ";topic:" + recordMetadata.topic());
        } catch (Exception e) {
            e.printStackTrace();
        }
        producer.close();
    }
}
 

2.1.3 发送类型

发送即忘记
producer.send(record)
同步发送
//通过send()发送完消息后返回一个Future对象,然后调用Future对象的get()方法等待kafka响应
//如果kafka正常响应,返回一个RecordMetadata对象,该对象存储消息的偏移量
// 如果kafka发生错误,无法正常响应,就会抛出异常,我们便可以进行异常处理
producer.send(record).get();

异步发送
producer.send(record, new Callback() {
public void onCompletion(RecordMetadata metadata, Exception exception) {
if (exception == null) {
System.out.println(metadata.partition() + ":" + metadata.offset());
}
}
});


2.1.4 序列化器

        消息要到网络上进行传输,必须进行序列化,而序列化器的作用就是如此。
Kafka 提供了默认的字符串序列化器( org.apache.kafka.common.serialization.StringSerializer ),
还有整型( IntegerSerializer )和字节数组( BytesSerializer )序列化器,这些序列化器都实现了接口
(org.apache.kafka.common.serialization.Serializer)基本上能够满足大部分场景的需求。


2.1.5 自定义序列化器

可以自己自定义,这里先放下,直接使用kafak的默认的就好了


2.1.6 分区器

本身 kafka 有自己的分区策略的,如果未指定,就会 使用默认的分区策略:
Kafka 根据传递消息的 key 来进行分区的分配,即 hash(key) % numPartitions 。如果 Key 相同的话,那么 就会分配到统一分区。


2.1.7 拦截器

Producer 拦截器 (interceptor) 是个相当新的功能,它和 consumer interceptor 是在 Kafka 0.10 版本被 引入的,主要用于实现clients 端的定制化控制逻辑。
生产者拦截器可以用在消息发送前做一些准备工作。
使用场景
1、按照某个规则过滤掉不符合要求的消息
2、修改消息的内容
3、统计类需求

 

import org.apache.kafka.clients.producer.ProducerInterceptor;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;

import java.util.Map;

/**
 * 自定义拦截器
 */
public class ProducerInterceptorPrefix implements ProducerInterceptor<String, String> {
    private volatile long sendSuccess = 0;
    private volatile long sendFailure = 0;

    @Override
    public ProducerRecord<String, String> onSend(ProducerRecord<String, String> record) {
        // 修改消息的 value,添加前缀
        String modifiedValue = "prefix1-" + record.value();
        return new ProducerRecord<>(record.topic(),
                record.partition(), record.timestamp(),
                record.key(), modifiedValue, record.headers());
        
        // 这里你可以对消息的 value 做一些额外的校验或操作
        // 如果 value 长度小于 5,可以抛出异常
        // if (record.value().length() < 5) {
        //     throw new RuntimeException("Message value is too short");
        // }
        
        // return record; // 这里默认返回原始记录,如果没有修改
    }

    @Override
    public void onAcknowledgement(RecordMetadata recordMetadata, Exception e) {
        if (e == null) {
            sendSuccess++;
        } else {
            sendFailure++;
        }
    }

    @Override
    public void close() {
        double successRatio = (double) sendSuccess / (sendFailure + sendSuccess);
        System.out.println("[INFO] 发送成功率=" + String.format("%f", successRatio * 100) + "%");
    }

    @Override
    public void configure(Map<String, ?> configs) {
        // 可以在这里读取自定义配置
    }
}

实现自定义拦截器之后需要在配置参数中指定这个拦截器,此参数的默认值为空,如下:
// 自定义拦截器使用
props.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG,ProducerDefineSerializer.cla
ss.getName());

效果演示: 



💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖

热门专栏推荐

🌈🌈计算机科学入门系列                     关注走一波💕💕

🌈🌈CSAPP深入理解计算机原理        关注走一波💕💕

🌈🌈微服务项目之黑马头条                 关注走一波💕💕

🌈🌈redis深度项目之黑马点评            关注走一波💕💕

🌈🌈JAVA面试八股文系列专栏           关注走一波💕💕

🌈🌈JAVA基础试题集精讲                  关注走一波💕💕   

🌈🌈代码随想录精讲200题                  关注走一波💕💕


总栏

🌈🌈JAVA基础要夯牢                         关注走一波💕💕  

🌈🌈​​​​​​JAVA后端技术栈                          关注走一波💕💕  

🌈🌈JAVA面试八股文​​​​​​                          关注走一波💕💕  

🌈🌈JAVA项目(含源码深度剖析)    关注走一波💕💕  

🌈🌈计算机四件套                               关注走一波💕💕  

🌈🌈数据结构与算法                           ​关注走一波💕💕  

🌈🌈必知必会工具集                           关注走一波💕💕

🌈🌈书籍网课笔记汇总                       关注走一波💕💕         



📣非常感谢你阅读到这里,如果这篇文章对你有帮助,希望能留下你的点赞👍 关注❤收藏✅ 评论💬,大佬三连必回哦!thanks!!!
📚愿大家都能学有所得,功不唐捐!

  • 7
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值