gpt4 book ai didi

java - Lagom 服务使用来自 Kafka 的输入

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:31:11 25 4
gpt4 key购买 nike

我正在尝试弄清楚如何使用 Lagom 来消费来自通过 Kafka 通信的外部系统的数据。

我遇到过这个 section of Lagom documentation ,它描述了 Lagom 服务如何通过订阅其主题与另一个 Lagom 服务进行通信。

helloService
.greetingsTopic()
.subscribe // <-- you get back a Subscriber instance
.atLeastOnce(
Flow.fromFunction(doSomethingWithTheMessage)
)

但是,当您想订阅包含由某个随机外部系统产生的事件的 Kafka 主题时,什么是合适的配置?

此功能是否需要某种适配器?澄清一下,我现在有这个:

object Aggregator {
val TOPIC_NAME = "my-aggregation"
}

trait Aggregator extends Service {
def aggregate(correlationId: String): ServiceCall[Data, Done]

def aggregationTopic(): Topic[DataRecorded]

override final def descriptor: Descriptor = {
import Service._

named("aggregator")
.withCalls(
pathCall("/api/aggregate/:correlationId", aggregate _)
)
.withTopics(
topic(Aggregator.TOPIC_NAME, aggregationTopic())
.addProperty(
KafkaProperties.partitionKeyStrategy,
PartitionKeyStrategy[DataRecorded](_.sessionData.correlationId)
)
)
.withAutoAcl(true)
}
}

我可以通过简单的 POST 请求调用它。但是,我希望通过使用来自某些(外部)Kafka 主题的 Data 消息来调用它。

我想知道是否有这样一种方法来以类似于此模型的方式配置描述符:

override final def descriptor: Descriptor = {
...
kafkaTopic("my-input-topic")
.subscribe(serviceCall(aggregate _)
.withAtMostOnceDelivery
}

我遇到过这个 discussion on Google Groups ,但在 OP 问题中,我没有看到他实际上对来自 some-topicEventMessage 做了任何事情,只是将它们路由到他的服务定义的主题。

编辑 #1:进度更新

查看文档,我决定尝试以下方法。我又添加了 2 个模块,aggregator-kafka-proxy-apiaggregator-kafka-proxy-impl

在新的 api 模块中,我定义了一个没有方法的新服务,但有一个主题代表我的 Kafka 主题:

object DataKafkaPublisher {
val TOPIC_NAME = "data-in"
}

trait DataKafkaPublisher extends Service {
def dataInTopic: Topic[DataPublished]

override final def descriptor: Descriptor = {
import Service._
import DataKafkaPublisher._

named("data-kafka-in")
.withTopics(
topic(TOPIC_NAME, dataInTopic)
.addProperty(
KafkaProperties.partitionKeyStrategy,
PartitionKeyStrategy[SessionDataPublished](_.data.correlationId)
)
)
.withAutoAcl(true)
}
}

在impl模块中,我只是简单的做了标准实现

class DataKafkaPublisherImpl(persistentEntityRegistry: PersistentEntityRegistry) extends DataKafkaPublisher {
override def dataInTopic: Topic[api.DataPublished] =
TopicProducer.singleStreamWithOffset {
fromOffset =>
persistentEntityRegistry.eventStream(KafkaDataEvent.Tag, fromOffset)
.map(ev => (convertEvent(ev), ev.offset))
}

private def convertEvent(evt: EventStreamElement[KafkaDataEvent]): api.DataPublished = {
evt.event match {
case DataPublished(data) => api.DataPublished(data)
}
}
}

现在,为了实际使用这些事件,在我的 aggregator-impl 模块中,我添加了一个“订阅者”服务,它接收这些事件,并在实体上调用适当的命令。

class DataKafkaSubscriber(persistentEntityRegistry: PersistentEntityRegistry, kafkaPublisher: DataKafkaPublisher) {

kafkaPublisher.dataInTopic.subscribe.atLeastOnce(
Flow[DataPublished].mapAsync(1) { sd =>
sessionRef(sd.data.correlationId).ask(RecordData(sd.data))
}
)

private def sessionRef(correlationId: String) =
persistentEntityRegistry.refFor[Entity](correlationId)
}

这有效地允许我在 Kafka 主题“data-in”上发布消息,然后在发送给实体使用之前代理并转换为 RecordData 命令。

然而,这对我来说似乎有点老套。我通过 Lagom 内部结构耦合到 Kafka。我无法轻易交换数据源。例如,如果我愿意,我将如何使用来自 RabbitMQ 的外部消息?如果我尝试从另一个 Kafka(与 Lagom 使用的不同)消费怎么办?

编辑 #2:更多文档

我在 Lagom 文档上找到了几篇文章,尤其是这篇文章:

Consuming Topics from 3rd parties

You may want your Lagom service to consume data produced on services not implemented in Lagom. In that case, as described in the Service Clients section, you can create a third-party-service-api module in your Lagom project. That module will contain a Service Descriptor declaring the topic you will consume from. Once you have your ThirdPartyService interface and related classes implemented, you should add third-party-service-api as a dependency on your fancy-service-impl. Finally, you can consume from the topic described in ThirdPartyService as documented in the Subscribe to a topic section.

最佳答案

我不使用 lagom 所以这可能只是一个想法。但是由于 akka-streamslagom 的一部分(至少我是这么认为的)- 从这个解决方案得到你需要的东西应该很容易。

我用了 akka-stream-kafka 这真的很好(我只做了一个原型(prototype))

当你消费消息时,你会做一些事情:

     Consumer
.committableSource(
consumerSettings(..), // config of Kafka
Subscriptions.topics("kafkaWsPathMsgTopic")) // Topic to subscribe
.mapAsync(10) { msg =>
business(msg.record) // do something
}

检查写得好documentation

您可以在这里找到我的整个示例: PathMsgConsumer

关于java - Lagom 服务使用来自 Kafka 的输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54514400/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com