唐突ですが、我が家の課題に『ゴミ出しを忘れる』というのがあります。たまに、家に帰って扉開けたらやばいニオイがして、激しく後悔します。ということで、LINEへ毎朝のゴミ出しの通知をしてみました。
という建前の AWS Lambda と LINE Notify 触ってみた系の記事です。
結論を先に言うと、LINEに定期的に通知するだけのボットが完成します。
目次
AWS Lambda とは
AWSが提供するマネージドサービスの一つ。
AWS Lambda (サーバーレスでコードを実行・自動管理) | AWS
コードをアップロードさえすれば、インフラを管理することなくコードを実行できるのが利点。AWS Lambda上の様々なイベントを契機にできる。
- S3のアップロード
- CloudWatch Logsに書き込まれた特定ログ
- Dynamo DBのデータ更新
- CloudWatch Eventsによる定期イベント(cron的な)
実装
こんなイメージで連携させる。
AWS Lambda で実行するコードを作成する
おおまかに以下の手順。
- mavenで依存関係を追加する
- ハンドラを実装する
- fat jarを作る
『AWS Toolkit for Eclipse』を入れると、コード作成が簡素化できるらしい。
が、今回はお試しなので、すべて自前で作る。
mavenで依存関係を追加する
awsのcoreライブラリを追加する。
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.2.0</version>
</dependency>
ハンドラを実装する
以下を参考に、Javaのコードを書く。
Lambda 関数ハンドラー (Java) - AWS Lambda
package garbage.notification; import ... public class App implements RequestHandler<Integer, String> { private static final String ACCESS_TOKEN = "SECRET_ACCESS_TOKEN"; private static final String API = "https://notify-api.line.me/api/notify"; @Override public String handleRequest(Integer count, Context context) { Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Asia/Tokyo")); switch (cal.get(Calendar.DAY_OF_WEEK)) { case Calendar.SUNDAY: break; case Calendar.MONDAY: post("今日は生ごみの日"); break; case Calendar.TUESDAY: post("今日は燃やさないゴミの日(第2,第4の週なら)"); break; case Calendar.WEDNESDAY: post("今日は生ごみの日"); break; case Calendar.THURSDAY: break; case Calendar.FRIDAY: post("今日は生ごみの日"); break; case Calendar.SATURDAY: post("今日はプラスチックゴミの日"); break; } return "success"; }
RequestHandler<T1, T2> は AWS Lambdaのハンドラのインタフェース。
- T1は 入力の型
- T2は 出力の型
T2 handleRequest(T1, Context) はハンドラメソッド。
- 引数の Context には AWSの実行環境に関する情報が格納される
- requestIDなど
今回は時刻による定期実行イベントのため、リクエストもレスポンスも適当なプリミティブ型を指定しておく。
次に、HTTPのPOST部分を作成する。
特に変わったところはないので説明は省略する。
public static void post(String msg) { RestTemplate restTemplate = new RestTemplate(new SimpleClientHttpRequestFactory()); try { MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>(); params.add("message", msg); HttpHeaders headers = new HttpHeaders(); headers.setContentType(new MediaType(MediaType.APPLICATION_FORM_URLENCODED, Charset.forName("utf-8"))); headers.add("Authorization", "Bearer " + ACCESS_TOKEN); RequestEntity req = new RequestEntity(params, headers, HttpMethod.POST, new URI(API)); restTemplate.exchange(req, String.class); } catch (URISyntaxException e) { e.printStackTrace(); } } }
fat jarを作る
以下を参考に、mavenを利用してfat jarを作る。
IDE なしで Maven を使用した .jar デプロイパッケージの作成 (Java) - AWS Lambda
AWSの公式では maven-shade-plugin が例に挙げられているけど maven-assembly-plugin でも動いた。classファイルがすべて含まれた fat jar 形式であることが重要なんでしょう。たぶん。
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.3</version> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
お金の話
無料枠内で使える時間は、利用するメモリに依存するらしく、128MBであれば 3,200,000s が目安になる。ということは 3,200,000s / 15s = 213333 回は実行できるので、当分はお金面の心配はなさそう。
料金体系の詳細はリファレンスを参照してください。
料金 - AWS Lambda(サーバーレスでコードを実行)|AWS