Amazon AthenaをAWS Lambdaから操作できるようにしてみた

  • 13
    いいね
  • 0
    コメント

Amazon Athenaがリリースされてから、できるだろう、というイメージがあったのでやってみました。現在jdbc接続しかできなさそうなので、Lambdaは必然的にJavaで記述することになります。

結果

結果だけ見たい人はこちらをどうぞ。ただ、「とりあえず動く」コードになっています。

https://github.com/kojiisd/aws-lambda-athena

制限事項

  1. 取得している値は全て文字列として扱っています。他の型で受け取りたい場合はソースを修正する必要があります。
  2. 見ればわかりますが、適切な例外の処理などはほとんどないです(これが「とりあえず動くコード」の原因)。きちんと使いたい場合はご自身で足りない分を実装してください。

やりたいこと

  1. Amazon AthenaにLambdaからアクセスできるプログラムの作成
  2. できるだけ柔軟に欲しい情報を取れるようにしたい

結果として、入力用JSONに期待するカラムも記述するようにしました。

準備

Credentialの準備

src/main/resources/config/credentialのファイルの中身を埋めてください。AthenaとLambda実行の権限があるアクセスキーを記述すれば大丈夫だと思います。

媒体作成

以下のコマンドで依存ライブラリを含んだjarファイルを作成してください。

$ mvn clean package

この時"clean"オプションはつけてください。pom.xmlを見ればわかりますが、Athenaのjarファイルを成果物に含めるために以下の設定をしています。

pom.xml
<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で叩いてみます。

スクリーンショット 2016-12-23 11.45.07.png

それでは準備していたスクリプトをLambda上で実行します。

0e72db35-9f83-1b56-4c28-8739d3277ea4.png

とりあえず何かしら値が取れたようですが、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に貼り付けてみると、、、

スクリーンショット 2016-12-23 12.18.04.png

件数も並び方も一緒ですね、素晴らしい!

まとめ

AthenaにLambdaからアクセスすることができるようになりました。が、見ての通り処理は重いしコストがかかりまくりですね。このレベルであればPythonとかNode.jsでサクッと書きたいものです。Athenaの接続が他の言語からもできるようになることを期待しています。

今回書いたコードを応用すれば、CRUDはもちろん、複数の型の取得に対応させることも可能ですので、もしやる気が出れば(笑)次回そちらもやってみようかと思います。