我正在尝试使用akka流来收听sqs,我从q获取消息 使用此代码段:
implicit val system = ActorSystem()
implicit val mat = ActorMaterializer()
implicit val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(ConfigUtils.dtsConfiguration.ioThreadPoolSize))
val awsSqsClient: AmazonSQSAsync = AmazonSQSAsyncClientBuilder
.standard()
.withCredentials(new ClasspathPropertiesFileCredentialsProvider())
.withEndpointConfiguration(new EndpointConfiguration(sqsEndpoint, ConfigUtils.dtsConfiguration.regionName))
.build()
val future = SqsSource(sqsEndpoint)(awsSqsClient)
.takeWhile(_ => true)
.mapAsync(parallelism = 2)(m => {
val msgBody = SqsMessage.deserializeJson(m.getBody)
msgBody match {
case Right(body) => //for each stream add (body.ID,body.Record.FileContent) or concatenate the new fileContent
// with current map (of same id)
// that for each key in the map - if the filecontent size > 100 kb remove the relevant tuple from
the map and perform an operation on it
}
Future(m, Ack())
})
.to(SqsAckSink(sqsEndpoint)(awsSqsClient))
.run()
我已经评论了我需要操作流的代码中的特定点。
我需要的是从sqs获取的每个记录执行此操作:
我想将它的内容放入Int [Int,String],Int代表键,字符串是记录内容。 (对于其他键,我将连接它的内容,直到它的大小超过1kb)
(这就像保存每个键的状态一样)。
然后我想做以下事情:
我想为每个元组执行一个操作(不断地使用流) 当它的内容大小> 1kb,然后将其从地图中删除。
我还需要一个ttl,用于那些没有在地图中更新太空时间的记录,例如30秒。
是否可以使用akka流完成?
感谢。
答案 0 :(得分:0)
Flow.statefulMapConcat
是一种使用swizz-army-knife的东西,允许你保持状态和条件下游值。如果你很高兴只在元素到达时丢弃TTL,这也是可行的,但是通过实现自定义GraphStage
,有一个嘀嗒触发驱逐有点棘手,可能会更容易。
这是一个简化的示例,它将累积每个键的值,直到达到限制然后向下游发射。
import scala.collection.immutable.Iterable
val theThing: Flow[(String, Int), (String, Int), NotUsed] =
Flow[(String, Int)]
.statefulMapConcat { () =>
// state kept in factory function scope
var state = Map[String, Int]()
// for each incoming tuple
{
case (key, value) =>
val newValueForKey = state.getOrElse(key, 0)
// ... evicting old elements could go here ...
if (newValueForKey > 10) {
// max size, emit something downstream
state = state - key
Iterable(key -> newValueForKey)
} else {
// just update state, don't emit anything
state = state + (key -> newValueForKey)
Iterable.empty
}
}
}
要做到这一点,你必须以某种方式引入一个tick元素,但这可能也会受到背压的影响,因此可以返回到自定义的GraphStage。 GraphStages有一个计时器API,允许他们将滴答作为不受背压影响的侧通道。您可以在Akka文档的这一部分中找到有关如何实现此类的详细信息:http://doc.akka.io/docs/akka/current/scala/stream/stream-customize.html#custom-linear-processing-stages-using-graphstage