springboot整合kafka

kafka是一个流式平台,官方的定义是:

A streaming platform has three key capabilities:
1,Publish and subscribe to streams of records, similar to a message queue or enterprise messaging system.
2,Store streams of records in a fault-tolerant durable way.
3,Process streams of records as they occur.

它能publish和subscribe消息,好像redis一样。它能以容错方式存储消息,因为可以有副本。它能处理消息流。

我们主要讲kafka与springboot的整合。


官网下载:

你可以选择binary版本2.13。

解压后的目录:

kafka依赖zookeeper,所以先启动zookeeper(cd到kafka解压目录):

 bin/zookeeper-server-start.sh config/zookeeper.properties 

然后再启动kafka:

bin/kafka-server-start.sh config/server.properties 

我们可以看一下kafka自带的主题:

bin/kafka-topics.sh --bootstrap-server localhost:9092 --list

生产者写是往主题里写消息,消费者订阅也是订阅主题的,就像我在网易订阅了体育新闻,然后一旦有新的体育新闻,我就会收到消息。

一个主题会被分解成一个个partition,一个partition里面的消息是有索引的,是有序的。

我们先创建一个主题:

bin/kafka-topics.sh --create --topic firstTopic --bootstrap-server localhost:9092

9092是kafka默认的端口号。

创建之后,我们整一个生产者:

bin/kafka-console-producer.sh --bootstrap-server localhost:9092 --topic firstTopic

意思就是我们连的是kafka上的firstTopic这个主题。

这个就是面向kafka编程,我们不用去管消费者的情况。

然后创建一个消费者:

bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic firstTopic

这时候生产者发送消息的话,消费者就会收到。


当然,我们使用的客户端语言是java,框架是springboot。

maven依赖:


        <!-- https://mvnrepository.com/artifact/org.springframework.kafka/spring-kafka -->
        <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
            <version>2.4.5.RELEASE</version>
        </dependency>

    <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.6</version>
    </dependency>

这是springboot中的关于kafka的依赖。

我们用了google的json来操作json数据。

首先自定义一个消息类:

package org.ocean.example.springboot.kafka;

import lombok.Data;

import java.time.ZonedDateTime;


@Data
public class KafkaMessage {
    private Long id;
    private String username;
    private String password;
    private ZonedDateTime zonedDateTime;
}

import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;

@Component
public class KafkaProducer {

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    public void sendMessage(KafkaMessage kafkaMessage) {
        this.kafkaTemplate.send("firstTopic", new Gson().toJson(kafkaMessage));
    }
}

我们使用kafka模版来向firstTopic发送消息。

import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class KafkaConsumer {

    @KafkaListener(topics = "firstTopic", groupId = "myGroup")
    public void obtainMessage(ConsumerRecord<String, String> consumerRecord) {

        String key = consumerRecord.key();
        String value = consumerRecord.value();
        int partition = consumerRecord.partition();
        long timestamp = consumerRecord.timestamp();
        String topic = consumerRecord.topic();
        log.info("key: " + key + "\n" + "value: " + value + "\n" + "partition: " + partition + "\n" + "timestamp: " + timestamp + "\n" + "topic: " + topic);
    }
}

我们监听firstTopic中的消息,并且声明这个consumer是属于myGroup这个组的。

我们打印了一些东西。

Each record consists of a key, a value, and a timestamp.

每条消息包含一个key,value和timestamp。

相同key的消息可以进入同一个partition。value就是发的string,timestamp是个时间戳,就是发消息的时间。

然后是controller:

package org.ocean.example.springboot.controller;


import org.ocean.example.springboot.kafka.KafkaMessage;
import org.ocean.example.springboot.kafka.KafkaProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.ZonedDateTime;

import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

@RestController
@RequestMapping(value = "/kafka", produces = APPLICATION_JSON_VALUE)
public class KafkaController {

    @Autowired
    private KafkaProducer kafkaProducer;

    @RequestMapping(value = "/message", method = RequestMethod.POST)
    public KafkaMessage getMessageWithPost(@RequestBody KafkaMessage kafkaMessage) {
        kafkaMessage.setZonedDateTime(ZonedDateTime.now());
        kafkaProducer.sendMessage(kafkaMessage);
        return kafkaMessage;
    }

}

我们把输入的数据发送给监听的consumer,并且返回给浏览器。

最后是yml中的配置:

server:
  port: 9090

spring:
  kafka:
    producer:
      bootstrap-servers: localhost:9092
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer

    consumer:
      bootstrap-servers: localhost:9092
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer

给producer,我们配置了序列化的处理类,因为我们要把string对象序列化成字节数组传输。给consumer,我们要使用反序列化类来把字节数组还原成对象。


启动springboot。

并且在.http文件中模拟post请求:

POST http://localhost:9090/kafka/message
Content-Type: application/json

{
  "id": 1,
  "username": "ocean",
  "password": 1212
}


当然,你也可以用postman或者是curl。

控制台得到了正确的信息:

key: null
value: {"id":1,"username":"ocean","password":"1212","zonedDateTime":{"dateTime":{"date":{"year":2020,"month":4,"day":20},"time":{"hour":23,"minute":37,"second":19,"nano":479000000}},"offset":{"totalSeconds":28800},"zone":{"id":"Asia/Shanghai"}}}
partition: 0
timestamp: 1587397039522
topic: firstTopic
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值