Kafka Streams+SpringBoot之探索:將一個流轉換到另外一個流 - mydeveloperplanet

banq發表於2019-10-17

為了從主題中讀取無限制的資料流,我們需要建立一個小型應用程式,以傳送無限制的資料流。我們模擬一條Tweet流,在Tweet末尾恰好有一個標籤。每秒都會在該主題上釋出一條訊息。Tweets始終包含相同的訊息(Lorem ipsum…),主題標籤是從5個主題標籤的固定列表中隨機選擇的。

@RestController
public class KafkaProducerController {
 
  private static final String loremIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor " +
      "incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco " +
      "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit " +
      "esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa " +
      "qui officia deserunt mollit anim id est laborum.";
 
  private static final String[] hashTags = {"latin", "italy", "roman", "caesar", "cicero"};
 
  private Random randomNumber = new Random();
 
  private String randomMessage;
 
  @RequestMapping("/sendMessages/")
  public void sendMessages() {
 
    Properties props = new Properties();
    props.put("bootstrap.servers", "localhost:9092");
    props.put("acks", "all");
    props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
    props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
 
    Producer<String, String> producer = new KafkaProducer<>(props);
 
    try {
      while (true) {
        // Every second send a message
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {}
 
        randomMessage = loremIpsum + " #" + hashTags[randomNumber.nextInt(hashTags.length)];
        producer.send(new ProducerRecord<String, String>("my-kafka-streams-topic", null, randomMessage));
 
      }
    } finally {
      producer.close();
    }
 
  }
 
}

變數loremIpsum是固定訊息,變數hashTags是主題標籤的固定列表。在該sendMessages方法中,我們首先定義一些Kafka屬性。在第一個try塊中,無休止的迴圈每秒向主題傳送一條帶有隨機主題標籤(變數randomMessage)的訊息。my-kafka-streams-topic。我們只為該主題提供一個值,而不是一個鍵,因為該主題中的鍵與我們無關。
最後要做的是在Kafka中建立主題。我們透過Kafka的bin目錄中的kafka-topics.sh 指令碼來執行此操作 :

$ ./kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic my-kafka-streams-topic


可以透過呼叫URL http:// localhost:8081 / sendMessages /來啟動資料流。

現在我們已經做好了所有準備,現在該開始第一個流媒體示例了。我們將從中讀取Tweets my-kafka-streams-topic,使用主題標籤過濾Tweets latin並將其釋出到主題my-kafka-streams-out1。
我們建立一個Spring Boot應用程式(mykafkaprocessingplanet多模組Maven專案中的模組),並將以下依賴項新增到pom中:

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-streams</artifactId>
    <version>2.3.0</version>
  </dependency>
  <dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-clients</artifactId>
    <version>2.3.0</version>
  </dependency>
</dependencies>


可以看出,除了kafka-streams依賴之外,我們還必須新增kafka-clients依賴。如果不新增最後一個依賴項,則在建立時會遇到以下錯誤KStream:

java.lang.NoSuchMethodError: org.apache.kafka.clients.admin.AdminClientConfig


與生產者一樣,我們確保可以在呼叫URL之後開始處理。這URL的KafkaProcessingController:

private KafkaStreams streams1;
 
@RequestMapping("/startProcessing1/")
public void startProcessing1() {
 
  Properties props = new Properties();
  props.put(StreamsConfig.APPLICATION_ID_CONFIG, "processor1");
  props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
  props.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass());
 
  final StreamsBuilder builder = new StreamsBuilder();
 //魔術關鍵行
  builder.stream("my-kafka-streams-topic").filter((key, value) -> ((String) value).endsWith("latin")).to("my-kafka-streams-out1");
 
  final Topology topology = builder.build();
  streams1 = new KafkaStreams(topology, props);
  streams1.start();
 
}

與往常一樣,首先我們需要定義屬性以連線到主題。注意,我們沒有覆蓋預設鍵Serializer / Deserializer,因為我們沒有為主題中的訊息提供鍵。注意魔術關鍵行,我們從my-kafka-streams-topic中讀取流,過濾以結“latin”結尾的訊息,並將過濾後的訊息傳送到主題my-kafka-streams-out1

最後要做的是建立輸出主題:

$ ./kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic my-kafka-streams-out1


是時候把所有東西放在一起了。透過從mykafkaproducerplanet目錄呼叫以下命令來啟動生產者:
$ mvn spring-boot:run

執行以下命令來啟動Consumer :

$ ./kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic my-kafka-streams-out1 --from-beginning


透過呼叫URL http:// localhost:8081 / sendMessages /將訊息從生產者傳送到my-kafka-streams-topic,透過呼叫URL http:// localhost:8082 / startProcessing1 /實現流轉發處理;可以透過呼叫URL http:// localhost:8082 / stop來停止流處理。

帖子中使用的資源當然可以在GitHub上找到。點選標題見原文
 

相關文章