Kafka实时API探秘

本文要点

  • 在构建应用程序和系统时,我们一直面临的一个挑战是如何有效地在它们之间交换信息,同时保持接口修改的灵活性,而不会对其他地方产生不恰当的影响 。
  • 事件提供了一种“金发姑娘式”的方法,实时API可以作为应用程序的基础,既灵活又高性能,既松耦合又高效 。在你所工作的业务领域,你可能会想到很多事件示例 。它们可以是人类之间产生的互动,也可以是机器之间产生的交互 。
  • Apache Kafka提供了一个可伸缩的事件流平台,你可以用它来构建强大的基于事件的应用程序 。Kafka通过Kafka Streams API提供流式处理能力 。
  • ksqlDB是一个专门为流式处理应用程序而构建的事件流数据库 。它提供了一个基于SQL的API来查询和处理Kafka中的数据 。
  • ksqlDB的特性包括过滤、转换和连接来自流和表的数据,通过聚合事件创建物化视图,等等 。
在构建应用程序和系统时,我们一直面临的一个挑战是如何有效地在它们之间交换信息,同时保持接口修改的灵活性,而不会对其他地方产生不恰当的影响 。接口越是具体和简单化,在做出变更时就越有可能需要进行彻底的重写 。反过来也是成立的,通用的集成模式可以适用,并得到广泛支持,但这是以性能作为代价 。
事件提供了一种“金发姑娘式”的方法,实时 API 可以作为应用程序的基础,既灵活又高性能,既松耦合又高效 。
事件可以被视为其他大多数数据结构的构建块 。一般来说,它们记录某件事情发生的事实和发生的时间点 。一个事件可以捕获不同级别的信息:从一个简单的通知到一个可以描述所发生事情的完整状态的事件 。
我们可以通过聚合事件来创建状态 。除了作为状态的基础,事件还可以用于在发生事件时异步触发其他地方的动作——这是事件驱动架构的基础 。通过这种方式,我们可以构建事件消费者来满足我们的需求——包括无状态的和有状态的 。事件生产者可以选择维护状态,但没有必要这样做,因为事件消费者可以从接收到的事件中重新构建状态 。
在你所工作的业务领域,你可能会想到很多事件示例 。它们可以是人类之间产生的互动,也可以是机器之间产生的交互 。它们可能包含一个丰富的有效负载,或者它们本质上只是一个通知 。例如:
  • 事件:userLogin
  • 有效载荷:zbeeblebrox在2020-08-17 16:26:39 BST时登录 。
  • 事件:CarParked
  • 有效载荷:车辆A42 XYZ在2020-08-17 16:36:27时停在了X42位置上 。
  • 事件:orderPlaced
  • 有效载荷:Robin在2020-08-17 16:35:41 BST时买了4罐总价为2.25英镑的烘豆 。
这些事件可以用来直接触发其他地方的动作(如处理订单的服务),也可以通过聚合来提供信息(如当前停车场已经被占用的数量,就可以知道还有多少空位) 。
所以,如果事件是我们构建应用程序和服务的基石,那么我们需要一种技术来支持我们——这就是 Apache Kafka 的切入点 。Kafka 是一个可伸缩的事件流平台,它提供了:
  • Pub/Sub
  • 发布(写)和订阅(读)事件流,包括从其他系统持续导入/导出数据 。
  • 有状态的流式处理
  • 按照你的需要持久和可靠地存储事件流 。
  • 存储
  • 按事件发生的顺序或追溯的方式处理事件流 。
Kafka 采用了分布式日志的概念 。通过这个简单但功能强大的分布式、不可变、仅追加的日志的概念,我们可以以一种可伸缩和高效的方式捕获和存储业务和系统产生的事件 。这些事件可以供多个用户使用,也可以进行进一步的处理和聚合,既可以直接使用,也可以存储在 RDBMS、数据湖和 NoSQL 等存储系统中 。
在本文的其余部分中,我将探索 Apache Kafka 提供的 API,并演示如何在应用程序中使用它们 。
生产者和消费者 API像 Kafka 这样的系统,它的伟大之处在于生产者和消费者是解耦的,这意味着我们可以在不需要消费者的情况下生产数据(由于是解耦的,我们可以大规模地这样做) 。一个事件发生了,我们把它发送到 kafka,就这么简单 。我们所需要知道的就是 Kafka 集群的细节,以及我们想要发送事件到的主题(Kafka 组织数据的一种方式,有点像 RDBMS 中的表) 。
Kafka 有很多不同语言的客户端 。这里有一个使用 Go 产生事件到 Kafka 的例子:
package mainimport ("gopkg.in/confluentinc/confluent-kafka-go.v1/kafka")func main() {topic := "test_topic"p, _ := kafka.NewProducer(&kafka.ConfigMap{"bootstrap.servers": "localhost:9092"})defer p.Close()p.Produce(&kafka.Message{TopicPartition: kafka.TopicPartition{Topic: &topic,Partition: 0},Value: []byte("Hello world")}, nil)}


推荐阅读