Java操作kafka——模拟生产者和消费者

引入Kafka依赖

本项目使用maven工程搭建需要引入以下必要依赖(必要)

        <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka-clients</artifactId>
            <version>0.11.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka-streams</artifactId>
            <version>0.11.0.0</version>
        </dependency>
  • 本人在该项目中引入的依赖(非必要)
<dependencies>
        <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka-clients</artifactId>
            <version>0.11.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka-streams</artifactId>
            <version>0.11.0.0</version>
        </dependency>
        <!-- log start -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.29</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.6</version>
        </dependency>
    </dependencies>

消费者

  1. (样式一)写入本地文件

package com.kafka.cunsumer;

import com.alibaba.fastjson.JSON;
import com.kafka.checkUtils.MessageCheck;
import com.kafka.utils.TimeUtils;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;

import java.io.*;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @author Cool.R
 * @date 2020/01/03
 * @version 1.0
 */
public class Customer02 {
    public static void main(String[] args) throws InterruptedException {
        Properties properties = new Properties();
        properties.put("bootstrap.servers", "192.168.62.53:9092");
        properties.put("group.id", "group-66");
        //session.timeout.ms:消费者在被认为死亡之前可以与服务器断开连接的时间,默认是3s 。
        properties.put("session.timeout.ms", "30000");
        //消费者是否自动提交偏移量,默认值是true,避免出现重复数据和数据丢失,可以把它设为 false。
        properties.put("enable.auto.commit", "false");
        properties.put("auto.commit.interval.ms", "1000");
        //auto.offset.reset:消费者在读取一个没有偏移量的分区或者偏移量无效的情况下的处理
        //earliest:在偏移量无效的情况下,消费者将从起始位置读取分区的记录。
        //latest:在偏移量无效的情况下,消费者将从最新位置读取分区的记录
        properties.put("auto.offset.reset", "earliest");
        properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        properties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        // max.partition.fetch.bytes:服务器从每个分区里返回给消费者的最大字节数
        //fetch.max.wait.ms:消费者等待时间,默认是500。
        // fetch.min.bytes:消费者从服务器获取记录的最小字节数。
        // client.id:该参数可以是任意的字符串,服务器会用它来识别消息的来源。
        // max.poll.records:用于控制单次调用 call () 方住能够返回的记录数量
        //receive.buffer.bytes和send.buffer.bytes:指定了 TCP socket 接收和发送数据包的缓冲区大小,默认值为-1

        KafkaConsumer<String, String> kafkaConsumer = new KafkaConsumer<>(properties);
        kafkaConsumer.subscribe(Arrays.asList("ETE_SOURCEDATA_PAASPERF"));
        /*while (true) {
            ConsumerRecords<String, String> records = kafkaConsumer.poll(100);
            for (ConsumerRecord<String, String> record : records) {
                System.out.printf("offset = %d, value = %s", record.offset(), record.value());
                System.out.println("=====================>");

            }
        }*/
        File file=new File("G:\\ETE_SOURCEDATA_PAASPERF.txt");
        ConsumerRecords<String, String> records = kafkaConsumer.poll(1000);
        try {
            FileOutputStream fout=new FileOutputStream(file);
            PrintWriter pw=new PrintWriter(fout);
            for (ConsumerRecord<String, String> record : records) {
               /* Map<String,Object> dataMap=new HashMap<>();
                List<Map<String,Object>> message=new ArrayList<>();
                dataMap.put("name", "PS.CACHE");
                dataMap.put("timestamp", TimeUtils.getTimestamp());

                Map<String, Object> sourceMap = MessageCheck.checkData(record.value());
                if (sourceMap==null){
                    System.out.println("源数据有误,请检查:"+record.value());
                    continue;
                }
                message.add(sourceMap);
                dataMap.put("message", message);
                System.out.println(dataMap.toString());
                pw.println(JSON.toJSONString(dataMap));*/
               pw.println(record.value());
            }
            fout.close();
            pw.close();
            System.out.println("写入完成!");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

  1. (样式二)只读
package com.kafka.cunsumer;

import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.consumer.ConsumerRecords;

import java.util.Arrays;
import java.util.Properties;

/**
 * @author Cool.R
 * @date 2020/01/03
 * @version 1.0
 */
public class Cunsumer01 {

    public static void main(String[] args) {
        Properties properties=new Properties();
        //指定kafka的ip和端口号
        properties.put("bootstrap.servers", "192.168.70.87:9092");
        properties.put("group.id", "jd-group336");
        properties.put("auto.commit.interval.ms", "1000");
        properties.put("auto.offset.timeout.ms", "3000");
        properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        properties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        KafkaConsumer<String,String> kafkaConsumer=new KafkaConsumer<String, String>(properties);
        //指定被消费的Topic
        kafkaConsumer.subscribe(Arrays.asList("ETE_CACHE_01"));
        while (true){
            ConsumerRecords<String,String> records = kafkaConsumer.poll(100);
            for (ConsumerRecord<String, String> record : records) {
                System.out.println("---------");
                System.out.printf("offset = %d, value = %s", record.offset(), record.value());
                System.out.println();
            }
        }
    }
}

生产者(从本地文件读入写入topic)

注意:必须先在kafka中建立相应的topic

package com.kafka.producer;

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;

import java.io.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Properties;

/**
 * @author Cool.R
 * @date 2020/01/03
 * @version 1.0
 */
public class ProducerDemo {
    public static void main(String[] args) {
        Properties properties = new Properties();
        //broker的地址清单,建议至少填写两个,避免宕机
        properties.put("bootstrap.servers", "192.168.70.87:9092");
        //acks指定必须有多少个分区副本接收消息,生产者才认为消息写入成功,用户检测数据丢失的可能性
        //acks=0:生产者在成功写入消息之前不会等待任何来自服务器的响应。无法监控数据是否发送成功,但可以以网络能够支持的最大速度发送消息,达到很高的吞吐量。
        //acks=1:只要集群的首领节点收到消息,生产者就会收到来自服务器的成功响应。
        //acks=all:只有所有参与复制的节点全部收到消息时,生产者才会收到来自服务器的成功响应。这种模式是最安全的,
        properties.put("acks", "all");
        //retries:生产者从服务器收到的错误有可能是临时性的错误的次数
        properties.put("retries", 0);
        //batch.size:该参数指定了一个批次可以使用的内存大小,按照字节数计算(而不是消息个数)。
        properties.put("batch.size", 16384);
        //linger.ms:该参数指定了生产者在发送批次之前等待更多消息加入批次的时间,增加延迟,提高吞吐量
        properties.put("linger.ms", 1);
        //buffer.memory该参数用来设置生产者内存缓冲区的大小,生产者用它缓冲要发送到服务器的消息。
        properties.put("buffer.memory", 33554432);
        //compression.type:数据压缩格式,有snappy、gzip和lz4,snappy算法比较均衡,gzip会消耗更高的cpu,但压缩比更高
        //key和value的序列化
        properties.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        properties.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        //启用gzip压缩
        properties.put("compression.type","gzip");
        //调整kafka每个请求的消息大小为5MB(这里对应压缩后消息大小),默认值为1MB
        properties.put("max.request.size", "5242880");
        //集合5MB大小的消息后发送,这样会提高消息的压缩比,减少省到总部的网络带宽,并且提高吞吐量,但是会增加消息发送的延时,和linger.ms两个参数,看哪个条件先满足就先触发(测算省平均发送峰值为40Mbps)
        properties.put("batch.size", "5000000");
        //集合1分钟内的消息后发送,这样会提高消息的压缩比,减少省到总部的网络带宽,并且提高吞吐量,但是会增加消息发送的延时
        properties.put("linger.ms", "60000");
        //client.id:该参数可以是任意的字符串,服务器会用它来识别消息的来源。
        //max.in.flight.requests.per.connection:生产者在收到服务器晌应之前可以发送多少个消息。越大越占用内存,但会提高吞吐量
        //timeout.ms:指定了broker等待同步副本返回消息确认的时间
        //request.timeout.ms:生产者在发送数据后等待服务器返回响应的时间
        //metadata.fetch.timeout.ms:生产者在获取元数据(比如目标分区的首领是谁)时等待服务器返回响应的时间。
        // max.block.ms:该参数指定了在调用 send()方法或使用 partitionsFor()方法获取元数据时生产者阻塞时间
        // max.request.size:该参数用于控制生产者发送的请求大小。
        //receive.buffer.bytes和send.buffer.bytes:指定了 TCP socket 接收和发送数据包的缓冲区大小,默认值为-1
        Producer<String, String> producer = null;
        File file = new File("G:\\ETE_CACHE_01.txt");
        BufferedReader bufferedReader = null;
        try {
            producer = new KafkaProducer<>(properties);

            bufferedReader = new BufferedReader(new FileReader(file));

            if (!bufferedReader.ready()) {
                System.out.println("文件无法读取");
                return;
            }
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                producer.send(new ProducerRecord<>("ETE_CACHE_01", line));
                Thread.sleep(500);
                System.out.println("成功发送:" + line);
            }
            /*for (int i = 0; i < 666; i++) {
                String msg = "我是Cool.R! "+new Date();
                producer.send(new ProducerRecord<String, String>("ETE_CACHE_01", msg));
                Thread.sleep(500);
                System.out.println("Sent:" + msg);
            }*/
        } catch (Exception e) {
            e.printStackTrace();

        } finally {
            producer.close();
            try {
                bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值