【发布时间】:2017-07-05 18:56:53
【问题描述】:
[注意] 这个问题是 Lagom 框架特有的!
在我当前的项目中,当上游高速并且看起来下游无法及时处理所有消息时,观察到将消息列表从 Source 剪切到 Kafka 主题发布者的问题。正如所意识到的那样,切割与PubSubRef.subscribe()方法https://github.com/lagom/lagom/blob/master/pubsub/javadsl/src/main/scala/com/lightbend/lagom/javadsl/pubsub/PubSubRef.scala#L85的行为有关
完整的方法定义:
def subscriber(): Source[T, NotUsed] = {
scaladsl.Source.actorRef[T](bufferSize, OverflowStrategy.dropHead)
.mapMaterializedValue { ref =>
mediator ! Subscribe(topic.name, ref)
NotUsed
}.asJava
}
有 OverflowStrategy.dropHead 被使用。可以改成back-pressure strategy吗?
UPD#1: 用例非常简单,当查询请求发布到命令主题时,获取它并从数据库表中查询对象,结果列表被推送到结果 Kafka 主题中。代码sn-p:
objectsResultTopic = pubSub.refFor(TopicId.of(CustomObject.class, OBJECTS_RESULT_TOPIC));
objectQueryTopic().subscribe().atLeastOnce(
Flow.fromSinkAndSource(
Flow.fromFunction(this::deserializeCommandAndQueryObjects)
.mapAsync(concurrency, objects -> objects)
.flatMapMerge(concurrency, objects -> objects)
.alsoTo(Sink.foreach(event -> LOG.trace("Sending object {}", object)))
.to(objectsResultTopic.publisher()),
Source.repeat(Done.getInstance())
)
)
如果deserializeCommandAndQueryObjects 函数生成的对象流大于默认值buffer-size = 1000,它会开始切割元素(我们的情况是大约 2.5k 个对象)。
UPD#2: 对象数据的来源是:
// returns CompletionStage<Source<CustomObject, ?>>
jdbcSession.withConnection(
connection -> Source.from(runQuery(connection, rowConverter))
)
还有订阅 Kafka objectsResultTopic:
TopicProducer.singleStreamWithOffset(
offset -> objectsResultTopic.subscriber().map(gm -> {
JsonNode node = mapper.convertValue(gm, JsonNode.class);
return Pair.create(node, offset);
}));
【问题讨论】:
-
发布到
objectQueryTopic的数据的来源是什么?什么是订阅objectsResultTopic重申一下,您在此处为objectsResultTopic使用的 API 不 使用 Kafka。 -
我可能会被一堆乱七八糟的代码 sn-ps 弄糊涂,但主要思想是通过订阅结果 Kafka 主题 = OBJECTS_RESULT_TOPIC 来获取 PubSubRef
objectsResultTopic并通过流程发送从数据库源加载的对象进入 objectsResultTopic.publisher() 以将它们发布到结果主题中。 -
这对于 StackOverflow 问答来说可能有点复杂,是的 :) 我认为最重要的是
PubSubRef不是这项工作的最佳工具。在我看来,您正试图从 Kafka 主题中读取数据,转换数据,然后将结果写入另一个主题。对吗?