項目背景:往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