elastic4s の json ライブラリ切り替えの実装にちょっと感動してる話
いつかの続き
elastic4s/package.scala at master · sksamuel/elastic4s · GitHub
で、件のコードがこの辺り。ひっじょうに薄くて、なんと 1 ファイルだけだったりします。
以前フォーマッター切り替えについて考えた記事を書きましたが、さらに先にある実現方法がこれか! と感動しております。
そうだよなー。中間の型クラス作って、委譲すればできるよな。
Kinesis Firehose のデータ変換 Lambda を Golang で作って計測してみた
概要
前回 やるといってたやつです。
AWS Lambda が Golang を公式サポートしたので、これまでやってきたのと同じような Lambda を作って計測してみました。
先に結果だけ書くと、
- Rust: 55.8 k レコードを 23.4 秒で処理
=> 1 秒あたり約 2384.6 レコードを処理 - Python: 56.7 k レコードを 397 秒で処理
=> 1 秒あたり約 142.8 レコードを処理 - Golang: 52.4k レコードを 13.4 秒で処理
=> 1 秒あたり約 3910.4 レコードを処理
表にするとこんな感じ。
Runtime | record/s |
---|---|
Python | 142.8 |
Rust | 2348.6 |
Golang | 3910.0 |
すごい。
仮説
当初立てていた仮説では、Rust とそんなに差はでないかな、と考えていました。
というのも、風の噂でGolang の正規表現は遅い場合がある
と聞いていたので、ネイティブで動くにしてもそのあたりで差が詰まってトントンという見込みでした。
実装
実装が上です。これまで同様、 Apache のログを JSON に変換する Lambda です。
AWS CodeStar で作った Web サービス用のものをゴリゴリ書き換えました。
Golang は初めて書きましたが、あんまり違和感なくいけました。
C 書いてましたし、error まわりも Rust の Result
と似たような意図を感じたので、そのまま書きました。
ただ、ただ日付には戸惑いました… わかるか!!
そんな僕を助けてくれた記事です。3年以上前…
Goのtimeパッケージのリファレンスタイム(2006年1月2日)は何の日? - Qiita
測定(おさらい)
Lambda の環境
- Runtime: Go 1.x
- メモリ: 128 MB
- 実行時間上限: 5分
Runtime は Go、残り2つは前回と同様です。
指標
ExecuteProcessing.Duration
: 変換 Lambda の実行時間SucceedProcessing.Records
: 変換 Lambda が正常に変換できたレコード数
こちらも前回同様です。
正常に変換できたレコード数を、どれだけの実行時間でさばいたかで測ります。
結果
52.4k レコードを 13.4 秒で処理してます。
ので結果として、1 秒あたり約 3910.4 レコードを処理 した、ってことがわかりました。めっちゃ速いな!
予備計測
上の実装では json-iterator
という速い package を使っていたためだきっとそうだ、ということで、JSON へのエンコードを標準の encoding/json
でも行いました。
その結果がこちら。
56.2k レコードを 15.8 秒で処理してます。
1 秒あたり約 3557.0 レコードを処理 てことでやっぱり速い!
まとめ
仮説は外れ、Golang は速かったです。
くやしい… Rust の正式対応こい!
API Gateway の Kinesis Proxy で追跡性をちょこっと上げてみる
結論
本文マッピングテンプレートを以下のようにします
#set($inputRoot = $input.path('$')) #define ($data){"requestId": "$context.requestId","data": "$inputRoot"}#end { "StreamName": "STREAM_NAME", "Data": "$util.base64Encode($data)", "PartitionKey": "KEY" }
これでリクエストの ID がとれ、後の処理の追跡がしやすくなる…はず?
設計に応じて、ステージ名とかパスとか入れるとよさそうです。
参考にさせてもらったところ
Amazon Kinesis プロキシとして API Gateway API を作成する - Amazon API Gateway
API Gatewayへの入力値にLambdaからアクセスする - Qiita
蛇足1: ちょっとめんどくさかった Json 文字列の作成
Kinesis Proxy の Data
は Base64 でエンコードされてる必要があります。よって、先に JSON 文字列を作ってやる必要がありました。
が、このやり方がひたすら謎で迷走してました。Velocity Template Language
てなんやねん…
結局は #define
でできました。
Apache Velocity Engine VTL Reference
ほかに試したこと
#set ($data = ...)
でいれてみる
-> ダブルクォート なしのやつが出来上がる- さらに
$data.json()
とかしてみる
-> 空文字が返ってくる #set ($data = ...)
の際に '"" をエスケープして追加してみる
-> いんたーなるさーばーえらー
蛇足2:本当は X-Ray の Trace Id がほしかった
API Gateway からの応答には入っていたので、$input.param('X-Amzn-Trace-Id')
と書けばとれたりするかなー、と思ったりしましたがだめでした。
これが取れると X-Ray での描画ができてさらに便利になるやん、と期待してたりしました。
CodeStar で AWS Lambda + Golang の雛形をサクッと作成してみた
前回 Golang サポートしたらやってみるといってたので、まずは雛形作成と調査だけ。Golang しっかり書いたことないですし。
CodeStar で雛形作成
AWS Lambda Supports Go をよむと CodeStar に対応しているぜー とかいてあったので、そちらで作りました。
物としては、API Gateway 経由で起動して、ローカルファイルを読み込んで返す Lambda でした。
仕組みについてはこちらをありがたく読ませていただきました。
CodeStar のよかったところ: クロスコンパイラ環境の準備と設定ができてる
CodeStar の利点としてはビルドやデプロイの設定がしてあることですね。とくにクロスコンパイラ環境。
家に帰る途中で調査の段取り考えてた時に、ビルド環境の準備面倒そうだなーとか思ってたので。
実際は $ GOOS=linux GOARCH=amd64
で行けるので手間でない模様。
雑感
バイナリサイズ: 2.4 MB
このぐらいのサイズにはなりますよね。
cold 状態からの起動による遅延: 感じられず
おそらく数ミリ秒
つづく
こちら にて紹介いただいていた sdk にFirehose のイベント定義 もありました。
書くぞー計測するぞー
Q. 2017/12/9 の AWS Lambda の OpenSSL のバージョンは?
import ssl def lambda_handler(event, context): return ssl.OPENSSL_VERSION
チェック!
結果: "OpenSSL 1.0.0-fips 29 Mar 2010"
おし、めんどくさくなってきた。
情報元:
OpenSSL 1.0.2 Shared Library missing · Issue #855 · Miserlou/Zappa · GitHub