kafka筆記_java實現生產者和消費者

項目背景:往kafka的topic imgchk_request中produce圖二中的參數,經過AI服務對圖片進行質檢,將結果再寫入kafka topic imgchk_response中供其它系統調用。

測試範圍:功能測試、性能測試

測試過程:用java寫一段kafka生產者和消費者的代碼,通過一次性生產不同數量的消息到imgchk_request,再通過消費者消費imgchk_response,監控應用服務器的資源且獲取到耗時。通過CM平臺也能實時查看到消息的生產和消費情況。

producer代碼:

package com.test.checkimage;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson.JSONObject;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.PartitionInfo;


public class TestProducer {
    public static void produce(int count){
        Properties props = new Properties();
        props.put("bootstrap.servers", "bigdata-dev-mq:9092,bigdata-dev-mq:9093,bigdata-dev-mq:9094");
        props.put("acks", "all");
        props.put("retries", 0);
        props.put("batch.size", 16384);
        props.put("linger.ms", 1);
        props.put("buffer.memory", 33554432);
        props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        //生產者發送消息
        String topic = "imgchk_request";//imgchk_request
        Producer<String, String> procuder = new KafkaProducer<String,String>(props);


        for (int i = 1; i <= count; i++) {
            //生成唯一的uuid值
            UUID uuid = UUID.randomUUID();

            //準備寫入topic的數據
            JSONObject params = new JSONObject();
            params.put("courier_id","12356");
            params.put("image_path","http://filesyshouse.oss-cn-beijing.aliyuncs.com/equipmentImg/2018/11/08/cb8153b7-64eb-48dd-8dc9-aaae3b97c4d7.jpg");
            params.put("storage_type","oss");
            params.put("image_class","equipment");
            params.put("task_uuid",uuid.toString());

            ProducerRecord<String, String> msg = new ProducerRecord<String,String>(topic,params.toJSONString());
            procuder.send(msg);

        }
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//設置日期格式
        System.out.println(df.format(new Date()));// new Date()爲獲取當前系統時間,也可使用當前時間戳

        //列出topic的相關信息
        List<PartitionInfo> partitions = new ArrayList<PartitionInfo>() ;
        partitions = procuder.partitionsFor(topic);
        for(PartitionInfo p:partitions)
        {
            System.out.println(p);
        }

        System.out.println("send message over.");
        procuder.close(100,TimeUnit.MILLISECONDS);

    }
}

consumer代碼:

package com.test.checkimage;

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

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Properties;

public class TestConsumer {
    public static void consumer(){
        Properties properties = new Properties();
        properties.put("bootstrap.servers", "bigdata-dev-mq:9092,bigdata-dev-mq:9093,bigdata-dev-mq:9094");
        properties.put("group.id", "group-1");
        properties.put("enable.auto.commit", "true");
        properties.put("auto.commit.interval.ms", "1000");
        properties.put("auto.offset.reset", "earliest");
        properties.put("session.timeout.ms", "30000");
        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<>(properties);
        kafkaConsumer.subscribe(Arrays.asList("imgchk_response"));//imgchk_response
        while (true) {
            ConsumerRecords<String, String> records = kafkaConsumer.poll(100);
            for (ConsumerRecord<String, String> record : records) {
                //通過設置時間戳,獲得消費此條消息的時間
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//設置日期格式
                String date = df.format(new Date());// new Date()爲獲取當前系統時間,也可使用當前時間戳
                System.out.printf("date=%s,offset = %d, value = %s", date,record.offset(), record.value());
                System.out.println();
            }
        }


    }
}

 

 

CM平臺


附:kafka的基礎知識
kafka和傳統的消息系統不同於:

  • kafka是一個分佈式系統,易於向外擴展
  • 它同時爲發佈和訂閱提供高吞吐量
  • 它支持多訂閱者,當失敗時能自動平衡消費者
  • 消息的持久化

kafka與redis作爲消息列隊使用的差異:
1、消息推送的可靠性 redis多用於實時性較高的消息推送,並不保證可靠。斷電就會清數據,雖然也提供持久化,但多要自己去實現。kafka保證可靠有一些延遲。
2、訂閱功能的分組,kafka中發佈一個內容,多個訂閱者可以分組,同一個組裏只有一個訂閱者consumer會收到該消息(topic下的每個分區只能分配給某個或多個group下的一個consumer),可用作負載均衡。group下的所有consumer都會協調在一起共同參與分配,即rebalance.

1.按照如上的算法,所以如果kafka的消費組需要增加組員,最多增加到和partition數量一致,超過的組員只會佔用資源,而不起作用;
2.kafka的partition的個數一定要大於消費組組員的個數,並且partition的個數對於消費組組員取模一定要爲0,不然有些消費者會佔用資源卻不起作用;
3.如果需要增加消費組的組員個數,那麼也需要根據上面的算法,調整partition的個數

kafka架構原理

在一套kafka架構中有多個producer、多個broker、多個consumer,每個producer可以對應多個topic,每個consumer只能對應一個consumer group。整個kafka架構對應一個zk集羣,通過zk管理集羣配置,選舉leader,以及在consumer group發生變化時進行Rebalance

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章