我如何 return 将 mapreduce 操作的结果发送到 AWS API 请求

How can I return the result of a mapreduce operation to an AWS API request

我有一个程序可以执行数千次蒙特卡洛模拟来预测结果;我不能说他们真正预测的是什么,所以我将使用 "the indisputable existence of santa claus" 中的另一个例子,因为那些算法的内容与问题无关。我想知道大富翁棋盘上的每个方块被访问的频率(以预测哪些房产最值得购买)。为此,我模拟了数千场比赛并整理了结果。我当前的实现是一个独立的 C# 应用程序,但我想将它移动到云端,以便我可以将其作为服务提供——每个用户都可以通过提交每个骰子的面数来获得个性化的结果。

当前的实现也很慢 - 它非常可并行化,因为每个模拟都是完全独立的,但我只有 8 个内核,所以在我的本地进行大约 50000 次单独模拟需要 20 分钟以上才能完成完整预测机.

计划是让 AWS lambda 函数每个 运行 一个(或几个)模拟然后整理 - 基本上是 mapreduce。我研究过使用 AWS EMR (Elastic MapReduce),但这对于我想要的来说规模太大了,将实例旋转到 运行 单独的计算似乎比单独的整个计算花费更长的时间(这不会对于数小时的离线分析很重要,但我希望低延迟响应网络请求。

我认为理想的情况是:

Lambda 0 - 触发许多其他 lambda 函数,每个函数执行一小部分计算。 Lambda 1..N - 并行进行许多模拟(数字不是常数)。 Lambda N+1 - 整理所有结果和 return 答案。

这里有一个 lambda mapreduce 框架:

https://github.com/awslabs/lambda-refarch-mapreduce

但它似乎有一个主要缺点 - 每次地图阶段完成时,它会将其结果写入 S3(我可以将其用作临时),然后通过事件触发新的 lambda。触发的 lambda 查看是否所有结果都已写入存储。如果不是,则结束,如果是,则执行还原步骤。这似乎是一个公平的解决方案,但我只是有点担心 a) 当两个结果放在一起时存在竞争风险,两个 reducer 能否同时计算结果? b) 似乎它发射了很多 lambda,它们都决定不 运行(我知道它们比 运行 便宜,但每个模拟的数量加倍到两个 - 计算和可能会减少 - 显然会使成本增加一倍)。有没有办法在将 100 个文件写入文件夹而不是每个文件之后触发 S3 结果?

我查看了使用步进函数,但我不确定如何在一个步骤中并行触发多个 lambda 并在状态机转换之前让它们全部 return。然而,步进函数对于最后的皱纹很有用 - 我想将所有这些隐藏在 API.

后面

根据我的阅读,APIs 可以触发 lambda 和 return 该 lambda 的结果,但我不希望调用的 lambda 成为那个 return结果。当您改为从 API 调用步进函数时,最后状态的结果不是由 API 调用 return 编辑的。

总之,我要:

API 请求 -> 并行计算结果 -> API 响应

中间的那一点我不清楚该怎么做,同时能够 return 所有结果作为对原始请求的响应 - 无论是靠自己都很容易。

我能看到的几个选项:

使用 AWS API 网关现在原生支持的 step 函数,并在一个状态下调用多个 lambda,等待它们全部 return 后再转换。

使用 AWS EMR,但以某种方式使预配置的实例始终处于活动状态以避免预配置时间开销。这显然否定了 Lambda 的可扩展性并且更昂贵。

使用 mapreduce 框架或类似的东西,并找到一种方法来响应来自不同 lambda 的传入请求到 API 请求最初调用的请求。理想情况下也减少此处涉及的 S3 事件的数量,但这不是优先事项。

立即响应来自第一个 lambda 的原始 API 请求,然后在计算完成后向用户推送更多数据(他们应该只需要大约 30 秒的并行性,域是这样的这是等待响应的可接受时间,甚至是 HTTP 响应)。

我怀疑它会对解决方案产生任何影响,因为它只是中间位的扩展,而不是根本性的变化,但真正的计算是迭代的,所以会是:

请求 -> Mapreduce -> Mapreduce -> ... -> 响应

只要我知道如何在请求中链接一组 lambda 函数,链接更多应该只是更多相同(我希望)。

谢谢。

P.S。我无法创建它们,标签 aws-emraws-elastic-mapreduce 都不存在。

一个想法是通过 API GW 调用 Lambda 函数(称之为 'workflow director'),然后在该函数中编写代码以直接调用步骤函数(或其他)并轮询状态因此您最终可以同步响应 HTTP 请求。

这只是异步工作流的同步包装器。请记住,API GW 在 29 秒时有一个硬超时,因此如果您预计此工作流将花费大约 30 秒,那么实施同步版本可能不值得。

异步模型(我猜在这种情况下直接从 API GW 调用步进函数)在任何一种情况下都可以工作。

编辑:抱歉,可能误解了您对步骤函数的评论。我认为没有同步的方式来调用步骤函数工作流并等待最终状态,但从您的评论来看似乎已经存在。

让我快速回答您的几个具体问题:

Is there a way to fire off an S3 result after, say, 100 files are written to a folder instead of after every one?

我认为这是不可能的。

I'm not sure how to fire many lambdas in parallel in one step and have them all return before the state machine transitions

你在文档中看到了吗? http://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-parallel-state.html

有趣的情况。喜欢阅读问题的详细信息。基本上,我们正在寻找 cpu 功率负载,但持续时间短......应该很快可用。如果我们真正意识到基本问题lambda 的缺点是它不支持线程,也不支持异步行为。

仔细考虑.. Lambda 看起来是正确的方法.. 如果您借助 dynamodb(不是另一个数据库,因为要求非常小;为什么要为此使用另一个 ec2 实例)怎么办..每当lambda 函数完成它并更新 dynamodb 中的记录.. 如果 db 中的这个值超过 100 --> 执行你最后的 lambda 函数..

号码固定在100吗?或者它可以是任何数字..如果它可以是任何数字 n;那我也可以想办法解决这个问题..

"api invocation happened to lambda 0 and u need to reply on that" 问题的解决方案是 lambda 0 应该如下所示:

for ( int i = 0 ; i < n ; i++){
   invoke processinglambda[i]; // each processingLambda process and updates 
                               // results in dynamodb
}
while (true) {
 (if work is done by ALL processing lambdas){
     //collate all data 
     return result;
   }

}

所以,我们基本上是在尝试使用上述设计来实现 MapReduce。Lambda 0 是主节点;它将作业委托给节点 lambda 1..N... 进行处理并在 dynamodb .. 主节点中不断更新结果;如果所有子节点都完成了工作,则继续查询 dynamodb。一旦完成;主节点整理所有数据和 returns 响应。