一、上一节讲了kafka的安装,这节讲一下Java开发kafka程序。
所需jar包
https://download.csdn.net/download/hezhihuahzh/10647732
可下载。
二、写代码前先大概说一下kafka的生产发送和接收消费的细节。
1、Consumer Group:一个Consumer Group包含多个consumer, 这个是预先在配置文件中配置好的。各个consumer(consumer 线程)可以组成一个组(Consumer group ),partition中的每个message只能被组(Consumer group ) 中的一个consumer(consumer 线程 )消费,如果一个message可以被多个consumer(consumer 线程 ) 消费的话,那么这些consumer必须在不同的组。
2、Kafka不支持一个partition中的message由两个或两个以上的consumer thread来处理,即便是来自不同的consumer group的也不行。它不能像AMQ那样可以多个BET作为consumer去处理message,这是因为多个BET去消费一个Queue中的数据的时候,由于要保证不能多个线程拿同一条message,所以就需要行级别悲观所(for update),这就导致了consume的性能下降,吞吐量不够。而kafka为了保证吞吐量,只允许一个consumer线程去访问一个partition。
3、如果觉得效率不高的时候,可以加partition的数量来横向扩展,那么再加新的consumer thread去消费。这样没有锁竞争,充分发挥了横向的扩展性,吞吐量极高。这也就形成了分布式消费的概念。
三、生产者(consumer)代码。发送简单的String类型数据。
1、生产者配置文件 producer_config.properties
#kafka服务的ip和端口
bootstrap.servers=192.168.169.128:9092
#ack方式有三种方式,0,1,-1,这里选择全部
acks=all
retries=30
batch.size=16384
linger.ms=50
buffer.memory=33554432
auto.commit.interval.ms=1000
compression.type=gzip
reconnect.backoff.ms=20000
retry.backoff.ms=20000
#默认的key序列化方式
key.serializer=org.apache.kafka.common.serialization.StringSerializer
#默认的value序列化方式,发送String简单类型的即可,发送对象或者其他复杂数据,需要自定义序列化方式
value.serializer=org.apache.kafka.common.serialization.StringSerializer
2、生产者Java代码
//定义topic
private final static String TOPIC1 = "appreportdata_700091";
public static void send() {
Producer producer = null;
Properties props = null;
try {
//初始化kafka配置信息
props = PropertyUtils.load("producer_config.properties");
producer = new KafkaProducer<>(props);
//发送1万条数据
for(int i=0;i++;i<=10000){
producer.send(new ProducerRecord(TOPIC1, i));
}
} catch (IOException e1) {
e1.printStackTrace();
}
try {
producer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
PS:producer一定要关闭,否则会丢失数据。或者调用flush方法。
四、消费者(consumer)代码,接收String简单类型数据。
1、消费者端配置文件 consumer_config.properties
bootstrap_servers=192.168.39.50:9092
#groupID标示一个消费组,里边的消费者均衡消费某个topic的消息,不会重复
group_id=appreportdata_900050
#消费消息后是否自动提交事务
enable_auto_commit=true
auto_commit_interval_ms=1000
auto_offset_reset=earliest
session_timeout_ms=30000
#key-value反序列化方式
key_deserializer=org.apache.kafka.common.serialization.StringDeserializer
value_deserializer=org.apache.kafka.common.serialization.StringDeserializer
2、消费者代码
public static void getMessage() {
//定义topic
String TOPIC ="appreportdata_700091";
ConsumerRecords records = null;
Properties props = null;
KafkaConsumer consumer = null;
Properties props = null;
try {
props = PropertyUtils.load("consumer_config.properties");
} catch (IOException e1) {
e1.printStackTrace();
}
try {
props = getProperties();
consumer = new KafkaConsumer<>(props);
// 订阅topic
consumer.subscribe(Arrays.asList(TOPIC));
while (true) {
try {
//这里500是每隔500毫秒拉取一次数据,每次拉取的数据个数由kafka配置决定,默认拉取条数是500条,如果少于500条,每次拉取条数随机
records = consumer.poll(500);
count=records.count();
System.err.println(count);
for (ConsumerRecord record : records) {
String content= record.value();
//把接收到的数据进行处理
offset = record.offset();
System.out.println("接收数据条数"+offset);
}
} catch (Exception e) {
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
3、properties加载工具类
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import org.apache.commons.io.IOUtils;
public class PropertyUtils {
private PropertyUtils(){
}
public static Properties load(File file) throws IOException{
InputStream in = null;
try {
in = new FileInputStream(file);
Properties props = new Properties();
props.load(in);
return props;
}finally{
IOUtils.closeQuietly(in);
}
}
public static Properties load(String path) throws IOException{
InputStream in = null;
try {
in = PropertyUtils.class.getClassLoader().getResourceAsStream(path);
Properties props = new Properties();
props.load(in);
return props;
}finally{
IOUtils.closeQuietly(in);
}
}
}
一个简单的发送接收demo就完成了。希望能给大家带来帮助。下节说一下kafka发送对象数据,自定义序列化和反序列化。