一般來說,Lambda 都是透過中介服務去觸發的
例如透過 DynamoDB Stream、SNS、Kinesis、S3 等等的
當這些服務發生變更時,發送訊息觸發 Lambda。
不過實務上,Lambda 本身只要具備 Invoke 權限,就能夠直接透過 AWS 的 Lambda API 去觸發另一個 Lambda。
範例
在下面這個範例中,是實驗的是呼叫自己,並且把呼叫的 counter 增加,直到呼叫自己的次數超過 3 次時就停止。
Maven 設定檔
Maven 的設定中,最重要的地方在於要加入 Lambda SDK。
這裡用的 AWS SDK 版本是 1.11.202,不過其實現在還有更新的版本了。
<properties> <aws.version>1.11.202</aws.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-bom</artifactId> <version>${aws.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencyManagement> <dependencies> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.6.2</version> </dependency> <!-- AWS --> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-lambda</artifactId> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> <version>1.1.0</version> </dependency> </dependencies>
稍微複習 (?) 一下,Maven 中的「aws-lambda-java-core」是 Lambda 的套件,讓我們可以實作 RequestHandler
而「aws-java-sdk-lambda」則是 AWS 的 Lambda SDK,是為了操作 AWS 的 Lambda API(也就是用來管理 AWS Lambda 的 API)。
「commons-io」和「gson」則是下面程式碼會用到的東西,分別是讀取 Lambda 輸入的串流以及把他們解析成 JSON 物件。
程式碼
public class EventHandler implements RequestStreamHandler { private static final Logger LOGGER = LoggerFactory.getLogger(EventHandler.class); @Override public void handleRequest( InputStream input, OutputStream output, Context context) throws IOException { try { String str = IOUtils.toString(input, StandardCharsets.UTF_8); LOGGER.trace("Source message: {}", str); handleRequest( new JsonParser().parse(str).getAsJsonObject(), context); } catch (Throwable t) { LOGGER.error("Error when handling a request.", t); } } protected void handleRequest (JsonObject json, Context context) { int count = (json.has("count")) ? json.get("count").getAsInt() : 1; // Terminate the self-triggering if it triggers 3 times. if (count < 3) { LOGGER.debug("Attempt to trigger itself ‘{}’: {}", context.getFunctionName(), count); AWSLambdaAsync client = AWSLambdaAsyncClientBuilder.defaultClient(); JsonObject eventContent = new JsonObject(); eventContent.addProperty("count", ++count); InvokeRequest request = new InvokeRequest() .withFunctionName(context.getFunctionName()) .withInvocationType(InvocationType.Event) .withPayload(eventContent.toString()); InvokeResult result = client.invoke(request); LOGGER.debug("Invoke result status: {}", result.getStatusCode()); } } }
上述程式碼中,主要分為兩個部份:
- #5 ~ #19 是實作接收事件的介面,會把接收到的事件內容轉換成 JSON 格式。
- #21 ~ #41 是解析事件的內容,並且決定是否要再次呼叫自己。
而真正呼叫自己的部份,就是 #28 ~ #37 行。
#28 行先建立一個非同步的 Lambda Client,非同步的意思是,呼叫 AWS Lambda API 時,會馬上得到一個具有 Future 特性的結果
可以不用實際地等待 AWS Lambda API 的回應。
#33 ~ #37 是決定要如何呼叫 Lambda 的方法。
具體來說,因為是要呼叫自己,因此設定了 withFunctionName() 是指定自己的函式名字。
而呼叫時,我想要射後不理,亦即我不要等待呼叫的 Lambda 告訴我結果,我只想要丟個東西給它,然後它就自己去跑自己的。
因此這裡設定 InvocationType 是 Event~這就是屬於射後不理的類型。
如果想要的是呼叫後還要取得 Lambda 執行後回傳的結果,那就應該要用 RequestResponse 這個類型。
(但這時要記得 Lambda 的執行時間最長只能 5 分鐘,等待別的 Lambda 執行時,自己的 5 分鐘血條依然在扣血~)
最後,因為要告訴下一個自己一些訊息,因此要設定 Payload。
執行結果
執行結果在 CloudWatch 上,大概會跑出類似這樣的 log。
START RequestId: a4d562af-d0e7-11e7-b8c8-b3b93b225046 Version: $LATEST 19.345 | EventHandler | Source message: {"key3": "value3","key2": "value2","key1": "value1"} 19.543 | EventHandler | Attempt to trigger itself ‘my_self_triggered_function’: 1 38.637 | EventHandler | Invoke result status: 200 END RequestId: a4d562af-d0e7-11e7-b8c8-b3b93b225046 REPORT RequestId: a4d562af-d0e7-11e7-b8c8-b3b93b225046 Duration: 19306.95 ms Billed Duration: 19400 ms Memory Size: 512 MB Max Memory Used: 107 MB START RequestId: aad79f94-d0e7-11e7-8e7b-91c27f1bebea Version: $LATEST 28.727 | EventHandler | Source message: {"count": 2} 28.907 | EventHandler | Attempt to trigger itself ‘my_self_triggered_function’: 2 END RequestId: aad79f94-d0e7-11e7-8e7b-91c27f1bebea REPORT RequestId: aad79f94-d0e7-11e7-8e7b-91c27f1bebea Duration: 9813.51 ms Billed Duration: 9900 ms Memory Size: 512 MB Max Memory Used: 86 MB START RequestId: b0879db9-d0e7-11e7-9e0f-9d2befc8992a Version: $LATEST 38.239 | EventHandler | Source message: {"count": 3} END RequestId: b0879db9-d0e7-11e7-9e0f-9d2befc8992a REPORT RequestId: b0879db9-d0e7-11e7-9e0f-9d2befc8992a Duration: 228.63 ms Billed Duration: 300 ms Memory Size: 512 MB Max Memory Used: 37 MB
沒有留言:
張貼留言