Avro をネイティブの実行可能ファイルで使用する
数ヶ月前に、 QuarkusとKafka、Avro (Apicurio schema registryを使用)についてブログを書きました。
HTTPリクエストを受信し、Kafkaのレコードを書き込み、Kafkaからレコードを読み出すというシンプルなアプリケーションを開発しました。 Avroを使ってレコードのシリアライズとデシリアライズを行っています。
その時は、 アプリケーション はネイティブモードで動作して いません でした。
Quarkus 1.10.2では、ネイティブモードで動作するようになりました!
なぜうまくいかなかったのでしょうか?
ネイティブコンパイラは、Javaでできることをすべてサポートしているわけではありません。 まだサポートされていないケースがあり、Avroではこれらのサポートされていない構文のいくつかを使用しています。幸いなことに、substitutions(コード内のサポートされていない構文を直接置き換える)を実装し、Quarkusのエクステンションを使用してコンパイラを正しく設定することができます。その結果、アプリケーションは何も設定する必要がなく、「it just works™️」。
Avro の話に戻りましょう。 Avro は GraalVM ネイティブコンパイラがサポートしていない メソッドハンドル を使用しています。
Avro が使用するサポートされていない構文を回避するために、 substitutions のセットを実装しました。 メソッドハンドルをリフレクションに置き換えました。
また、 GenericDatumReader
は、ビルド時にスレッドに触れるため、少し作業が必要です。
最後に、Quarkus Avro Processor(Quarkusエクステンションの一部)で、 @AvroGenerated
でアノテーションされたすべてのクラスをリフレクションの為に登録します。新しいインスタンスの生成にリフレクションを使用している為です。
見せて!
アプリケーションの コード を取得し、GraalVMがインストールされていることを確認してください。そして、ネイティブ実行可能ファイルを次のようにビルドします:
mvn package -Pnative
数分かかる場合がありますので、コーヒーや紅茶を淹れましょう
Kafka ブローカーとスキーマレジストリーを次のように起動します:
docker-compose up -d
最後に、 ./target/kafka-and-avro-1.0.0-SNAPSHOT-runner
でアプリケーションを実行します。
いくつかの映画をアプリに送信します:
curl --header "Content-Type: application/json" \
--request POST \
--data '{"title":"The Shawshank Redemption","year":1994}' \
http://localhost:8080/movies
curl --header "Content-Type: application/json" \
--request POST \
--data '{"title":"The Godfather","year":1972}' \
http://localhost:8080/movies
curl --header "Content-Type: application/json" \
--request POST \
--data '{"title":"The Dark Knight","year":2008}' \
http://localhost:8080/movies
curl --header "Content-Type: application/json" \
--request POST \
--data '{"title":"12 Angry Men","year":1957}' \
http://localhost:8080/movies
正常に処理されていることをアプリケーションログ出力で確認してください:
2020-12-02 11:06:32,699 INFO [MovieResource] (executor-thread-1) Sending movie 12 Angry Men to Kafka
2020-12-02 11:06:33,230 INFO [MovieConsumer] (vert.x-eventloop-thread-0) Received movie: 12 Angry Men (1957)
2020-12-02 11:07:01,325 INFO [MovieResource] (executor-thread-1) Sending movie The Shawshank Redemption to Kafka
2020-12-02 11:07:01,345 INFO [MovieConsumer] (vert.x-eventloop-thread-0) Received movie: The Shawshank Redemption (1994)
2020-12-02 11:07:01,350 INFO [MovieResource] (executor-thread-1) Sending movie The Godfather to Kafka
2020-12-02 11:07:01,361 INFO [MovieConsumer] (vert.x-eventloop-thread-0) Received movie: The Godfather (1972)
2020-12-02 11:07:01,368 INFO [MovieResource] (executor-thread-1) Sending movie The Dark Knight to Kafka
2020-12-02 11:07:01,378 INFO [MovieConsumer] (vert.x-eventloop-thread-0) Received movie: The Dark Knight (2008)
2020-12-02 11:07:01,388 INFO [MovieResource] (executor-thread-1) Sending movie 12 Angry Men to Kafka
2020-12-02 11:07:01,396 INFO [MovieConsumer] (vert.x-eventloop-thread-0) Received movie: 12 Angry Men (1957)
ネイティブでのAvroサポートはまだ実験的なものです。前回のQuarkusバージョンでは、かなりの進歩を遂げましたが、いくつかの未発見の部分があるかもしれません。 何かおかしな点を見つけましたら教えてください !