12
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

軽量フレームワークMicronautでサーバーレスJavaを始めよう!

Posted at

サーバーレスがとても盛り上がっていますね。
Javaはいわゆるコールドスタートの問題でサーバーレスには向いていないとの声もありましたが、今回紹介するMicronautを始めとしたマイクロフレームワークや、GraalVMのネイティブイメージ作成機能(SubstrateVM)の登場により状況が大きく変わってきています。

この辺りの流れは、@_kenshさんや@jyukutyoさんの「JJUG CCC 2019 Fall」での素晴らしい講演資料がありますので、そちらを見てワクワクしましょう。

さあ、ではMicronautで実際にサーバーレスJavaを作ってみましょう!

なんでMicronaut?

Micronautは、キャッチコピーの中で「サーバーレスのためのフレームワーク」であることを謳っています。
また「re:Invent2019」にて、MicronautとLambdaについてのセッションも開催していました。
他のフレームワークと比較して特にサーバーレスに力を入れていて、個人的にとても魅力を感じたので今回セレクトしました。

他のフレームワークはないの?

Java(を始めとするJVM言語)が使用できるマイクロフレームワークとしてメジャーなのは、下記3つかと思います。

どれもこれからが楽しみなフレームワークですね。
キャッチコピーなどを比較してみたので、ご参考までにどうぞ。

キャッチコピー

フレームワーク キャッチコピー 意訳
Micronaut A modern, JVM-based, full-stack framework for building modular, easily testable microservice and serverless applications. マイクロサービスとサーバーレスのためのモダンなフルスタックフレームワークだよ
Quarkus A Kubernetes Native Java stack tailored for OpenJDK HotSpot and GraalVM. OpenJDK HotSpotとGraalVMに最適化したKubernetesネイティブなフレームワークだよ
Helidon Lightweigt. Fast. Crafted for Microservices. マイクロサービスのために作られた軽量で高速なフレームワークだよ

Googleトレンド(アメリカ、過去1年間)

Screen Shot 2019-12-04 at 23.01.22.png

GitHubスター数

Screen Shot 2019-12-04 at 22.59.19.png
https://www.githubcompare.com/

その他

  • 2019/11/28にリリースされたIntelliJ IDEA 2019.3では、「Microservices frameworks support」としてMicronaut、Quarkus、Helidonの3つがサポートされました。注目度合いが伺えますね!
  • Spring Frameworkも次期バージョンの5.3でGraalVMに対応するようです。こちらも楽しみ!

Micronautのセットアップ

では、Micronautをセットアップしてみましょう。
公式サイトではSDKMANでのインストールが推奨されているので、その手順でインストールしましょう。

SDKMANのインストール

$ curl -s https://get.sdkman.io | bash

ターミナル再起動、もしくは下記シェルを実行

$ source "$HOME/.sdkman/bin/sdkman-init.sh"

sdkコマンドが通ればOK

$ sdk version
SDKMAN 5.7.4+362

Micronautのインストール

$ sdk install micronaut

mnコマンドが通ればOK

$ mn -V
| Micronaut Version: 1.2.7
| JVM Version: 11.0.5

MicronautでのLambda関数の作成

プロジェクトの雛形はmnコマンド経由で作成します。
mnだけを入力すると対話モードで起動できます。
コマンド補完もできるので便利です。コマンド履歴も辿れます。

$ mn
| Starting interactive mode...
| Enter a command name to run. Use TAB for completion:
mn> 

コマンドの使い方はmn> helpで確認できます。

mn> help
Usage: mn [-hnvVx] [COMMAND]
Micronaut CLI command line interface for generating projects and services.
Commonly used commands are:
  create-app NAME
  create-cli-app NAME
  create-federation NAME --services SERVICE_NAME[,SERVICE_NAME]...
  create-function NAME
・・・

今回はLambda関数を作りたいので、create-functionを使いましょう。

mn> create-function hello-world
| Generating Java project...
| Function created at /Users/cojohnny/micronaut/hello-world
| Initializing application. Please wait...

一度対話モードを抜けて、生成されたプロジェクトを確認します。

mn> exit
$ cd hello-world/
$ tree
.
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── micronaut-cli.yml
├── settings.gradle
└── src
    ├── main
    │   ├── java
    │   │   └── hello
    │   │       └── world
    │   │           ├── Application.java
    │   │           ├── HelloWorld.java
    │   │           └── HelloWorldFunction.java
    │   └── resources
    │       ├── application.yml
    │       └── logback.xml
    └── test
        └── java
            └── hello
                └── world
                    ├── HelloWorldClient.java
                    └── HelloWorldFunctionTest.java

生成されたソースを見てみましょう。
HelloWorldFunction.javaのapplyメソッドがLambda関数です。
今の実装は、入力されたJSONのnameの設定値を返すだけの処理になっています。

HelloWorldFunction.java
package hello.world;

import io.micronaut.function.executor.FunctionInitializer;
import io.micronaut.function.FunctionBean;
import javax.inject.*;
import java.io.IOException;
import java.util.function.Function;

@FunctionBean("hello-world")
public class HelloWorldFunction extends FunctionInitializer implements Function<HelloWorld, HelloWorld> {

    @Override
    public HelloWorld apply(HelloWorld msg) {
         return msg;
    }

    /**
     * This main method allows running the function as a CLI application using: echo '{}' | java -jar function.jar 
     * where the argument to echo is the JSON to be parsed.
     */
    public static void main(String...args) throws IOException {
        HelloWorldFunction function = new HelloWorldFunction();
        function.run(args, (context)-> function.apply(context.get(HelloWorld.class)));
    }    
}

ではgradlewでビルドしてみましょう。

$ ./gradlew assemble

Jarが2種類出来上がります。

$ tree build/libs/
build/libs/
├── hello-world-0.1-all.jar
└── hello-world-0.1.jar

ファイル名の末尾に-allとついているほうが、依存ライブラリが含まれた「Fat Jar」なので、そちらをLambdaにアップロードします。

Lambda関数のセットアップ

作成した「hello-world-0.1-all.jar」をAWSにアップロードしましょう。
Handlerには「hello.world.HelloWorldFunction::apply」を設定。

image.png

Lambda関数の実行

それではLambda関数を実行してみましょう。
Lambdaコンソール上部の「Test」ボタンから、リクエストのJSONを設定します。
JSONには下記を指定。

{
  "name": "Lambda"
}

image.png

「Test」実行!
動きましたね!

image.png

まとめ

今回は単純な処理の実行だけでしたが、気軽にフレームワークを含んだLambda関数を作成して実行できることがわかったと思います。
Micronautなどの軽量フレームワークを使うことで、フレームワークの豊富な機能を使いながらLambdaを構築することができるようになるため、大規模アプリケーションへのサーバーレスアーキテクチャの適用もますます拡がっていきそうですね。

一番の懸念だったコールドスタートについても、先日のre:Invent2019で発表された「provisioned concurrency」という有力な解決策が提示されたため、本番環境への適用に対するハードルもどんどん下がってきています。

2020年もさらなる拡がりが予想されるサーバーレスの世界、とても楽しみですね!
特にJavaの大規模システムに関わっていてサーバーレスにあまり馴染みがなかったという方も、今が始めどきだと思います。
一緒にサーバーレスJavaを始めましょう!

参考

Java最新フレームワーク、Helidon、Micronaut、Quarkusをnative-imageまでまとめて試す
Micronaut User Guide
AWS Lambda announces Provisioned Concurrency

12
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?