多个并行AWS Lambda调用

时间:2019-02-26 07:26:14

标签: amazon-web-services aws-lambda python-asyncio python-3.7

我正在尝试使用python 3.7.2和aiobotocore软件包执行多个AWS Lambda调用。这是我的代码。

import asyncio
import aiobotocore


async def invoke(payload, session):
    async with session.create_client('lambda', region_name='us-east-1') as client:
        return await client.invoke(FunctionName='MY_FUNCTION', Payload=payload)


def generate_invocations(payloads, session):
    for payload in payloads:
        yield invoke(payload, session)


def invoke_all(payloads):
    loop = asyncio.get_event_loop()

    async def wrapped():
        session = aiobotocore.get_session(loop=loop)
        invocations = generate_invocations(payloads, session)
        return await asyncio.gather(*invocations)

    return loop.run_until_complete(wrapped())


def main():
    payloads_list = []  # MY PAYLOADS LIST 
    lambda_responses = invoke_all(payloads_list)
    print(lambda_responses)


if __name__ == '__main__':
    main()

代码运行得非常快(对于1秒钟左右的10个有效负载,而不是使用boto3 lambda客户端调用的15个有效负载),但是我遇到两个问题:

1)lambda_responses中的元素包括“ Payload”键,其值类型为aiobotocore.response.StreamingBody。当我尝试value.read()时,我收到“协程对象StreamingBody.read”,并且我认为代码中存在一些问题。我可以通过“ json.loads(json.loads(r ['Payload'] ._ buffer.pop())['body'])”接收所需的响应,但是正确的获取方法是什么。

2)在极少数情况下,响应之一中的“有效负载”具有空缓冲区。如何确保invoke_all函数返回非空响应?正确使用aiobotocore吗?

我是python 3和异步功能的新手。受aiobotocore文档和Mathew Marcus blog的示例的启发。

谢谢!

1 个答案:

答案 0 :(得分:2)

  

1)lambda_responses中的元素包括“ Payload”键,其值类型为aiobotocore.response.StreamingBody。当我尝试value.read()时,我收到“协程对象StreamingBody.read”

这意味着将等待read()协程,而您仍应在事件循环中执行此操作。例如,您可以更改invoke协程以同时读取响应:

async def invoke(payload, session):
    async with session.create_client('lambda', region_name='us-east-1') as client:
        resp = await client.invoke(FunctionName='MY_FUNCTION', Payload=payload)
        payload = await r['Payload'].read()
        return payload  # or assemble a dict with relevant parts
  

2)在极少数情况下,响应之一中的“有效负载”具有空缓冲区。

这可能是因为您在实际读取内容之前正在访问缓冲区。在某些情况下,信息很快就会到达,以至于无论如何您都可以在内部缓冲区中找到它,但是有时您必须等待它。使用read()之类的公共方法可确保您正确使用了API。另一方面,_buffer属性以下划线开头,这表示它是一个实现细节,不能直接访问。