Ber*_*one 1 amazon-web-services python-3.x python-asyncio boto3 aws-lambda
我最近发布了一个有关如何仅允许从VPC内的EC2实例调用AWS Lambda函数的问题。通过将带有“ AWS lambda角色”策略的IAM角色附加到EC2实例,我设法使其正常工作,现在我可以使用boto3调用lambda函数。
现在,我想使用asyncio await语法异步调用lambda函数。我读到lambda函数通过设置提供了一个异步版本InvokeType='Event',但是实际上使调用立即返回而没有得到函数的结果。
由于函数需要一些时间,因此我想并行启动许多函数,因此我想避免在等待函数返回时阻塞执行。
我尝试使用aiobotocore,但这仅支持基本的“ s3”服务功能。
解决这个问题的最佳方法(谦虚)是使用AWS API Gateway服务通过GET / POST请求调用lambda函数,该请求可以使用aiohttp轻松处理。
但是,我无法使其正常运行。
我在EC2 IAM角色中添加了策略“ AmazonAPIGatewayInvokeFullAccess”,但每次尝试执行以下操作:
import requests
r = requests.get('https://url_to_api_gateway_for_function')
Run Code Online (Sandbox Code Playgroud)
我得到禁止的回应<Response [403]>。
我直接使用lambda函数中的触发器创建了API网关。
我还尝试编辑API网关设置,方法是在函数路径中添加post方法并设置“ AWS_IAM”身份验证,然后将其部署为“ prod”部署。仍然是相同的禁止响应。当我通过“ API网关上的测试屏幕”对其进行测试时,它可以正常工作。
任何想法如何解决这个问题?我错过了一步吗?
经过一些努力,我设法解决了我的问题。
问题在于,curl和python模块(例如python的请求)不会使用运行它们的EC2计算机的IAM凭据对http请求进行签名。对AWS GATEWAY API的http请求必须使用AWS v4登录协议进行签名。
此处是一个示例:http : //docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
幸运的是,为了简单起见,有一些帮助器模块,例如request-aws-sign:https : //github.com/jmenga/requests-aws-sign
最后,代码可能类似于:
import aiohttp
import asyncio
from requests_aws_sign import AWSV4Sign
from boto3 import session
session = session.Session()
credentials = session.get_credentials()
region = session.region_name or 'ap-southeast-2'
service = 'execute-api'
url = "get_it_from_api->stages->your_deployment->invoke_url"
auth=AWSV4Sign(credentials, region, service)
async def invoke_func(loop):
async with aiohttp.request('GET', url, auth=auth, loop=loop) as resp:
html = await resp.text()
print(html)
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))
Run Code Online (Sandbox Code Playgroud)
希望这可以节省其他人的时间!
编辑:
为了完整性和帮助他人,我不得不说,由于requests_aws_sign与aiohttp不兼容的事实,上面的代码不起作用。我收到一些“验证字段错误”。
我试图通过使用以下方法解决它:
async with session.get(url, headers=update_headers()) as resp:
Run Code Online (Sandbox Code Playgroud)
其中update_headers()是一个简单的函数,用于模仿requests_aws_sign对标头所做的操作(这样,我就可以使用header参数将它们直接设置为上述请求)。看起来像这样:
def update_headers(sim_id):
url = urlparse("get_it_from_api->stages->your_deployment->invoke_url")
path = url.path or '/'
querystring = ''
if url.query:
querystring = '?' + urlencode(parse_qs(url.query), doseq=True)
safe_url = url.scheme + '://' + url.netloc.split(':')[0] + path + querystring
request = AWSRequest(method='GET', url=safe_url)
SigV4Auth(credentials, service, region).add_auth(request)
return dict(request.headers.items())
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4950 次 |
| 最近记录: |