Amazon Athenaがリリースされてから、できるだろう、というイメージがあったのでやってみました。現在jdbc接続しかできなさそうなので、Lambdaは必然的にJavaで記述することになります。
結果
結果だけ見たい人はこちらをどうぞ。ただ、「とりあえず動く」コードになっています。
制限事項
- 取得している値は全て文字列として扱っています。他の型で受け取りたい場合はソースを修正する必要があります。
- 見ればわかりますが、適切な例外の処理などはほとんどないです(これが「とりあえず動くコード」の原因)。きちんと使いたい場合はご自身で足りない分を実装してください。
やりたいこと
- Amazon AthenaにLambdaからアクセスできるプログラムの作成
- できるだけ柔軟に欲しい情報を取れるようにしたい
結果として、入力用JSONに期待するカラムも記述するようにしました。
準備
Credentialの準備
src/main/resources/config/credentialのファイルの中身を埋めてください。AthenaとLambda実行の権限があるアクセスキーを記述すれば大丈夫だと思います。
媒体作成
以下のコマンドで依存ライブラリを含んだjarファイルを作成してください。
$ mvn clean package
この時"clean"オプションはつけてください。pom.xmlを見ればわかりますが、Athenaのjarファイルを成果物に含めるために以下の設定をしています。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<executions>
<execution>
<id>install-external</id>
<phase>clean</phase>
<configuration>
<file>${basedir}/lib/AthenaJDBC41-1.0.0.jar</file>
<repositoryLayout>default</repositoryLayout>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-athena</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<generatePom>true</generatePom>
</configuration>
<goals>
<goal>install-file</goal>
</goals>
</execution>
</executions>
</plugin>
Lambdaへのアップロード
作成したjarファイルをLambdaにアップロードしてください。この時Jarのファイルサイズが10MBを超える大きなものになると思うので、LambdaへのアップロードはS3を使った方が便利です(Lambdaもそう推奨しています)
入力用のJSONの準備
今回入力としては以下のパラメータを想定しています。
No | Column Name | Description | Required |
---|---|---|---|
1 | region | リージョン名 | false |
2 | s3Path | SQLを保持する先のS3パス | true |
3 | sql | SQL | true |
4 | columnListStr | 取得したいカラムのリスト(カンマ区切り) | true |
リージョンは現在us-east-1かus-west-2のみ対応しています。Lambdaでテストする場合は上記を含んだJSONを送ってあげれば実施できます。リージョンを指定する場合は、S3のバケットのリージョンと接続先Athenaのリージョンを合わせるようにしてください。
{
"region": "us-east-1",
"s3Path": "s3://ishida-athena-staging-dir/",
"sql": "SELECT elbname, requestip, requestport, backendip, backendport, requestprocessingtime, backendprocessingtime, timestamp FROM sampledb.elb_logs order by timestamp desc limit 10",
"columnListStr": "elbname, requestip, requestport, backendip, backendport, requestprocessingtime, backendprocessingtime, timestamp"
}
実施する際のLambdaのスペック設定ですが、メモリは少なくとも192MB,タイムアウトは30秒ほどは見ておいた方が良いかと思います。メモリ128MBで実施したらOutOfMemoryが出てしまいました。(デフォルトだとメモリ512MB、タイムアウト15秒だったかな。それはそれで今回は不適切です)
実行
Lambdaスクリプトを実行してみます。今回アクセス先は「sampledb」にします。Athenaを利用開始するとデフォルトで設定されるアレです。
まず、今回実施しようとしているクエリをそのままAthenaで叩いてみます。
それでは準備していたスクリプトをLambda上で実行します。
とりあえず何かしら値が取れたようですが、Lambdaのコンソールは見づらい。。。
CloudWatchでログ内容を確認します。(というかLambda処理に20秒もかかってますね。。。初回実行とはいえなかなか厳しい性能です^^;)
あとLogger周りでWARNログが出ていますが、ここでは気にしません。
Input parameter:jp.gr.java_conf.kojiisd.lambdaathena.dto.Request@6e38921c[
region=us-east-1
s3Path=s3://ishida-athena-staging-dir/
sql=SELECT elbname, requestip, requestport, backendip, backendport, requestprocessingtime, backendprocessingtime, timestamp FROM sampledb.elb_logs order by timestamp desc limit 10
columnListStr=elbname, requestip, requestport, backendip, backendport, requestprocessingtime, backendprocessingtime, timestamp
]
result:
elbname, requestip, requestport, backendip, backendport, requestprocessingtime, backendprocessingtime, timestamp
lb-demo,246.140.190.136,63777,250.193.168.100,8888,7.2E-5,0.379241,2014-09-30T01:28:17.587188Z
lb-demo,246.129.63.235,10182,251.36.119.81,8888,4.7E-5,0.013368,2014-09-30T01:18:08.310452Z
lb-demo,248.214.120.18,25187,249.205.250.232,8000,5.9E-5,0.014451,2014-09-30T01:18:08.294613Z
lb-demo,249.125.138.56,64948,241.35.85.250,8888,6.6E-5,0.023272,2014-09-30T01:18:08.266146Z
lb-demo,247.161.61.55,2700,254.243.154.128,8888,7.5E-5,0.026167,2014-09-30T01:18:08.264297Z
lb-demo,241.35.85.250,10182,248.214.120.18,443,4.6E-5,0.013153,2014-09-30T01:18:08.225343Z
lb-demo,250.165.161.74,25187,249.45.101.192,8888,4.8E-5,0.013252,2014-09-30T01:18:08.207854Z
lb-demo,247.161.61.55,2700,248.14.80.185,8888,4.8E-5,0.015274,2014-09-30T01:18:08.175776Z
lb-demo,249.45.101.192,64948,247.161.61.55,8888,1.15E-4,0.020176,2014-09-30T01:18:08.162703Z
lb-demo,253.51.141.83,10182,243.16.92.84,8888,6.6E-5,0.015285,2014-09-30T01:18:08.130488Z
なんとなくそれっぽい結果が出ています。一応Excelに貼り付けてみると、、、
件数も並び方も一緒ですね、素晴らしい!
まとめ
AthenaにLambdaからアクセスすることができるようになりました。が、見ての通り処理は重いしコストがかかりまくりですね。このレベルであればPythonとかNode.jsでサクッと書きたいものです。Athenaの接続が他の言語からもできるようになることを期待しています。
今回書いたコードを応用すれば、CRUDはもちろん、複数の型の取得に対応させることも可能ですので、もしやる気が出れば(笑)次回そちらもやってみようかと思います。