1. c9katayama

    Posted

    c9katayama
Changes in title
+AWS Lambda JavaでLambdaFunctionで発生した例外の処理について
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,136 @@
+#はじめに
+AWS Lambdaで、呼び出し元/呼び出し先ともにJavaを使った際の例外処理についてまとめてみました。
+
+#テスト用のクラス
+##Lambda Functionクラス
+AWS Lambdaに登録するためのクラスです。
+
+```java
+package lambdatest;
+
+import java.time.LocalDateTime;
+
+import com.amazonaws.services.lambda.runtime.Context;
+
+public class Lambda {
+
+ public String ok(Object o, Context context) {
+ context.getLogger().log("OK " + LocalDateTime.now());
+ return "OK";
+ }
+
+ public String timeout(Object o, Context context) {
+ try{
+ Thread.sleep(TimeUnit.SECONDS.toMillis(100));
+ }catch(Exception e){
+
+ }
+ context.getLogger().log("Timeout " + LocalDateTime.now());
+ return "Timeout";
+ }
+
+ public String runtimeException(Object o, Context context) {
+ context.getLogger().log("RuntimeException " + LocalDateTime.now());
+ throw new RuntimeException("RuntimeException");
+ }
+
+ public String exception(Object o, Context context) throws Exception {
+ context.getLogger().log("exception " + LocalDateTime.now());
+ throw new Exception("Exception");
+ }
+}
+```
+
+##Lambdaの呼び出しコード
+登録したLambdaを呼び出すクライアントクラスです。
+
+```java
+package lambdatest;
+
+import com.amazonaws.regions.Region;
+import com.amazonaws.regions.Regions;
+import com.amazonaws.services.lambda.AWSLambdaClient;
+import com.amazonaws.services.lambda.model.InvokeRequest;
+import com.amazonaws.services.lambda.model.InvokeResult;
+
+public class InvokeLambda {
+
+ public static void main(String[] args) {
+ AWSLambdaClient lambda = new AWSLambdaClient();
+ lambda.setRegion(Region.getRegion(Regions.AP_NORTHEAST_1));
+ InvokeRequest req = new InvokeRequest();
+ req.setFunctionName("LambdaTest");
+ req.setPayload("{\"hoo\":\"bar\"}");
+ try {
+ InvokeResult invoke = lambda.invoke(req);
+ String res = new String(invoke.getPayload().array());
+ System.out.println(res);
+ System.out.println(invoke.getFunctionError());
+ System.out.println(invoke.getStatusCode());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
+```
+
+#呼び出し時の挙動確認
+上記のテストクラスを使って、呼び出すLambdaのメソッドごとの挙動を確認した結果が以下となります。
+
+##OKのパターン
+正常パターン。lambdatest.Lambda::ok を呼び出す。処理は成功して、"OK"という文字列が返って来ます。
+
+```
+Payload:"OK"
+FunctionError:null
+StatusCode:200
+```
+
+##Timeoutのパターン
+lambdatest.Lambda::timeoutを呼び出すと処理がタイムアウトする。
+呼び出し元では例外は発生せず、タイムアウト時に以下のPayload,FunctionError,StatusCodeが返ってきます。
+
+```
+Payload:{"errorMessage":"2016-02-19T10:10:00.159Z e59b6744-d6f0-11e5-9eae-c56145704801 Task timed out after 15.00 seconds"}
+FunctionError:Unhandled
+StatusCode:200
+```
+
+##RuntimeExceptionのパターン
+lambdatest.Lambda::runtimeExceptionを呼び出すとRuntimeExceptionがすろーされる。
+呼び出し元では例外は発生せず、タイムアウト時に以下のPayload,FunctionError,StatusCodeが返ってきます。
+
+```
+Payload:{"errorMessage":"RuntimeException","errorType":"java.lang.RuntimeException","stackTrace":["lambdatest.Lambda.runtimeException(Lambda.java:28)","sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)","sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)","sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)","java.lang.reflect.Method.invoke(Method.java:497)"]}
+FunctionError:Unhandled
+StatusCode:200
+```
+
+##Exceptionのパターン
+Payloadに入っている例外クラス名がExceptionとなっていだけで、あとはRuntimeExceptionと同じです。
+
+##LambdaのHandler設定が間違っていた時
+AWS LambdaのHandler設定が誤っており、呼び出し先クラスやメソッドがない場合。
+この場合でも呼び出し元では例外は発生せず、タイムアウト時に以下のPayload,FunctionError,StatusCodeが返ってきます。
+
+```
+Payload:{"errorMessage":"No public method named ERRORHANDLER with appropriate method signature found on class class lambdatest.Lambda"}
+FunctionError:Unhandled
+StatusCode:200
+```
+
+##例外処理の方法
+結論として、AWSクレデンシャル/リージョン/FunctionNameが正しければ、Lambda側で例外が発生してもクライアント側では例外がすろーされないため、InvokeResultの中身を見て、エラーかどうかを判断する必要があります。
+InvokeResult#getFunctionError()の戻り値がnullでない場合はエラーが発生しているとみなしてもよさそうなので、この場合はPayloadからエラー内容を取り出し、適宜メッセージを取り出してログを吐いたりリトライする形になります。
+
+なおAWSクレデンシャル間違いの場合はcom.amazonaws.AmazonServiceException、リージョンやFunctionNameが違う場合はcom.amazonaws.services.lambda.model.ResourceNotFoundExceptionが発生するため、これは別途catchして例外処理を行う必要があります。
+
+
+
+
+
+
+
+
+
+