Azkarra Streams簡介:Apache Kafka Streams的第一個微框架

banq發表於2019-11-29

Kafka Streams是一個功能強大的庫,用於在Apache Kafka之上構建複雜的流應用程式。隨著時間的推移,以及經過多個專案之後,我們發現自己正在編寫相同的程式碼來在生產環境中執行和與Kafka Streams應用程式互動。

我們堅信,基於Kafka Streams的簡單微服務的開發應該花費幾天而不是幾周的時間,而最少的功能才能安全地投入生產。

因此,我們決定構建自己的框架,以簡化Kafka Streams應用程式的開發和操作。

今天,我們很高興宣佈推出Azkarra Streams,這是一個新的開源微型Java框架,可讓您集中精力編寫Kafka Streams拓撲程式碼,而不是執行它們所需的樣板程式碼。

主要特徵

Azkarra Streams提供了一組功能,可以快速除錯和構建可用於生產環境的Kafka Streams應用程式。其中包括:

  • Kafka Streams例項的生命週期管理(不再需要KafkaStreams#start())。
  • 輕鬆外部化拓撲和Kafka Streams配置(使用Typesafe Config)。
  • 嵌入式HTTP伺服器,用於查詢狀態儲存(Undertow)。
  • HTTP端點,用於監視流應用程式指標(例如:JSON,Prometheus)。
  • 用於拓撲視覺化的Web UI。
  • 使用SSL或基本身份驗證的加密和身份驗證。
  • 等等。

為什麼選擇Azkarra

在編寫第一個Azkarra應用程式之前,讓我們花一些時間描述標準Kafka Streams應用程式的不同部分,以便更好地瞭解Azkarra的好處。

為此,我們將使用著名的單詞計數示例,該示例可在Kafka Streams官方文件中找到

首先,我們必須宣告並構建一個Topology。

StreamsBuilder builder = new StreamsBuilder();
KStream<String, String> textLines = builder
 .stream("streams-plaintext-input");

 textLines.flatMapValues(value ->
  Arrays.asList(value.toLowerCase().split("\\W+"))
 )
.groupBy((key, value) -> value)
.count(Materialized.as("WordCount"))
.toStream()
.to(
  "streams-wordcount-output",       
  Produced.with(Serdes.String(), Serdes.Long())
);
Topology topology = builder.build();

定義應用配置:

Properties props = new Properties();
props.put(APPLICATION_ID_CONFIG, "streams-word-count");
props.put(BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
props.put(DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass());
props.put(DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass());

建立KafkaStreams 例項:

final KafkaStreams streams = new KafkaStreams(topology, props);

最後,我們必須管理Kafka Streams應用程式的執行部分。這意味著,啟動KafkaStreams例項並使用關閉掛鉤管理應用程式的乾淨關閉。

final CountDownLatch latch = new CountDownLatch(1);
Runtime.getRuntime().addShutdownHook(
new Thread("streams-shutdown-hook") {
  @Override
  public void run() {
    streams.close();
    latch.countDown();
  }
});

  try {
     streams.start();
     latch.await();
  } catch (Throwable e) {
     System.exit(1);
  }
  System.exit(0);

這是完整的程式碼:GitHub Gist

當然,流應用程式很少那麼簡單。例如,您將需要新增錯誤處理並監視Kafka Streams例項的狀態。此外,您可能希望使用互動式查詢等查詢內部商店。

最後但並非最不重要的一點是,有時您必須處理一些問題(例如:https : //issues.apache.org/jira/browse/KAFKA-7380)。

但是現實是,作為開發人員,您應該始終將開發工作重點放在拓撲的定義和優化上。原因很簡單-這是為您的業務創造價值的部分。

Azkarra的第一步

我們希望解決的第一個方面是將構建Topology與執行之間的關注點分離。確實,我們認為建立和啟動新KafkaStreams例項不應由開發人員直接管理。

因此,讓我們使用Azkarra API重寫WordCount示例。

首先,我們將使用Azkarra Streams Maven原型建立一個簡單的專案結構。您可以執行以下命令:

$ mvn archetype:generate -DarchetypeGroupId=io.streamthoughts \
-DarchetypeArtifactId=azkarra-quickstart-java \
-DarchetypeVersion=0.3 \
-DgroupId=azkarra.streams \
-DartifactId=azkarra-getting-started \
-Dversion=1.0-SNAPSHOT \
-Dpackage=azkarra \
-DinteractiveMode=false

在pom.xml已經包含Azkarra流和卡夫卡流的依賴關係:

<dependencies>
    <dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka-streams</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>io.streamthoughts</groupId>
        <artifactId>azkarra-streams</artifactId>
        <version>0.3</version>
    </dependency>
</dependencies>

使用您喜歡的IDE或編輯器,開啟Maven專案。建立一個新檔案src/main/java/azkarra,該檔案具有基本的java main(String[] args)方法和如下的拓撲定義:

package azkarra;
@AzkarraStreamsApplication
public class SimpleStreamsApp {

    public static void main(String[] args) {
        AzkarraApplication.run(SimpleStreamsApp.class, args);
    }

    @Component
    public static class WordCountTopology implements TopologyProvider {

        @Override
        public Topology get() {
            StreamsBuilder builder = new StreamsBuilder();
            KStream<String, String> textLines = 
                          builder.stream("streams-plaintext-input");

            textLines
                .flatMapValues(value ->
                    Arrays.asList(value.toLowerCase().split("\\W+"))
                )
                .groupBy((key, value) -> value)
                .count(Materialized.as("WordCount"))
                .toStream()
                .to(
                   "streams-wordcount-output",
                   Produced.with(Serdes.String(), Serdes.Long())
                );
            return builder.build();
        }

        @Override
        public String version() {
            return "1.0";
        }
    }
}

如您所見,我們僅實現了一個名為的介面以TopologyProvider構建Topology。Azkarra Streams負責自動配置和啟動所謂的KafkaStreams例項。

接下來,我們必須配置我們的應用程式。我們將建立一個名為一個簡單的檔案application.conf中src/main/resources/application.conf包含以下程式碼:

注意:您也可以將檔案保留在專案中。

azkarra {
  context {
    streams {
      bootstrap.servers = "localhost:9092"
      default.key.serde = "org.apache.kafka.common.serialization.Serdes$StringSerde"
      default.value.serde = "org.apache.kafka.common.serialization.Serdes$StringSerde"
    }
  }
}

恭喜你!您使用Azkarra編了寫第一個流應用程式。

在Docker上執行您的應用

為了執行我們的應用程式,我們必須首先啟動一個Kafka叢集。為此,我們將使用Confluent.Inc維護的官方Kafka Docker映像

要啟動單節點Kafka群集,請執行docker-compose.yml專案中包含的檔案。

$ cd azkarra-getting-started 
$ docker -compose up -d

然後,建立拓撲使用的兩個主題(源,接收器)。為此,您可以執行提供的指令碼:

$ chmod u + x quickstart-create-wordcount-topics.sh 
$ ./ quickstart-create-wordcount-topics.sh

最後,我們將打包並執行Maven專案:

$ mvn clean package && java -jar target / azkarra-quickstart-java-0.3.jar

要驗證,您的流應用程式正在執行,請檢查執行狀況終結點:

$ curl -sX GET'http :// localhost:8080 / health' | grep'UP'

最後,讓我們向Kafka主題傳送一些訊息streams-plaintext-input:

$ docker exec -it azkarra-cp-broker /usr/bin/kafka-console-producer --topic streams-plaintext-input --broker-list kafka:9092
Azkarra Streams
WordCount
I Heart Logs   
Kafka Streams
Making Sense of Stream Processing

消費
streams-wordcount-output 的輸出:

$ docker exec -it azkarra-cp-broker /usr/bin/kafka-console-consumer --from-beginning --property print.key=true --property key.separator="-" --topic streams-wordcount-output --bootstrap-server kafka:9092

嵌入式HTTP伺服器

Azkarra的主要功能之一是嵌入式Web伺服器,它公開了用於管理和監視本地流應用程式的端點

例如,您可以列出本地執行的流例項(即:在JVM中執行的例項)。

$ curl -sX GET http://localhost:8080/api/v1/streams | jq .
<p>[
 "word-count-topology-1–0"
]

獲得指定流資訊:

$ curl -sX GET http://localhost:8080/api/v1/streams/word-count-topology-1-0/ | jq . 
{
 "id": "word-count-topology-1–0",
 "since": "2019–11–26T13:48:17.35+01:00[Europe/Paris]",
 "name": "WordCountTopology",
 "version": "1.0",
 "state": {
 "state": "RUNNING",
 "since": "2019–11–26T13:48:18.772+01:00[Europe/Paris]"
 }
}

最後輸出流應用到Prometheus格式:

$ curl -sX GET ‘http://localhost:8080/api/v1/streams/word-count-topology-1-0/metrics?format=prometheus'
# HELP streams_incoming_byte_rate The number of incoming bytes per second
# TYPE streams_incoming_byte_rate counter
streams_incoming_byte_rate{group=”admin-client-node-metrics”,id=”word-count-topology-1–0",client_id=”word-count-topology-1–0-e04c076a-7d46–4bdc-9bc2–14d181370762-admin”,node_id=”node — 1",} 0.0
# HELP streams_incoming_byte_total The total number of incoming bytes
# TYPE streams_incoming_byte_total counter
streams_incoming_byte_total{group=”admin-client-node-metrics”,id=”word-count-topology-1–0",client_id=”word-count-topology-1–0-e04c076a-7d46–4bdc-9bc2–14d181370762-admin”,node_id=”node-1",} 1066.0

Azkarra WebUI

Azkarra Streams的另一個很酷的功能是:http:// localhost:8080/ui上提供了預設的嵌入式Web UI,可用於管理流應用程式。

Azkarra WebUI最初是為了促進開發而設計的,但很快發展成為一個小型管理介面。

例如,您可以停止,使用“可用操作”按鈕重新啟動流應用程式,瀏覽指標,配置等。

Azkarra WebUI還附帶了用於流拓撲的簡單DAG表示。

互動查詢

最後,Kafka Streams具有強大的機制來查詢stream應用程式實現的狀態。通常,作為開發人員,我們構建HTTP端點以使用公共Kafka Streams API公開這些狀態。

Azkarra Streams為此提供了一個預設終結點,可以通過Azkarra WebUI直接訪問該終結點。

 

相關文章