使用 Apache Kafka 实现 Quarkus 的反应式消息

什么是 Apache Kafka 以及为何要使用它?

现在,数据处理和消费的方式与以往的实践是不一样的。在过去,数据会存储到一个数据库中,并且会进行批处理以获取分析结果。

尽管这种方式依然占有一席之地,但是更现代化的平台能够让我们在数据进入系统的时候对其进行实时处理。

Apache Kafka (简称为 Kafka)是一个分布式的事件存储和流处理平台,能够存储、消费和处理数据流。

要理解 Kafka 是如何运行的,我们需要掌握五个基本概念:

  • 事件(Event,或者叫做消息):事件是一个具有时间戳的键-值对,代表了存储在系统中需要进行处理的数据。从 Kafka 的角度来看,它就是一堆字节。

  • 分区(Partition):分区是生产和消费事件的地方。在分区中,能够保证事件的顺序。

  • 主题(Topic):一个主题是由一个或多个分区组成的。主题是开发人员使用的工作单元,能够消费或生产事件。

  • 消费者(Consumer):消费者订阅某个主题,这样每当事件发布到该主题时,消费者都会得到通知。

  • 生产者(Producer):生产者发布事件到主题(实际上是属于该主题的某个分区)中。

Apache Kafka 的一个重要特点是它在创建时充分考虑到了可扩展性和容错性,使其非常适合高性能的应用。我们认为,Kafka 可以取代一些传统的消息系统,比如 Java Message Service(JMS)和 Advanced Message Queuing Protocol(AMQP)。

Apache Kafka 能够与当前使用的大多数语言进行集成,但是在本文中,我们将会讨论它与 Java 的集成,具体来讲是与 Quarkus Java 栈的集成。

Quarkus 是什么?

Quarkus 是一个全栈、Kubernetes 原生的 Java 框架,适用于 Java 虚拟机(JVM)和原生编译环境,专门为容器中运行的 Java 进行了优化,使其成为 Serverless、云和 Kubernetes 环境下的高效平台。

Quarkus 没有重复发明轮子,而是使用了由标准/规范支撑的知名企业级框架,并且使它们能够借助 GraalVM 编译为二进制文件。

如何在 Quarkus 中集成 Kafka?

Quarkus 使用 SmallRye Reactive Messaging 项目实现与 Apache Kafka 的交互。

Quarkus 入门

要开始使用 Quarkus,最快捷的方式就是通过其  添加所需的依赖。每个服务可能会有不同的依赖,我们可以在 Java 11 或 Java 17 之间选择。要实现 Quarkus 与 Kafka 的集成,我们需要添加_SmallRye Reactive Messaging - Kafka Connector_扩展。

要开发的应用

假设我们是一家影视流媒体公司,其中有个用例就是保存电影。这的确可以通过传统数据库来实现,但是考虑到要实现良好的用户体验需要实时互动,因此我们决定将它们存储在 Kafka 中。

所以,我们会有两个服务,其中一个服务会在用户停止播放电影的时候生成一个事件,另外一个服务则会消费这些事件,并以服务器事件的方式对其进行展示和流式处理。

下图展示了应用的架构:

接下来,我们使用 Quarkus 实现这些服务并阐述一些内部的细节。

电影播放的生产者(Movie Plays Producer)

每当用户停止播放电影的时候,该服务会向 Kafka _PlaytimeMovies_主题发送一个事件。该事件包含了电影的 ID 以及观看的总时间。为了便于显示,我们将会使用一个定时器自动触发模拟用户观看电影的逻辑。

当该服务启动的时候,它将会生成一些电影到 Kafka _Movies_主题中。

创建项目

导航至 Quarkus 的 初始页面 并选择_smallrye-reactive-messaging-kafka_以便于集成 Kafka。然后,选择_Jackson_扩展,用于实现事件在 JSON 和 Java 的对象-字节数组之间进行编排/解排。同时,取消选中生成_Started Code_的选项。

如下面的截图所示:

你也可以跳过这个手动的步骤并导航至 Kafka Quarkus Generator 链接,在这里,所有的内容都已经选择好了。然后,点击_Generate your application_按钮,以下载应用骨架的压缩文件。

解压文件,并在你最喜欢的 IDE 中打开项目。

开发

我们创建两个 POJO,其中一个代表 Movie ,另外一个代表 PlayedMovie 。

public class Movie {
       public int id;   public String name;   public String director;   public String genre;    public Movie(int id, String name, String director, String genre) {
         this.id = id;       this.name = name;       this.director = director;       this.genre = genre;   }}

复制代码

Movie 包含了电影的 id 、 name 、 director 和 genre 。

public class PlayedMovie {
     public int id;   public long duration;
   public MoviePlayed(int id, long duration) {
         this.id = id;       this.duration = duration;   }}

复制代码

PlayedMovie 包含了 id 和 duration 字段,分别代表了已播放电影的标识符以及用户观看的时长。

我们还需要一个

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值