发布和使用不同类型的消息的最佳方式是什么?

时间:2016-04-13 00:08:31

标签: apache-kafka kafka-consumer-api kafka-producer-api

Kafka 0.8V

我想发布/使用byte []对象,java bean对象,可序列化对象等等。

为此类型方案定义发布者和使用者的最佳方法是什么? 当我从消费者迭代器中使用消息时,我不知道它是什么类型的消息。 有人能指点我如何设计这样的场景吗?

1 个答案:

答案 0 :(得分:4)

我根据Kafka主题强制执行单个架构或对象类型。这样,当您收到消息时,您确切地知道您将获得什么。

至少,您应该决定某个主题是保留binary还是string数据,并视具体情况而定,如何进一步编码。

例如,您可以将名为 Schema 的主题包含JSON - 以字符串形式存储的编码对象。

如果您使用JSON和JavaScript之类的松散类型的语言,那么在同一主题中存储具有不同模式的不同对象可能很诱人。使用JavaScript,您只需调用JSON.parse(...),即可查看生成的对象,并找出您要对其执行的操作。

但是你不能用像Scala这样的严格类型的语言来做到这一点。 Scala JSON解析器通常希望您将JSON解析为已定义的Scala类型,通常为case class。它们不适用于此模型。

一种解决方案是保留一个模式/一个主题规则,但作弊一点:将对象包装在一个对象中。典型的示例是 Action 对象,其中您有一个描述操作的标头,以及一个具有依赖于标头中列出的操作类型的模式的有效负载对象。想象一下这个伪模式:

{name: "Action", fields: [
  {name: "actionType", type: "string"},
  {name: "actionObject", type: "string"}
]}

这样,即使是强类型语言,您也可以执行以下操作(同样这是伪代码):

action = JSONParser[Action].parse(msg)
switch(action.actionType) {
  case "foo" => var foo = JSONParser[Foo].parse(action.actionObject)
  case "bar" => var bar = JSONParser[Bar].parse(action.actionObject)
}

这种方法的一个巧妙之处在于,如果您的消费者只等待特定的action.actionType,并且只是忽略所有其他消费者,那就很漂亮轻量级,它只解码标题并推迟解码action.actionObject,直到需要时为止。

到目前为止,这一切都是关于字符串编码的数据。如果您想使用二进制数据,当然您也可以将其包装在JSON中,或者包含任何基于字符串的编码(如XML)。但是也有很多二进制编码系统,比如Thrift和 Avro 。实际上,上面的伪模式基于Avro。你甚至可以在Avro中做一些很酷的事情,比如模式演化,除了其他方面提供了一种非常灵活的方式来处理上面的Action用例 - 你可以定义一个模式,而不是将一个对象包装在一个对象中。其他模式的子集,只解码您想要的字段,在本例中只是action.actionType字段。以下是 schema evolution 的精彩描述。

简而言之,我建议的是:

  1. 解决基于模式的编码系统(无论是JSON,XML,Avro, 无论)
  2. 为每个主题规则强制执行一个架构