多易教育KAFKA实战(3)-java消费者客户端API示例代码

本节目录

  1. 入门程序
  2. 消费日志topic
  3. 滑动窗口统计消费topic

1 入门程序

public class ConsumerDemo {
    public static void main(String[] args) {

        Properties props = new Properties();
        props.setProperty("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        props.setProperty("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        props.setProperty("bootstrap.servers", "h1:9092,h2:9092,h3:9092");
        // groupid是消费者所属的消费组的标识  ,同一个组中的消费者在消费一个topic数据时,会各自消费一部分,互不重复
        props.setProperty("group.id", "g1");
        // 消费起始偏移量自动指定,默认值是latest
        props.setProperty("auto.offset.reset", "latest");
        // 是否要把消费者消费到的offset自动提交到kafka去保存 :__consumer_offsets
        /***
         * 消费者组在消费数据的时候,可以讲当前消费到的offset位置,自动记录到kafka中一个特别的topic中: __consumer_offsets
         * 这样一来,万一在某一瞬间,消费者所在机器宕机,崩溃
         * 那么,将消费者重启后,它能从kafka的__consumer_offsets中找到崩溃前消费到的位置,从而可以从那个地方继续往后消费,避免重复消费
         */
        props.setProperty("enable.auto.commit", "true");

        // 构造一个kafka消费者客户端
        KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(props);
        ArrayList<String> topics = new ArrayList<>();
        topics.add("doit14-2");
        // 消费者在消费数据之前,需要先“订阅”主题
        consumer.subscribe(topics);

        while (true) {
            // ConsumerRecords是一个Iterable,里面有一个迭代器,所以,取数据时可以拿出迭代器iterator来迭代,也可以直接用增强for循环迭代
            ConsumerRecords<String, String> records = consumer.poll(200);
            /*Iterator<ConsumerRecord<String, String>> iter = records.iterator();
            while(iter.hasNext()){
                ConsumerRecord<String, String> rec = iter.next();
                String key = rec.key();
                String value = rec.value();

            }*/
            for (ConsumerRecord<String, String> rec : records) {
                String key = rec.key();
                String value = rec.value();
                System.out.println("key: " + key + "\t value: " + value);

            }
        }

    }
}

2 消费日志topic

/**
*   --多易教育
 * web用户行为日志数据统计:行为事件的发生次数
 */
public class LogEventCalc {
    public static void main(String[] args) {

        Properties  = new Properties();
        p.setProperty("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        p.setProperty("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        p.setProperty("bootstrap.servers", "h1:9092,h2:9092,h3:9092");
        p.setProperty("group.id", "g1");
        p.setProperty("auto.offset.reset", "latest");
        p.setProperty("enable.auto.commit", "true");

        // 构造一个kafka消费者客户端
        KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(props);
        ArrayList<String> topics = new ArrayList<>();
        topics.add("doit14-log");
        // 消费者在消费数据之前,需要先“订阅”主题
        consumer.subscribe(topics);

        HashMap<String, Integer> cntMap = new HashMap<>();

        while(true){
            ConsumerRecords<String, String> records = consumer.poll(100);
            for (ConsumerRecord<String, String> record : records) {
                String line = record.value();
                //解析这一条json数据
                JSONObject jsonObject = JSON.parseObject(line);
                // 提取行为事件类型
                String eventid = jsonObject.getString("eventid");
                // 对事件计数
                cntMap.put(eventid,cntMap.getOrDefault(eventid,0)+1);
                // 打印统计结果
                System.out.println(cntMap);
            }
        }


    }
}

3 滑动窗口统计消费topic

/**
 * -- 多易教育 
 * 滑动窗口统计
 * 窗口长度:10s
 * 滑动距离:5s
 */
public class SlideWindowCalc {
    public static void main(String[] args) {

        // 构造所需的数据结构
        ArrayBlockingQueue<ConsumerRecord> queue = new ArrayBlockingQueue<>(1000);
        HashMap<String, Integer> cntMap = new HashMap<>();
		
        // 1. 构造一个线程,来持续不断地从kafka中拉取数据,放入一个阻塞队列
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 构造一个kafka消费者客户端
                Properties props = new Properties();
                props.setProperty("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
                props.setProperty("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
                props.setProperty("bootstrap.servers", "h1:9092,h2:9092,h3:9092");
                props.setProperty("auto.offset.reset", "latest");
                props.setProperty("group.id","aa");
                props.setProperty("enable.auto.commit", "true");
                // 构造一个kafka消费者客户端
                KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(props);
                // 消费者在消费数据之前,需要先“订阅”主题
                consumer.subscribe(Arrays.asList("doit14-window"));
                while(true){
                    ConsumerRecords<String, String> records = consumer.poll(100);
                    for (ConsumerRecord<String, String> record : records) {
                        try {
                            // 将kafka消息用阻塞方法插入队列,如果队列已满,会一直等待可用空间的到来
                            queue.put(record);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();
        // 2. 构造一个定时任务,每隔5s运行一次,从阻塞队列中取最近10s的数据进行统计
        Timer timer = new Timer();
        TimerTask task = new TimerTask(){
            @Override
            public void run() {
                long taskStartTs = System.currentTimeMillis();
                // 从阻塞队列中取数据,进行统计
                //queue.take(); //阻塞方法,如果队列中有数据,就取到数据并返回,如果队列中没有数据,则等待数据的到来
                try {
                    while(true) {
                        ConsumerRecord<String,String> rec = queue.poll(10, TimeUnit.MILLISECONDS);
                        if(rec != null && rec.timestamp()>taskStartTs-10000 && rec.timestamp()<taskStartTs ){
                            String word = rec.value();
                            cntMap.put(word,cntMap.getOrDefault(word,0)+1);
                        }else if(rec != null && rec.timestamp()>=taskStartTs){
                            break;
                        }else if(System.currentTimeMillis()-taskStartTs > 2500){
                            break;
                        }
                    }
                    System.out.println("-----------------calc time : " + taskStartTs + " -------------------- ");
                    System.out.println(cntMap);
                    // 清空hashmap
                    cntMap.clear();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        timer.schedule(task,0,5000);
    }

}

猜你喜欢

转载自blog.csdn.net/qq_37933018/article/details/106690051
今日推荐