笔者大数据方向全靠自学,可能某些地方不对,踩了很多坑,可能有很多地方不对还望各位不吝赐教,感谢
首先Kafka有个很重的特性 那就是版本差异很大,你不能说很多博主写错了,但是你现在去学习你就发现很多方法都是报错了。这是因为版本原因 本文版本是Kakfa2.0版本
创建项目,引用kafka依赖 这个我就不写了
public class KfkConsumer {
private static Properties properties;
private KafkaConsumer<String, String> kafkaConsumer;
private String topic;
private String group;
public KfkConsumer(String group,String topic){
this.group = group;
this.topic=topic;
intt();
}
public void intt(){
properties = new Properties();
//连接的服务器
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "你的kafkaip:端口号");
//消费组
properties.put(ConsumerConfig.GROUP_ID_CONFIG,group);
//是否自动提交数据
properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true");
//自动提交的时间间隔
properties.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000");
//关于重新读取策略
properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
//心跳时间
properties.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "30000");
//序列化和反序列
properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.LongDeserializer");
// System.setProperty("java.security.auth.login.config", ".../kafka_client_jaas.conf"); // 环境变量添加,需要输入配置文件的路径
// properties.put("security.protocol", "SASL_PLAINTEXT");
// properties.put("sasl.mechanism", "PLAIN");
}
//发送消费信息的方法
public List Monitor(){
kafkaConsumer= new KafkaConsumer<>(properties);
kafkaConsumer.subscribe(Arrays.asList(topic));//订阅的topic 可以写多个
while (true) {
ConsumerRecords<String, String> records = kafkaConsumer.poll(100);
records.forEach(record->{
System.out.printf("topic: %s , partition: %d , offset = %d, key = %s, value = %s%n", record.topic(),
record.partition(), record.offset(), record.key(), record.value());
});
// for (ConsumerRecord record : records) {
// System.out.printf("topic: %s , partition: %d , offset = %d, key = %s, value = %s%n", record.topic(),
// record.partition(), record.offset(), record.key(), record.value());
//
// }
}
}
}
public class KfkProducer {
private static Properties properties;
static{
properties = new Properties();
//服务器端口
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "你的kafkaip:端口号");
//发送策略 分3中 ”all“,1,0
properties.put(ProducerConfig.ACKS_CONFIG, "1");
//如果请求失败,生产者会自动重试,我们指定是0次,如果启用重试,则会有重复消息的可能性
properties.put(ProducerConfig.RETRIES_CONFIG, 0);
properties.put(ProducerConfig.BATCH_SIZE_CONFIG, 16384);
//序例化
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
}
//这里 的处理逻辑不是很好,凑合着看
public void sendTos(String value){
Producer<String, String> procuder = new KafkaProducer<String, String>(properties);
ProducerRecord<String,String> record = new ProducerRecord<String, String>("test-yl","1",value);
//这里也可以不要后面个回掉函数,看你选择,我是测试用
procuder.send(record,new Callback() {
@Override
public void onCompletion(RecordMetadata metadata, Exception exception) {
// System.out.println("message send to partition " + metadata.partition() + ", offset: " + metadata.offset());
System.out.println("消息传输成功 主题:"+metadata.topic()+ " 分区:"+metadata.partition()+" 偏移量:"+metadata.offset());
}
});
}
}
我这里是简单的实现了一个wrodcount的一个demo,就是计数器 计算所有的页面 被访问了多少次
public class StreamDemo {
public static void init(){
Properties config = new Properties();
//这个配置 我也不是很清楚,只知道会生成两个这个topic
config.put(StreamsConfig.APPLICATION_ID_CONFIG, "teset");
//连接的端口号
config.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, ”你的kafkaip:端口号“);
//序列化和反序列化
config.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass());
config.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass());
StreamsBuilder builder = new StreamsBuilder();
KStream<String, String> textLines;
//第一个参数是 从哪里获取源流
//第二个参数是 如何进行序列化
//后面的.filter()方法是 过滤方法,过滤一些你不需要的 数据 我这里是过滤了 一下资源文件,写法很不好,重点是比较直观
textLines = builder.stream("test002" , Consumed.with(Serdes.String(), Serdes.String())).filter(new Predicate<Object, Object>() {
@Override
public boolean test(Object s, Object s2) {
//LogBean log = (LogBean)JSON.parse(s2.toString());
if (s2.toString().contains(".js")){
return false;
}else if(s2.toString().contains(".css")){
return false;
}else if(s2.toString().contains(".png")){
return false;
}else if(s2.toString().contains(".gif")){
return false;
}else if(s2.toString().contains(".jpg")){
return false;
}else if(s2.toString().contains(".jpeg")){
return false;
}
return true;
}
});
textLines
// .mapValues(new MyMapValues()) 这里是一个有状态的改变,对每条数据都进行一个有状态的改变
//.flatMapValues(Line -> Arrays.asList(Line.toLowerCase().split(" ")))
.groupBy((key, word) -> word) //分组 按value 分组
.count() //聚合方法
.toStream() //转换成KStream对象
.process(MyProcessor::new); //处理器
.to("test004", Produced.with(Serdes.String(), Serdes.Long())); //接入到 test004的这个topic
KafkaStreams streams = new KafkaStreams(builder.build(), config);
streams.start(); //启动
}
}