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