一般來說,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
沒有留言:
張貼留言