Akka Stream Kafka:找不到关键'kafka-clients'的配置设置

时间:2018-06-18 17:22:03

标签: scala apache-kafka akka akka-stream alpakka

我正在尝试使用Alpakka Kafka connector (Akka Stream Kafka)创建一个简单的原型。

运行应用程序时出现以下错误:

com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'kafka-clients'

我在./src/main/scala/App.scala中有以下代码:

import akka.Done
import akka.actor.ActorSystem
import akka.kafka.ProducerSettings
import akka.kafka.scaladsl.Producer
import akka.stream.{ActorMaterializer, Materializer}
import akka.stream.scaladsl.Source
import com.typesafe.config.ConfigFactory
import org.apache.kafka.clients.producer.ProducerRecord
import org.apache.kafka.common.serialization.StringSerializer

import scala.concurrent.Future

object App {
  def main(args: Array[String]): Unit = {
    println("Hello from producer")

    implicit val system = ActorSystem("fakeProducer")
    implicit val materializer: Materializer = ActorMaterializer()

    val config = system.settings.config // ConfigFactory.load()

    val producerSettings =
      ProducerSettings(config, new StringSerializer, new StringSerializer)
      .withBootstrapServers("localhost:9092")

    val done: Future[Done] =
      Source(1 to 100)
        .map(_.toString)
        .map(value => new ProducerRecord[String, String]("test-basic-numbers", value))
        .runWith(Producer.plainSink(producerSettings))


    println("Done")
  }
}

以下build.sbt

name := "test-akka-stream"

version := "0.1"

scalaVersion := "2.11.8"

libraryDependencies += "com.typesafe.akka" %% "akka-stream-kafka" % "0.21.1"

我使用sbt run运行应用。我没有配置任何超级/装配罐。

我可能错过了一些显而易见的东西,但我看不到它......我怀疑akka依赖项存在一些问题。

更新

正如@ terminally-chill调用ProducerSettings(system, new StringSerializer, new StringSerializer)(传递ActorSystem而不是配置)所建议的那样解决问题。我只是不明白这是设计还是错误。

更新2

我创建了一个已修复的github issue。现在,文档更准确,并解释了创建ProducerSettings / ConsumerSettings的正确方法。

val config = system.settings.config.getConfig("akka.kafka.producer")
val producerSettings =
      ProducerSettings(config, new StringSerializer, new StringSerializer)
      .withBootstrapServers("localhost:9092")

或者您可以按照上面的说明传递ActorSystem

4 个答案:

答案 0 :(得分:2)

感谢您在Alpakka Kafka连接器项目中注意到并提出问题。 该文档现已更新:https://doc.akka.io/docs/akka-stream-kafka/current/producer.html

答案 1 :(得分:1)

通常,我将所有配置保留在AkkaSystem实例中。我没有将Alpakka用于Kafka,但我的许多实现均基于源代码。

使用val config = ConfigFactory.load()加载类型安全配置对象,然后将config传递到val system = ActorSystem("fakeProducer", config)

最后,将system.settings.config传递给ProducerSettings

您当前的代码未通过任何设置,因为尚未将配置加载到Akka系统中。您的val config = system.settings.config引用的是一个空配置,其中没有kafka-clients部分(最好的猜测)。

答案 2 :(得分:1)

尽管我试图创建一个基本的“ hello world” Kafka消费者而不是生产者,但我认为我几乎遇到了与您相同的问题(几乎在同一时间)。我猜您只是在浏览Alpakka Kafka connector documentation中的文档,并遵循他们首次定义的示例

val config = system.settings.config

,然后将其传递到新的ConsumerSettings对象。我猜想在线文档存在缺陷,但是我对Akka Streams还是陌生的(这是我第一次通过示例学习的尝试),我没有资格弄清楚到底是对还是错。 / p>

我尝试创建和application.conf文件,然后执行ConfigFactory.load(),然后在创建时将其手动传递给ActorSystem,然后将该系统传递给ConsumerSettings构造函数,以及有关丢失的“ kafka客户端”消失了,但显然我什至不必这样做。如您所说,仅传递“ system”变量而不是“ config”变量即可达到目的。

希望这可以帮助在黑暗中同样摸索的人。我必须说,尽管Akka Streams周围有很多嗡嗡声,但似乎确实缺乏文档。一旦弄明白这些东西,我可能不得不写一篇博客文章!

答案 3 :(得分:1)

感谢@ terminally-chill和@ murray-todd-williams的回答。我进行了一些进一步的研究,并尝试在此处进行总结:

ConsumerSettingsProducerSettings都具有apply个函数,这些函数采用Config(请参见here)或ActorSystem(请参见{{3 }}。

问题在于,使用ActorSystem时代码是:

val config = system.settings.config.getConfig("akka.kafka.consumer")
apply(config, keyDeserializer, valueDeserializer) // call the other overload

在使用Config时,代码为:

val properties = ConfigSettings.parseKafkaClientsProperties(config.getConfig("kafka-clients"))

因此,当直接传递配置时,代码将搜索kafka-clients属性,而不是传递ActorSystem时,代码将检查akka.kafka.consumer/akka.kafka.producer

最后考虑一下,默认情况下,在创建ActorSystem实例时,大多数设置都是从​​嵌入式reference.conf文件加载的,并且与您的application.conf文件合并(如果存在)。更多信息here。 因此,基本上唯一需要设置的属性通常是bootstrap.servers

因此,您现在可以理解为什么使用system.settings.config时代码不起作用。此配置实例已加载reference.conf(具有所有默认设置,请参见here)和自定义application.confkafka-clients属性位于akka.kafka.consumer/akka.kafka.producer内部,但是代码直接检查kafka-clients

一些可能的解决方案:

  • 使用其他重载直接传递ActorSystem
  • 使用system.settings.config.getConfig("akka.kafka.consumer")
  • 传递正确的部分
  • 通过Config部分手动构建kafka-clients实例

对我来说,问题在于here提供的官方文档没有提及这些差异,并且提供的示例不完整和/或不精确。对于Akka专家来说,这可能很清楚,但是对于新开发人员而言,这可能会非常混乱。

我创建了一个更加“易于使用”的示例here,然后打开一个in this gist