Created
December 4, 2016 01:09
-
-
Save sangheestyle/1fb5655d4230dda14dbf75e3f00f99ed to your computer and use it in GitHub Desktop.
invoke aws lambda from another lambda
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import unicode_literals | |
import base64 | |
from datetime import datetime, timedelta | |
import random | |
import string | |
import json | |
import zlib | |
from concurrent.futures import ThreadPoolExecutor, as_completed | |
import boto3 | |
client = boto3.client('lambda') | |
def random_word(length): | |
return ''.join(random.choice(string.letters) | |
for i in range(length)) | |
def random_sentence(): | |
return ''.join(random_word(8) for i in range(100)) | |
def invoke_lambda(): | |
user_comment = random_sentence() | |
text_data = json.dumps( | |
{x: user_comment for x in range(100)}) | |
payload = json.dumps( | |
base64.b64encode(zlib.compress(text_data))) | |
begin = datetime.now() | |
response = client.invoke( | |
FunctionName='minsky-dedup-stage-dedup', | |
InvocationType='RequestResponse', | |
Payload=payload | |
) | |
result = response["Payload"].read() | |
end = datetime.now() | |
return {"duration": end - begin, "result": result} | |
num_concurrent = 1000 | |
durations = [] | |
results = [] | |
begin = datetime.now() | |
with ThreadPoolExecutor(max_workers=num_concurrent) as e: | |
future_to_order = {e.submit(invoke_lambda): i | |
for i in range(num_concurrent)} | |
for future in as_completed(future_to_order): | |
order = future_to_order[future] | |
try: | |
data = future.result() | |
except Exception as exc: | |
print('{} generated an exception: {}'.format(order, exc)) | |
else: | |
results.append(data["result"]) | |
durations.append(data["duration"]) | |
end = datetime.now() | |
print("min: {}".format(min(durations))) | |
print("max: {}".format(max(durations))) | |
print("avg: {}".format(sum(durations, timedelta(0)) / len(durations))) | |
print("duration for {} requests: {}".format(len(durations), end - begin)) | |
""" | |
Result | |
min: 0:00:00.025017 | |
max: 0:00:00.872450 | |
avg: 0:00:00.113591 | |
duration for 1000 requests: 0:00:04.300826 | |
""" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
어제 AWS 람다 관련해서 궁금한게 있어서 오늘 시간 내서 잠시 해봤다.
https://gist.github.com/sangheestyle/1fb5655d4230dda14dbf75e3f00f99ed
1. AWS 람다의 request limit
현재 AWS 람다(이하 람다)는 Safety limit 이 있어서 아래 공식에 의거해서 request rate 을 100까지만 허용한다.
request rate = number of concurrent executions / function duration
가령 5초 걸리는 람다 펑션을 10개 한 번에 돌렸다면
2 = 10 / 5
가 된다. 그러니까 만약 해당 펑션을 500개 한 꺼번에 돌리면 request rate 가 500이 되므로 safety limit 에 걸리고, 딜레이가 생긴다.
http://docs.aws.amazon.com/lambda/latest/dg/concurrent-executions.html
이게 왜 safety limit 이냐면 운이 나빠서 누가 실수해서 한 꺼번에 잔뜩 돌리면 그게 비용이 엄청 올라가기 때문이다. 만약 safety limit 을 올리려면 따로 아마존에 요청해야 한다. (위 링크)
이걸 한번 돌려봤는데 약 0.5초 정도 걸리는 펑션을 파이썬의 concurrent.future.ThreadPoolExecutor 를 이용해서 max_workers=1000 으로 돌려봤다. 이 경우에 대해서 request rate 를 구해보면
500 = 1000 / 0.5
이 되므로 다섯 번에 걸쳐서 작업하는 것이나 마찬가지인 경우가 되므로 전체를 다 처리하는데 최소 2.5초 이상 걸리게 되는 것이다. 실제로는 4초 정도 걸렸다.
그러니까 람다를 어떠한 용도로 사용하느냐... 에 따라서 펑션 배치를 좀 다르게 해야할 것이다. 가령 같은 용도의 펑션을 여러개 만들어서 중간에 풀을 만들어서 돌리는 것도 필요하다면 가능하겠고, 아니면 위에 나온데로 아마존에 연락해서 올려달라 하는 방법도 있겠고.
2. 람다의 제한시간
람다는 펑션을 하나 돌리는데 5분까지 (300초)만 허용한다. 그러니까 그 이상이라면 함수를 쪼개거나 하는 식으로 해야 할 것이다. (200초 -> 200 초 -> 200초)
그런데 하나 알아둬야 하는 경우는 람다를 API Gateway(이하 APIG) 와 연결해서 API를 바로 웹으로 빼주는 경우는 APIG의 timeout 이 30초라서 람다가 5분까지 돌아도 실제 HTTP 500 을 클라이언트는 받게 된다. 따라서 이 경우도 잘 생각을 해야 할 것이다.
3. 람다 함수 간에 주고받기
람다 함수간에 데이터를 주고 받을 수 있는데 람다의 event 를 가지고 주고 받으면 된다. 그런데 이때에도 한 가지 문제가 발생하는데 무엇이냐면 event 의 크기가 제한된다는 것이다. 그러니까 무작정 클 수 없다.
그래서 나는 이벤트에 대한 페이로드를 아래와 같이 생성했다.
보내려는 원문(text_date)를 압축해서 base64 인코드 해서 json으로 만들었다. json 은 유니코드로 정의되어 있어야 하는데 zlib 으로 압축을 하면 UTF-8 으로 된다. 그래서 에러가 생기는데, 이때 base64로 인코딩을 해주면 된다. 이렇게 하고 나면 데이터 사이즈가 상당히 줄어든다. (텍스트에 따라 다르지만)
http://stackoverflow.com/questions/3929301/utf-8-compatible-compression-in-python
요런거 좀 이해하고 넘어갈만 하다.