唐突ですが、我が家の課題に『ゴミ出しを忘れる』というのがあります。たまに、家に帰って扉開けたらやばいニオイがして、激しく後悔します。ということで、LINEへ毎朝のゴミ出しの通知をしてみました。
という建前の AWS Lambda と LINE Notify 触ってみた系の記事です。
結論を先に言うと、LINEに定期的に通知するだけのボットが完成します。
目次
AWS Lambda とは
AWSが提供するマネージドサービスの一つ。
AWS Lambda (サーバーレスでコードを実行・自動管理) | AWS
コードをアップロードさえすれば、インフラを管理することなくコードを実行できるのが利点。AWS Lambda上の様々なイベントを契機にできる。
- S3のアップロード
- CloudWatch Logsに書き込まれた特定ログ
- Dynamo DBのデータ更新
- CloudWatch Eventsによる定期イベント(cron的な)
LINE Notify とは
LINEのチャンネルにメッセージを通知できる連携サービス。
実装
こんなイメージで連携させる。
LINE Notify でパーソナルアクセストークンを発行する
今回はパーソナルアクセストークンを利用する。
トークンを付けてリクエストすることで、チャンネルに任意のメッセージを送れる。
[超簡単]LINE notify を使ってみる - Qiitaqiita.com
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>
https://aws.amazon.com/jp/lambda/pricing/
定期実行するイベントを作成する
CloudWatchサービスに移動し、時刻起動のイベントを作成する。
cron式は UTC 時間のため、 JST(日本時間) から -9 時間したものを指定する。
AWS Lambda の設定をする
関数を作成する。
関数コードを設定する
CloudWatchEvents を指定する
- 作成した定期実行イベントを指定する
テストする
『テストイベントの設定』をクリックする。
今回はリクエストの型をIntegerとしたため、数値を指定する。
実際にはアプリケーションコードで引数を使ってないので、意味はない。
テストを実行すると、結果が表示される。
また、LINEにも通知されている。
CloudWatch Eventsの入力値を設定する
CloudWatchで作成したイベントの編集にうつり、ターゲット > 入力の設定 で入力値を設定する。
お金の話
無料枠内で使える時間は、利用するメモリに依存するらしく、128MBであれば 3,200,000s が目安になる。ということは 3,200,000s / 15s = 213333 回は実行できるので、当分はお金面の心配はなさそう。
料金体系の詳細はリファレンスを参照してください。
料金 - AWS Lambda(サーバーレスでコードを実行)|AWS