如何将mapreduce操作的结果返回给AWS API请求

时间:2017-07-27 19:31:22

标签: amazon-web-services aws-lambda aws-api-gateway aws-step-functions

我有一个程序执行数千次monte-carlo模拟来预测结果;我不能说出他们真正预测的内容,所以我将使用圣诞老人无可争辩的存在的另一个例子",因为这些算法的内容与问题无关。我想知道Monopoly董事会上每个广场的访问频率(预测哪些是最好的购买物业)。为此,我模拟了数千个游戏并整理结果。我目前的实现是一个独立的C#应用​​程序,但我想将它移动到云端,以便我可以将其作为服务提供 - 每个用户都可以通过提交每个骰子所拥有的边数来获得个性化结果。

当前的实现也非常慢 - 它非常简单,因为每个模拟都是完全独立的,但我只有8个内核,所以在我的本地机器上完成大约50000个单独模拟的完整预测需要20多分钟。

计划是让AWS lambda函数运行一个(或几个)模拟然后整理 - 基本上mapreduce它。我查看了使用AWS EMR(弹性MapReduce),但这对于我想要的太大了,旋转实例单独运行计算似乎比单独的整个计算花费更长时间(这对于多个小时离线分析,但我希望通过网络请求进行低延迟响应。)

我认为的理想是:

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

这里有一个lambda mapreduce框架:

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

但它似乎有一个主要缺点 - 每次地图阶段完成时,它会将结果写入S3(我将其作为临时使用),然后通过事件触发新的lambda。触发lambda看看是否所有结果都已写入存储。如果不是,则结束,如果是,则执行还原步骤。这似乎是一个公平的解决方案,但我只是稍微关注a)当两个结果汇总在一起时,种族危险可能会有两个减少器计算结果吗?并且b)看起来好像它已经解雇了许多只是决定不运行的lambdas(我知道它们运行起来很便宜,但是每次模拟的数量加倍到两次 - 计算并且可能会减少 - 显然会加倍费用)。有没有办法在将100个文件写入文件夹而不是每个文件夹之后触发S3结果?

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

根据我的阅读,API可以触发lambda并返回该lambda的结果,但我不希望调用的lambda是返回结果的lambda。当您从API调用步骤函数时,最后状态的结果将由API调用返回。

简而言之,我想:

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

中间的那一点我不清楚该怎么做,同时能够将所有结果作为对原始请求的响应返回 - 或者单独使用它们很容易。

我可以看到几个选项:

使用现在由AWS API网关本机支持的步骤函数,并在一个状态中调用多个lambda,等待它们在转换之前返回。

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

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

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

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

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

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

谢谢。

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

2 个答案:

答案 0 :(得分:2)

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

这只是异步工作流程周围的同步包装器。请记住,API GW在29秒时有一个硬超时,因此如果您希望此工作流程大约需要30秒,那么实现同步版本可能不值得。

异步模型(我想在这种情况下,直接从API GW调用步骤函数)可以在任何一种情况下都有效。

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

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

  

有没有办法在将100个文件写入文件夹而不是每个文件夹之后触发S3结果?

我认为这是不可能的。

  

我不确定如何在一步中并行发射多个lambda并让它们在状态机转换之前全部返回

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

答案 1 :(得分:1)

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

对它的思考.. Lambda看起来是正确的方式..如果你接受dynamodb的帮助(不是另一个db,因为需求非常小;为什么还有另一个ec2实例只是为了这个)怎么办...每当一个lambda函数完成它并更新dynamodb中的记录..如果db中的这个值大于100 - >执行你的最终lambda函数..

号码是否固定为100?或者它可以是任何数字..如果它可以是任何数字n;那么我也可以考虑解决这个问题......

你的问题的解决方案“api调用发生在lambda 0,你需要回复”,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 ..一旦完成;主节点整理所有数据并返回响应。