SlideShare a Scribd company logo
1 of 43
Download to read offline
Java EE から Quarkus による開発へ

の移行について

Shigeru Tatsuta

2020/02/26 JakartaOne Live Japan 2020

自己紹介

竜田 茂 (たつた しげる)



ソフトバンク株式会社

テクノロジーユニット IT&ネットワーク統括 IT 本部



前職の日本オラクルでは Java アプリケーションサーバ製品の技術サポートを
担当。



2013 年よりソフトバンクに参画し、Java ミドルウェア製品の全社導入支援、お
よびリアルタイム処理基盤 Chronos-Core プロジェクト、IBM との提携にともな
い IBM Watson のローカライズにも参画。 



現在はプロフェッショナルなテクノロジー集団の実現を目指して、Java での
CloundNative な開発を推進中。 



ソフトバンクの IT 本部について

IT 本部はいわゆる情報システム部門で、主にキャリア事業に必要な IT
サービスを提供するためシステムを開発・運用しています。

IT 本部のシステムの多くは Java で開発、あるいは Java 製品を利用し
ています。

キャリア事業を支えるシステム開発

キャリア事業のシステムはユーザーの皆さまの生活を支える重要なイ
ンフラであるため、自社のデータセンターで Warterfall による堅牢・堅実
なシステム開発がメインでした。

CloudNative への挑戦

事業環境の変化に伴い、事業部門との密なコミュニケーションが重要、
スピード感が必要等のシステムの特性に応じて、アジャイル開発や
CloudNative なシステム開発も積極的に取り組んでいます。

アプリケーションサーバからの転換

これまでのアプリケーションサーバ上での可動を前提した Java EE
ベースの開発から、アプリケーションサーバを必要としない実行可能
Jar ベースの開発への移行が課題。

大きな Java プロセス

コンテナにおける Java プロセス

これまでの大きな Java プロセスに複数のアプリケーションをデプロイ
から、小さな Java プロセスとアプリケーションをコンテナにパッケージし
て、デプロイする時代へ。

App
 App
 App
 App
 App

App
小さな Java プロセス
App App App App
クラウドネイティブなアプリケーション

CloudNative の指針として、12-factor App があるが、コンテナのサイ
ズ、起動の速さが重要となってくる。

I. コードベース

バージョン管理されている1つのコードベースと複数のデプロイ

VII. ポートバインディング 

ポートバインディングを通してサービスを公開する

II. 依存関係

依存関係を明示的に宣言し分離する

VIII. 並行性

プロセスモデルによってスケールアウトする

III. 設定

設定を環境変数に格納する

IX. 廃棄容易性

高速な起動とグレースフルシャットダウンで堅牢性を最大化する

IV. バックエンドサービス 

バックエンドサービスをアタッチされたリソースとして扱う

X. 開発/本番一致

開発、ステージング、本番環境をできるだけ一致させた状態を保つ

V. ビルド、リリース、実行 

ビルド、リリース、実行の3つのステージを厳密に分離する

XI. ログ

ログをイベントストリームとして扱う

VI. プロセス

アプリケーションを1つもしくは複数のステートレスなプロセスとして実行する

XII. 管理プロセス

管理タスクを1回限りのプロセスとして実行する

GraalVM のネイティブイメージ

コンテナ環境でも引き続き社内に開発者の多い Java で開発したかっ
たが、一般に JVM は起動が遅いので、GraalVM のネイティブイメージ
に着目。

新世代 Java フレームワークの選定

2019/06 に、GraalVM のネイティブイメージに対応している以下の新世
代 Java フレームワークを比較検討し、当時最も親和性の高かった
Quarkus の採用を決定。

Quarkus の採用

View API
Azure Traffic 

Manager

Azure Application
Gateway

2019/08 より、ショップ向けの新規システム開発にて、バックエンドの
REST API に Quarkus (0.20.0) を使用して開発。

Azure Kubernetes Service

オンプレ

2019/12 に一部店舗でトライアル中。近日全店舗展開予定。

ここが良いよ Quarkus

JavaEE との親和性が高い

Qarkus Blog でも言及されているとおり、Quarkus は MicroProfile と互
換性があり、Java EE との親和性が高い。

エンタープライズシステムでは、標準である Java EE の採用が多いた
め、学習コストは低い。

Thorntail 4.x

JBoss.org の MicroProfile の実装である Thorntail (旧 WildFly Swarm)
は次期 Thorntail 4.x の開発を中止。

Quarkus は JBoss.org のプロジェクトが多く採用されているので、
WildFly からの MicroProfile の移行先としても良い。

Quarkus は起動が高速

新規に開発された DI コンテナ ArC によって、依存性をビルド時に解決
するため、実行時に依存性を解決する Spring Boot と比較して起動が
高速。

初回コール時に実行 
起動時に実行

初回コール時に実行 
ビルド時に実行

新世代のフレームワーク

Quarkus、Micronaut 等の新世代のフレームワークはアノテーションの
スキャン、依存性の解決、バイトコードの生成などの処理をビルド時に
実施するため、起動も早く、メモリのフットプリントも小さい。

「Quarkus 入門」 

 https://www.slideshare.net/agetsuma/quarkus 

Bean 定義アノ
テーションのス
キャン
@Inject アノテー
ションのスキャン
依存性の解決
プロキシバイト
コードの生成
Bean の生成
前世代

新世代

Kubernetes の死活監視

MicroProfile Health も準拠しているため、Kubernetes の Liveness
Probe、Readiness Probe も容易に対応できる。

livenessProbe:

httpGet:

path: /health/live

port: 8080

initialDelaySeconds: 15

periodSeconds: 5

timeoutSeconds: 15

successThreshold: 1

failureThreshold: 3

readinessProbe:

httpGet:

path: /health/ready

port: 8080

initialDelaySeconds: 15

periodSeconds: 5

timeoutSeconds: 15

successThreshold: 1

failureThreshold: 3



テスト機能の充実

Spring Boot と同様に、UT の実装についてもフレームワークでサポート
されており、@SpringBootTest のように @QuarkusTest で CDI のテスト
も実装できる。

特に HTTP ベースのテストは REST Assured が統合されており、Spring
Boot と比較すると実装しやすい。

@QuarkusTest

public class GreetingResourceTest {



@Test

public void testHelloEndpoint() {

given()

.when().get("/hello")

.then()

.statusCode(200)

.body(is("hello"));

}



}

プロファイルの切り替え

Spring Boot と同様に、application.properties に、%プロファイル名で定
義し、実行時に -Dquarkus.profile=プロファイル名で切り替えができ、
CI/CD とも親和性が高い。

quarkus.datasource.url=jdbc:sqlserver://localhost:1433

%it.quarkus.datasource.url=jdbc:sqlserver://xxxx:1433

%st.quarkus.datasource.url=jdbc:sqlserver://xxxx:1433

%pr.quarkus.datasource.url=jdbc:sqlserver://xxxx:1433



JavaEE では、DeltaSpike を利用して実現していたが、はるかに使いや
すい。

ここがいまいちだよ Quarkus

ときおり Quarkus が起動しなくなる

Quarkus を使い始めた当初は、ときおり以下のようなエラーが発生して
Quarkus が起動しなくなる。

Unable to properly register the hierarchy of the following classes for reflection as they are not in the Jandex index:

- com.example.Fruit

- com.example.Car

Consider adding them to the index either by creating a Jandex index for your dependency or via quarkus.index-dependency
properties.

Jandex インデックスの生成方法

Quarkus の Bean Discovery の実装に起因するもので、以下の
jandex-maven-plugin の設定を追加することで対応可能。

(というか、最初から設定されていれば・・・)

<plugin>

<groupId>org.jboss.jandex</groupId>

<artifactId>jandex-maven-plugin</artifactId>

<version>1.0.7</version>

<executions>

<execution>

<id>make-index</id>

<goals>

<goal>jandex</goal>

</goals>

</execution>

</executions>

</plugin>



デフォルト設定では fatJar でない

デフォルトの設定では fatJar とはなっておらず、-runner.jar だけでは起
動しない。target の下の lib の下のファイルも必要。

$ java -jar code-with-quarkus-1.0.0-SNAPSHOT-runner.jar

Exception in thread "main" java.lang.NoClassDefFoundError: io/quarkus/runtime/Application

at java.base/java.lang.ClassLoader.defineClass1(Native Method)

at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)

at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)

at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:800)

at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:698)

at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:621)

at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579)

at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)

at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)

at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:27)

Caused by: java.lang.ClassNotFoundException: io.quarkus.runtime.Application

at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)

at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)

at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)

... 10 more

fatJar のビルド設定

fatJar としてビルドするには、quarkus-maven-plugin で uberJar=true
を指定すればよい。

<plugin>

<groupId>io.quarkus</groupId>

<artifactId>quarkus-maven-plugin</artifactId>

<version>${quarkus-plugin.version}</version>

<executions>

<execution>

<goals>

<goal>build</goal>

</goals>

<configuration>

<uberJar>true</uberJar>

</configuration>

</execution>

</executions>

</plugin>





署名付き Jar でエラー

fatJar としてビルドした場合、依存ライブラリに署名付き Jar が含まれ
ていると、SecurityException が発生する。

$ java -jar target/backend-runner.jar

Error: A JNI error has occurred, please check your installation and try again

Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes

at java.base/sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:336)

at java.base/sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:269)

at java.base/java.util.jar.JarVerifier.processEntry(JarVerifier.java:273)

at java.base/java.util.jar.JarVerifier.update(JarVerifier.java:230)

at java.base/java.util.jar.JarFile.initializeVerifier(JarFile.java:757)

at java.base/java.util.jar.JarFile.ensureInitialization(JarFile.java:1034)

at java.base/java.util.jar.JavaUtilJarAccessImpl.ensureInitialization(JavaUtilJarAccessImpl.java:69)

at java.base/jdk.internal.loader.URLClassPath$JarLoader$2.getManifest(URLClassPath.java:870)

at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:786)

at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:698)

at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:621)

at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579)

at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)

at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)

at java.base/java.lang.Class.forName0(Native Method)

at java.base/java.lang.Class.forName(Class.java:398)

at java.base/sun.launcher.LauncherHelper.loadMainClass(LauncherHelper.java:760)

at java.base/sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:655)





署名付き Jar の対処

<plugin>

<groupId>io.quarkus</groupId>

<artifactId>quarkus-maven-plugin</artifactId>

<version>${quarkus-plugin.version}</version>

<executions>

<execution>

<goals>

<goal>build</goal>

</goals>

<configuration>

<uberJar>true</uberJar>

<ignoredEntries>

<ignoredEntry>META-INF/MSFTSIG.SF</ignoredEntry>

<ignoredEntry>META-INF/MSFTSIG.RSA</ignoredEntry>

</ignoredEntries>

</configuration>

</execution>

</executions>

</plugin>





META-INF/*.SF、META-INF/*.RSA などを ignoredEntry で指定するこ
とで回避可能。

ただし、#4259 の修正により 0.23.2 以降では発生しない。

JAX-WS 連携がサポートされていない

JAX-WS (Apache CXF) の extension は #4005 Extension for CXF で
開発中。Apache CXF を直接使うことはできるが、Java 9 以降では
JAXB などの API がごっそりなくなっているので依存性の解決は結構
面倒。

<dependency>

<groupId>org.apache.cxf</groupId>

<artifactId>cxf-rt-frontend-jaxws</artifactId>

<scope>compile</scope>

</dependency>

<dependency>

<groupId>javax.xml.ws</groupId>

<artifactId>jaxws-api</artifactId>

<scope>compile</scope>

</dependency>

<dependency>

<groupId>org.apache.cxf</groupId>

<artifactId>cxf-rt-transports-http</artifactId>

<scope>runtime</scope>

</dependency>

fatJar と Apache CXF との相性

Apache CXF を直接利用することは可能だが、fatJar で利用すると
NullPointerException が発生する。

java.lang.NullPointerException

at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:85)

at org.apache.cxf.jaxws.ServiceImpl.initializePorts(ServiceImpl.java:217)

at org.apache.cxf.jaxws.ServiceImpl.initialize(ServiceImpl.java:160)

at org.apache.cxf.jaxws.ServiceImpl.<init>(ServiceImpl.java:128)

at org.apache.cxf.jaxws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:82)

at javax.xml.ws.Service.<init>(Service.java:112)





quarkus-maven-plugin で uberJar=false で、回避はできるが、fatJar は
現状は諦めるしかない。

⇒ 現状は -runner.jar と lib 下の jar ファイルをコンテナ化。

Mock オブジェクトがいまいち

Spring Boot では @MockBean で、mockito と連携できるが、Quarkus
の場合は Mock クラスは自作する必要がある。

@Mock

@ApplicationScoped 

public class MockExternalService extends ExternalService {



@Override

public String service() {

return "mock";

}

}





Spring Boot + mockito に比べると、テストごとに Mock オブジェクトの
振る舞いをセットアップできなくて不便。

Quarkus は画面はサポートしていない

Quarkus は Spring Boot や Micronaut とは異なり画面は実装できな
い。#1911 によると JSP などの View はサポートされておらず、今のと
ころサポートするつもりもないらしい。

現状、フロントエンドは Spring Boot で実装しているが、Micronaut か、
SPA への移行を検討。

Azure App Insights との連携がいまいち

Spring Boot の場合、以下の依存性を追加し、さらに
application.properties で設定をするだけで、アプリケーションの変更せ
ずに、Application Insights と自動で連携できる。

<dependency>

<groupId>com.microsoft.azure</groupId>

<artifactId>applicationinsights-spring-boot-starter</artifactId>

<version>2.5.1</version>

</dependency>





azure.application-insights.instrumentation-key=[your ikey from the resource]

spring.application.name=[your app name]

Quarkus は まだメジャーではないので Application Insights Spring Boot
Starter のようなものは存在しない。

Netty に関連する OOM

Quarkus 内部的に Netty を利用しており、アプリケーション側で Direct
Buffer を使う実装が多い場合、Direct buffer memory に起因する
OutOfMemoryError が発生し易い。

Exception in thread "Thread-316" java.lang.OutOfMemoryError: Direct buffer memory

at java.base/java.nio.Bits.reserveMemory(Unknown Source)

at java.base/java.nio.DirectByteBuffer.<init>(Unknown Source)

at java.base/java.nio.ByteBuffer.allocateDirect(Unknown Source)

at java.base/sun.nio.ch.Util.getTemporaryDirectBuffer(Unknown Source)

at java.base/sun.nio.ch.IOUtil.read(Unknown Source)

at java.base/sun.nio.ch.IOUtil.read(Unknown Source)

at java.base/sun.nio.ch.SimpleAsynchronousFileChannelImpl$2.run(Unknown Source)

at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.base/java.lang.Thread.run(Unknown Source)



JVM のチューニング

Java ヒープを多く確保するため、Native メモリのチューニングを攻めた
チューニングとしてたため、MaxDirectMemorySize を増やし、
-Djdk.nio.maxCachedBufferSize=262144 を設定。

-XX:MetaspaceSize=128m
-XX:MaxMetaspaceSize=128m
-XX:InitialCodeCacheSize=64m
-XX:ReservedCodeCacheSize=64m
-XX:CompressedClassSpaceSize=64m
-XX:MaxDirectMemorySize=64m
-Djdk.nio.maxCachedBufferSize=262144
Quarkus のリリースサイクル


 バージョン
 リリース日

1.0.x

1.0.0.Final
 2019/10/25

1.0.1.Final
 2019/11/28

1.1.x

1.1.0.Final
 2019/12/17

1.1.1.Final
 2020/01/07

1.2.x

1.2.0.Final
 2020/01/23

1.2.1.Final
 2020/02/19

Quarkus はマイナーバージョンアップが早く、新しいマイナーバージョン
がリリースされると、パッチバージョンはリリースされない。

エンタープライズでは、できるだけ長くメジャー/マイナーバージョンを使
い続けたいので、昨今の JDK の問題と同様悩ましい。

Quarkus のバージョンアップ

2 週間のイテレーションでアジャイル開発しており、リリースのタイミング
で最新の OS、JDK、Quakus にバージョンアップし、最新のバージョンに
追従することで対応。

ソースコード

静的解析

単体

テスト

結合

テスト

システム

テスト

コンテナ

保存

webhook
Azure Kubernetes Service

Azure Container Registory
社内 Docker Registory 

pull deploy
いろいろ不満も言ったけど

Quarkus おすすめです

JavaEE に慣れ親しんだエンジニアにとって、MicroProfile の移行先とし
て、学習コストも低くお勧め。

1) REST API だけでよく、画面は実装する必要はない場合

2) JavaEE の慣れ親しんだエンジニアが社内に多い場合

3) WildFly 等の JBoss.org の製品を利用している場合

4) Microservice、CloudNative な開発を視野に入れている場合

ただし、バージョンアップが早いため、短いリリースサイクルで、最新
バージョンに追従していける体制が必要。

これから挑戦したいこと

ネイティブイメージの利用について

「Javaの起動時間といかに戦うか」 

 https://speakerdeck.com/kishida/how-to-fight-against-java-warmup-time 


 JIT
 AOT

ビルド時間
 ○
 ✕

起動時間
 ✕
 ○

スループット
 ○
 ✕

ピークパフォーマンスまで 
 ✕
 ○

ネイティブイメージにも将来的には挑戦したいが、AOT にもメリデメが
あり、JIT でも十分起動は高速なので、ネイティブイメージであと数秒削
るのが有意義なのかは、慎重に判断。

CDS の利用について

「Javaの起動時間といかに戦うか」 

 https://speakerdeck.com/kishida/how-to-fight-against-java-warmup-time 

現状は LTS の Java 11 を利用しているが、リリースごとに最新の Java
に追従していくなら、LTS でなくてよいので、最新の Java に移行し、
Class-Data Sharing を利用した起動の高速化も検討。

機能
 バージョン
 JEP

Application Class-Data Sharing 
 Java 10
 JEP 310

Default CDS Archives 
 Java 12
 JEP 341

Azure Application Insights 対応

Java 用の Application Insights の API は提供されているので、
Application Insights Spring Boot Starter のようなものを実装し、Spring
Boot と同等にアプリケーションを監視できるようにしたい。

ご清聴ありがとうございました

#
 資料名

①
 【JJUG CCC 2019 Fall】JavaオンプレシステムをAKS + Quarkusに移行した話

②
 Quarkus is Eclipse MicroProfile 3.2 compatible!

③
 Thorntail Community Announcement on Quarkus

④
 Quarkus Dependency Injection

⑤
 Quarkus入門

⑥
 Unable to forward from a JAX-RS service to JSP

⑦
 Extension for CXF

⑧
 Skip adding signature files to the generated uber jar

⑨
 Fixing Java's ByteBuffer native memory "leak"

⑩
 Javaの起動時間といかに戦うか

参考資料


More Related Content

What's hot

Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Akihiro Suda
 
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2tamtam180
 
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)NTT DATA Technology & Innovation
 
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugMasatoshi Tada
 
Java によるクラウドネイティブ の実現に向けて
Java によるクラウドネイティブ の実現に向けてJava によるクラウドネイティブ の実現に向けて
Java によるクラウドネイティブ の実現に向けてShigeru Tatsuta
 
エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織Takafumi ONAKA
 
Kubernetesでの性能解析 ~なんとなく遅いからの脱却~(Kubernetes Meetup Tokyo #33 発表資料)
Kubernetesでの性能解析 ~なんとなく遅いからの脱却~(Kubernetes Meetup Tokyo #33 発表資料)Kubernetesでの性能解析 ~なんとなく遅いからの脱却~(Kubernetes Meetup Tokyo #33 発表資料)
Kubernetesでの性能解析 ~なんとなく遅いからの脱却~(Kubernetes Meetup Tokyo #33 発表資料)NTT DATA Technology & Innovation
 
最適なOpenJDKディストリビューションの選び方 #codetokyo19B3 #ccc_l5
最適なOpenJDKディストリビューションの選び方 #codetokyo19B3 #ccc_l5最適なOpenJDKディストリビューションの選び方 #codetokyo19B3 #ccc_l5
最適なOpenJDKディストリビューションの選び方 #codetokyo19B3 #ccc_l5Takahiro YAMADA
 
AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
AngularとSpring Bootで作るSPA + RESTful Web ServiceアプリケーションAngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーションssuser070fa9
 
え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理
え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理
え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理NTT DATA Technology & Innovation
 
さくっと理解するSpring bootの仕組み
さくっと理解するSpring bootの仕組みさくっと理解するSpring bootの仕組み
さくっと理解するSpring bootの仕組みTakeshi Ogawa
 
コンテナの作り方「Dockerは裏方で何をしているのか?」
コンテナの作り方「Dockerは裏方で何をしているのか?」コンテナの作り方「Dockerは裏方で何をしているのか?」
コンテナの作り方「Dockerは裏方で何をしているのか?」Masahito Zembutsu
 
PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門泰 増田
 
9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...
9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...
9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...NTT DATA Technology & Innovation
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Kohei Tokunaga
 
Spring Bootをはじめる時にやるべき10のこと
Spring Bootをはじめる時にやるべき10のことSpring Bootをはじめる時にやるべき10のこと
Spring Bootをはじめる時にやるべき10のこと心 谷本
 
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Taku Miyakawa
 
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティスAmazon Web Services Japan
 
単なるキャッシュじゃないよ!?infinispanの紹介
単なるキャッシュじゃないよ!?infinispanの紹介単なるキャッシュじゃないよ!?infinispanの紹介
単なるキャッシュじゃないよ!?infinispanの紹介AdvancedTechNight
 
決済サービスのSpring Bootのバージョンを2系に上げた話
決済サービスのSpring Bootのバージョンを2系に上げた話決済サービスのSpring Bootのバージョンを2系に上げた話
決済サービスのSpring Bootのバージョンを2系に上げた話Ryosuke Uchitate
 

What's hot (20)

Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行
 
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
 
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
 
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsug
 
Java によるクラウドネイティブ の実現に向けて
Java によるクラウドネイティブ の実現に向けてJava によるクラウドネイティブ の実現に向けて
Java によるクラウドネイティブ の実現に向けて
 
エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織
 
Kubernetesでの性能解析 ~なんとなく遅いからの脱却~(Kubernetes Meetup Tokyo #33 発表資料)
Kubernetesでの性能解析 ~なんとなく遅いからの脱却~(Kubernetes Meetup Tokyo #33 発表資料)Kubernetesでの性能解析 ~なんとなく遅いからの脱却~(Kubernetes Meetup Tokyo #33 発表資料)
Kubernetesでの性能解析 ~なんとなく遅いからの脱却~(Kubernetes Meetup Tokyo #33 発表資料)
 
最適なOpenJDKディストリビューションの選び方 #codetokyo19B3 #ccc_l5
最適なOpenJDKディストリビューションの選び方 #codetokyo19B3 #ccc_l5最適なOpenJDKディストリビューションの選び方 #codetokyo19B3 #ccc_l5
最適なOpenJDKディストリビューションの選び方 #codetokyo19B3 #ccc_l5
 
AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
AngularとSpring Bootで作るSPA + RESTful Web ServiceアプリケーションAngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
 
え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理
え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理
え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理
 
さくっと理解するSpring bootの仕組み
さくっと理解するSpring bootの仕組みさくっと理解するSpring bootの仕組み
さくっと理解するSpring bootの仕組み
 
コンテナの作り方「Dockerは裏方で何をしているのか?」
コンテナの作り方「Dockerは裏方で何をしているのか?」コンテナの作り方「Dockerは裏方で何をしているのか?」
コンテナの作り方「Dockerは裏方で何をしているのか?」
 
PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門
 
9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...
9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...
9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行
 
Spring Bootをはじめる時にやるべき10のこと
Spring Bootをはじめる時にやるべき10のことSpring Bootをはじめる時にやるべき10のこと
Spring Bootをはじめる時にやるべき10のこと
 
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方
 
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
 
単なるキャッシュじゃないよ!?infinispanの紹介
単なるキャッシュじゃないよ!?infinispanの紹介単なるキャッシュじゃないよ!?infinispanの紹介
単なるキャッシュじゃないよ!?infinispanの紹介
 
決済サービスのSpring Bootのバージョンを2系に上げた話
決済サービスのSpring Bootのバージョンを2系に上げた話決済サービスのSpring Bootのバージョンを2系に上げた話
決済サービスのSpring Bootのバージョンを2系に上げた話
 

Similar to Java EE から Quarkus による開発への移行について

ソフトバンクにおける Java による クラウドネイティブの実現
ソフトバンクにおける Java による クラウドネイティブの実現ソフトバンクにおける Java による クラウドネイティブの実現
ソフトバンクにおける Java による クラウドネイティブの実現Shigeru Tatsuta
 
企業システムで使えるマイクロサービスの特長と実践 (Oracle Cloudウェビナーシリーズ: 2021年4月15日)
企業システムで使えるマイクロサービスの特長と実践 (Oracle Cloudウェビナーシリーズ: 2021年4月15日)企業システムで使えるマイクロサービスの特長と実践 (Oracle Cloudウェビナーシリーズ: 2021年4月15日)
企業システムで使えるマイクロサービスの特長と実践 (Oracle Cloudウェビナーシリーズ: 2021年4月15日)オラクルエンジニア通信
 
G-Tech2015 Hadoop/Sparkを中核としたビッグデータ基盤_20151006
G-Tech2015 Hadoop/Sparkを中核としたビッグデータ基盤_20151006G-Tech2015 Hadoop/Sparkを中核としたビッグデータ基盤_20151006
G-Tech2015 Hadoop/Sparkを中核としたビッグデータ基盤_20151006Cloudera Japan
 
EXTREME TEAM で Agile を目指して
EXTREME TEAM で Agile を目指してEXTREME TEAM で Agile を目指して
EXTREME TEAM で Agile を目指してShigeru Tatsuta
 
SDLoader SeasarCon 2009 Whire
SDLoader SeasarCon 2009 WhireSDLoader SeasarCon 2009 Whire
SDLoader SeasarCon 2009 WhireAkio Katayama
 
Building React, Flutter and Blazor development and debugging environment with...
Building React, Flutter and Blazor development and debugging environment with...Building React, Flutter and Blazor development and debugging environment with...
Building React, Flutter and Blazor development and debugging environment with...Shotaro Suzuki
 
AWS を活用して小さなチームで 世界で使われるサービスを運用する方法 - JAWS Days 2013
AWS を活用して小さなチームで 世界で使われるサービスを運用する方法 - JAWS Days 2013AWS を活用して小さなチームで 世界で使われるサービスを運用する方法 - JAWS Days 2013
AWS を活用して小さなチームで 世界で使われるサービスを運用する方法 - JAWS Days 2013Takashi Someda
 
Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略takezoe
 
Backlog、Cacoo にみるAWS運用の勘所 - JAWS UG 三都物語
Backlog、Cacoo にみるAWS運用の勘所 - JAWS UG 三都物語Backlog、Cacoo にみるAWS運用の勘所 - JAWS UG 三都物語
Backlog、Cacoo にみるAWS運用の勘所 - JAWS UG 三都物語Takashi Someda
 
Dockerを活用したリクルートグループ開発基盤の構築
Dockerを活用したリクルートグループ開発基盤の構築Dockerを活用したリクルートグループ開発基盤の構築
Dockerを活用したリクルートグループ開発基盤の構築Recruit Technologies
 
20201107 jjug ccc Spring Boot ユーザーのための Quarkus 入門
20201107 jjug ccc Spring Boot ユーザーのための Quarkus 入門20201107 jjug ccc Spring Boot ユーザーのための Quarkus 入門
20201107 jjug ccc Spring Boot ユーザーのための Quarkus 入門ryoheiseki1
 
Oracle GoldenGate Veridata 12cR2 セットアップガイド
Oracle GoldenGate Veridata 12cR2 セットアップガイドOracle GoldenGate Veridata 12cR2 セットアップガイド
Oracle GoldenGate Veridata 12cR2 セットアップガイドオラクルエンジニア通信
 
コマンド1発でAzureにDC/OS環境を作る方法
コマンド1発でAzureにDC/OS環境を作る方法コマンド1発でAzureにDC/OS環境を作る方法
コマンド1発でAzureにDC/OS環境を作る方法Toru Makabe
 
できる!サーバレスアーキテクチャ
できる!サーバレスアーキテクチャできる!サーバレスアーキテクチャ
できる!サーバレスアーキテクチャazuma satoshi
 
JavaからScalaへの継続的なマイグレーション
JavaからScalaへの継続的なマイグレーションJavaからScalaへの継続的なマイグレーション
JavaからScalaへの継続的なマイグレーションMakoto Fukuhara
 
Apache Spark超入門 (Hadoop / Spark Conference Japan 2016 講演資料)
Apache Spark超入門 (Hadoop / Spark Conference Japan 2016 講演資料)Apache Spark超入門 (Hadoop / Spark Conference Japan 2016 講演資料)
Apache Spark超入門 (Hadoop / Spark Conference Japan 2016 講演資料)NTT DATA OSS Professional Services
 
実プロジェクトの経験から学ぶazureサービス適用パターン
実プロジェクトの経験から学ぶazureサービス適用パターン実プロジェクトの経験から学ぶazureサービス適用パターン
実プロジェクトの経験から学ぶazureサービス適用パターンKuniteru Asami
 
リリースを支える負荷測定
リリースを支える負荷測定リリースを支える負荷測定
リリースを支える負荷測定gree_tech
 

Similar to Java EE から Quarkus による開発への移行について (20)

ソフトバンクにおける Java による クラウドネイティブの実現
ソフトバンクにおける Java による クラウドネイティブの実現ソフトバンクにおける Java による クラウドネイティブの実現
ソフトバンクにおける Java による クラウドネイティブの実現
 
企業システムで使えるマイクロサービスの特長と実践 (Oracle Cloudウェビナーシリーズ: 2021年4月15日)
企業システムで使えるマイクロサービスの特長と実践 (Oracle Cloudウェビナーシリーズ: 2021年4月15日)企業システムで使えるマイクロサービスの特長と実践 (Oracle Cloudウェビナーシリーズ: 2021年4月15日)
企業システムで使えるマイクロサービスの特長と実践 (Oracle Cloudウェビナーシリーズ: 2021年4月15日)
 
G-Tech2015 Hadoop/Sparkを中核としたビッグデータ基盤_20151006
G-Tech2015 Hadoop/Sparkを中核としたビッグデータ基盤_20151006G-Tech2015 Hadoop/Sparkを中核としたビッグデータ基盤_20151006
G-Tech2015 Hadoop/Sparkを中核としたビッグデータ基盤_20151006
 
EXTREME TEAM で Agile を目指して
EXTREME TEAM で Agile を目指してEXTREME TEAM で Agile を目指して
EXTREME TEAM で Agile を目指して
 
SDLoader SeasarCon 2009 Whire
SDLoader SeasarCon 2009 WhireSDLoader SeasarCon 2009 Whire
SDLoader SeasarCon 2009 Whire
 
Building React, Flutter and Blazor development and debugging environment with...
Building React, Flutter and Blazor development and debugging environment with...Building React, Flutter and Blazor development and debugging environment with...
Building React, Flutter and Blazor development and debugging environment with...
 
AWS を活用して小さなチームで 世界で使われるサービスを運用する方法 - JAWS Days 2013
AWS を活用して小さなチームで 世界で使われるサービスを運用する方法 - JAWS Days 2013AWS を活用して小さなチームで 世界で使われるサービスを運用する方法 - JAWS Days 2013
AWS を活用して小さなチームで 世界で使われるサービスを運用する方法 - JAWS Days 2013
 
Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略
 
Backlog、Cacoo にみるAWS運用の勘所 - JAWS UG 三都物語
Backlog、Cacoo にみるAWS運用の勘所 - JAWS UG 三都物語Backlog、Cacoo にみるAWS運用の勘所 - JAWS UG 三都物語
Backlog、Cacoo にみるAWS運用の勘所 - JAWS UG 三都物語
 
Dockerを活用したリクルートグループ開発基盤の構築
Dockerを活用したリクルートグループ開発基盤の構築Dockerを活用したリクルートグループ開発基盤の構築
Dockerを活用したリクルートグループ開発基盤の構築
 
20201107 jjug ccc Spring Boot ユーザーのための Quarkus 入門
20201107 jjug ccc Spring Boot ユーザーのための Quarkus 入門20201107 jjug ccc Spring Boot ユーザーのための Quarkus 入門
20201107 jjug ccc Spring Boot ユーザーのための Quarkus 入門
 
cross2012a fujya
cross2012a fujyacross2012a fujya
cross2012a fujya
 
Oracle GoldenGate Veridata 12cR2 セットアップガイド
Oracle GoldenGate Veridata 12cR2 セットアップガイドOracle GoldenGate Veridata 12cR2 セットアップガイド
Oracle GoldenGate Veridata 12cR2 セットアップガイド
 
コマンド1発でAzureにDC/OS環境を作る方法
コマンド1発でAzureにDC/OS環境を作る方法コマンド1発でAzureにDC/OS環境を作る方法
コマンド1発でAzureにDC/OS環境を作る方法
 
できる!サーバレスアーキテクチャ
できる!サーバレスアーキテクチャできる!サーバレスアーキテクチャ
できる!サーバレスアーキテクチャ
 
Java on Azure 2019
Java on Azure 2019Java on Azure 2019
Java on Azure 2019
 
JavaからScalaへの継続的なマイグレーション
JavaからScalaへの継続的なマイグレーションJavaからScalaへの継続的なマイグレーション
JavaからScalaへの継続的なマイグレーション
 
Apache Spark超入門 (Hadoop / Spark Conference Japan 2016 講演資料)
Apache Spark超入門 (Hadoop / Spark Conference Japan 2016 講演資料)Apache Spark超入門 (Hadoop / Spark Conference Japan 2016 講演資料)
Apache Spark超入門 (Hadoop / Spark Conference Japan 2016 講演資料)
 
実プロジェクトの経験から学ぶazureサービス適用パターン
実プロジェクトの経験から学ぶazureサービス適用パターン実プロジェクトの経験から学ぶazureサービス適用パターン
実プロジェクトの経験から学ぶazureサービス適用パターン
 
リリースを支える負荷測定
リリースを支える負荷測定リリースを支える負荷測定
リリースを支える負荷測定
 

Java EE から Quarkus による開発への移行について

  • 1. Java EE から Quarkus による開発へ
 の移行について
 Shigeru Tatsuta
 2020/02/26 JakartaOne Live Japan 2020

  • 2. 自己紹介
 竜田 茂 (たつた しげる)
 
 ソフトバンク株式会社
 テクノロジーユニット IT&ネットワーク統括 IT 本部
 
 前職の日本オラクルでは Java アプリケーションサーバ製品の技術サポートを 担当。
 
 2013 年よりソフトバンクに参画し、Java ミドルウェア製品の全社導入支援、お よびリアルタイム処理基盤 Chronos-Core プロジェクト、IBM との提携にともな い IBM Watson のローカライズにも参画。 
 
 現在はプロフェッショナルなテクノロジー集団の実現を目指して、Java での CloundNative な開発を推進中。 
 

  • 3. ソフトバンクの IT 本部について
 IT 本部はいわゆる情報システム部門で、主にキャリア事業に必要な IT サービスを提供するためシステムを開発・運用しています。
 IT 本部のシステムの多くは Java で開発、あるいは Java 製品を利用し ています。

  • 7. 大きな Java プロセス
 コンテナにおける Java プロセス
 これまでの大きな Java プロセスに複数のアプリケーションをデプロイ から、小さな Java プロセスとアプリケーションをコンテナにパッケージし て、デプロイする時代へ。
 App
 App
 App
 App
 App
 App 小さな Java プロセス App App App App
  • 8. クラウドネイティブなアプリケーション
 CloudNative の指針として、12-factor App があるが、コンテナのサイ ズ、起動の速さが重要となってくる。
 I. コードベース
 バージョン管理されている1つのコードベースと複数のデプロイ
 VII. ポートバインディング 
 ポートバインディングを通してサービスを公開する
 II. 依存関係
 依存関係を明示的に宣言し分離する
 VIII. 並行性
 プロセスモデルによってスケールアウトする
 III. 設定
 設定を環境変数に格納する
 IX. 廃棄容易性
 高速な起動とグレースフルシャットダウンで堅牢性を最大化する
 IV. バックエンドサービス 
 バックエンドサービスをアタッチされたリソースとして扱う
 X. 開発/本番一致
 開発、ステージング、本番環境をできるだけ一致させた状態を保つ
 V. ビルド、リリース、実行 
 ビルド、リリース、実行の3つのステージを厳密に分離する
 XI. ログ
 ログをイベントストリームとして扱う
 VI. プロセス
 アプリケーションを1つもしくは複数のステートレスなプロセスとして実行する
 XII. 管理プロセス
 管理タスクを1回限りのプロセスとして実行する

  • 9. GraalVM のネイティブイメージ
 コンテナ環境でも引き続き社内に開発者の多い Java で開発したかっ たが、一般に JVM は起動が遅いので、GraalVM のネイティブイメージ に着目。

  • 10. 新世代 Java フレームワークの選定
 2019/06 に、GraalVM のネイティブイメージに対応している以下の新世 代 Java フレームワークを比較検討し、当時最も親和性の高かった Quarkus の採用を決定。

  • 11. Quarkus の採用
 View API Azure Traffic 
 Manager
 Azure Application Gateway
 2019/08 より、ショップ向けの新規システム開発にて、バックエンドの REST API に Quarkus (0.20.0) を使用して開発。
 Azure Kubernetes Service
 オンプレ
 2019/12 に一部店舗でトライアル中。近日全店舗展開予定。

  • 13. JavaEE との親和性が高い
 Qarkus Blog でも言及されているとおり、Quarkus は MicroProfile と互 換性があり、Java EE との親和性が高い。
 エンタープライズシステムでは、標準である Java EE の採用が多いた め、学習コストは低い。

  • 14. Thorntail 4.x
 JBoss.org の MicroProfile の実装である Thorntail (旧 WildFly Swarm) は次期 Thorntail 4.x の開発を中止。
 Quarkus は JBoss.org のプロジェクトが多く採用されているので、 WildFly からの MicroProfile の移行先としても良い。

  • 15. Quarkus は起動が高速
 新規に開発された DI コンテナ ArC によって、依存性をビルド時に解決 するため、実行時に依存性を解決する Spring Boot と比較して起動が 高速。

  • 16. 初回コール時に実行 
起動時に実行
 初回コール時に実行 
ビルド時に実行
 新世代のフレームワーク
 Quarkus、Micronaut 等の新世代のフレームワークはアノテーションの スキャン、依存性の解決、バイトコードの生成などの処理をビルド時に 実施するため、起動も早く、メモリのフットプリントも小さい。
 「Quarkus 入門」 
  https://www.slideshare.net/agetsuma/quarkus 
 Bean 定義アノ テーションのス キャン @Inject アノテー ションのスキャン 依存性の解決 プロキシバイト コードの生成 Bean の生成 前世代
 新世代

  • 17. Kubernetes の死活監視
 MicroProfile Health も準拠しているため、Kubernetes の Liveness Probe、Readiness Probe も容易に対応できる。
 livenessProbe:
 httpGet:
 path: /health/live
 port: 8080
 initialDelaySeconds: 15
 periodSeconds: 5
 timeoutSeconds: 15
 successThreshold: 1
 failureThreshold: 3
 readinessProbe:
 httpGet:
 path: /health/ready
 port: 8080
 initialDelaySeconds: 15
 periodSeconds: 5
 timeoutSeconds: 15
 successThreshold: 1
 failureThreshold: 3
 

  • 18. テスト機能の充実
 Spring Boot と同様に、UT の実装についてもフレームワークでサポート されており、@SpringBootTest のように @QuarkusTest で CDI のテスト も実装できる。
 特に HTTP ベースのテストは REST Assured が統合されており、Spring Boot と比較すると実装しやすい。
 @QuarkusTest
 public class GreetingResourceTest {
 
 @Test
 public void testHelloEndpoint() {
 given()
 .when().get("/hello")
 .then()
 .statusCode(200)
 .body(is("hello"));
 }
 
 }

  • 19. プロファイルの切り替え
 Spring Boot と同様に、application.properties に、%プロファイル名で定 義し、実行時に -Dquarkus.profile=プロファイル名で切り替えができ、 CI/CD とも親和性が高い。
 quarkus.datasource.url=jdbc:sqlserver://localhost:1433
 %it.quarkus.datasource.url=jdbc:sqlserver://xxxx:1433
 %st.quarkus.datasource.url=jdbc:sqlserver://xxxx:1433
 %pr.quarkus.datasource.url=jdbc:sqlserver://xxxx:1433
 
 JavaEE では、DeltaSpike を利用して実現していたが、はるかに使いや すい。

  • 21. ときおり Quarkus が起動しなくなる
 Quarkus を使い始めた当初は、ときおり以下のようなエラーが発生して Quarkus が起動しなくなる。
 Unable to properly register the hierarchy of the following classes for reflection as they are not in the Jandex index:
 - com.example.Fruit
 - com.example.Car
 Consider adding them to the index either by creating a Jandex index for your dependency or via quarkus.index-dependency properties.

  • 22. Jandex インデックスの生成方法
 Quarkus の Bean Discovery の実装に起因するもので、以下の jandex-maven-plugin の設定を追加することで対応可能。
 (というか、最初から設定されていれば・・・)
 <plugin>
 <groupId>org.jboss.jandex</groupId>
 <artifactId>jandex-maven-plugin</artifactId>
 <version>1.0.7</version>
 <executions>
 <execution>
 <id>make-index</id>
 <goals>
 <goal>jandex</goal>
 </goals>
 </execution>
 </executions>
 </plugin>
 

  • 23. デフォルト設定では fatJar でない
 デフォルトの設定では fatJar とはなっておらず、-runner.jar だけでは起 動しない。target の下の lib の下のファイルも必要。
 $ java -jar code-with-quarkus-1.0.0-SNAPSHOT-runner.jar
 Exception in thread "main" java.lang.NoClassDefFoundError: io/quarkus/runtime/Application
 at java.base/java.lang.ClassLoader.defineClass1(Native Method)
 at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
 at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
 at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:800)
 at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:698)
 at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:621)
 at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579)
 at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
 at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
 at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:27)
 Caused by: java.lang.ClassNotFoundException: io.quarkus.runtime.Application
 at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
 at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
 at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
 ... 10 more

  • 24. fatJar のビルド設定
 fatJar としてビルドするには、quarkus-maven-plugin で uberJar=true を指定すればよい。
 <plugin>
 <groupId>io.quarkus</groupId>
 <artifactId>quarkus-maven-plugin</artifactId>
 <version>${quarkus-plugin.version}</version>
 <executions>
 <execution>
 <goals>
 <goal>build</goal>
 </goals>
 <configuration>
 <uberJar>true</uberJar>
 </configuration>
 </execution>
 </executions>
 </plugin>
 
 

  • 25. 署名付き Jar でエラー
 fatJar としてビルドした場合、依存ライブラリに署名付き Jar が含まれ ていると、SecurityException が発生する。
 $ java -jar target/backend-runner.jar
 Error: A JNI error has occurred, please check your installation and try again
 Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
 at java.base/sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:336)
 at java.base/sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:269)
 at java.base/java.util.jar.JarVerifier.processEntry(JarVerifier.java:273)
 at java.base/java.util.jar.JarVerifier.update(JarVerifier.java:230)
 at java.base/java.util.jar.JarFile.initializeVerifier(JarFile.java:757)
 at java.base/java.util.jar.JarFile.ensureInitialization(JarFile.java:1034)
 at java.base/java.util.jar.JavaUtilJarAccessImpl.ensureInitialization(JavaUtilJarAccessImpl.java:69)
 at java.base/jdk.internal.loader.URLClassPath$JarLoader$2.getManifest(URLClassPath.java:870)
 at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:786)
 at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:698)
 at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:621)
 at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579)
 at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
 at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
 at java.base/java.lang.Class.forName0(Native Method)
 at java.base/java.lang.Class.forName(Class.java:398)
 at java.base/sun.launcher.LauncherHelper.loadMainClass(LauncherHelper.java:760)
 at java.base/sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:655)
 
 

  • 27. JAX-WS 連携がサポートされていない
 JAX-WS (Apache CXF) の extension は #4005 Extension for CXF で 開発中。Apache CXF を直接使うことはできるが、Java 9 以降では JAXB などの API がごっそりなくなっているので依存性の解決は結構 面倒。
 <dependency>
 <groupId>org.apache.cxf</groupId>
 <artifactId>cxf-rt-frontend-jaxws</artifactId>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>javax.xml.ws</groupId>
 <artifactId>jaxws-api</artifactId>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>org.apache.cxf</groupId>
 <artifactId>cxf-rt-transports-http</artifactId>
 <scope>runtime</scope>
 </dependency>

  • 28. fatJar と Apache CXF との相性
 Apache CXF を直接利用することは可能だが、fatJar で利用すると NullPointerException が発生する。
 java.lang.NullPointerException
 at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:85)
 at org.apache.cxf.jaxws.ServiceImpl.initializePorts(ServiceImpl.java:217)
 at org.apache.cxf.jaxws.ServiceImpl.initialize(ServiceImpl.java:160)
 at org.apache.cxf.jaxws.ServiceImpl.<init>(ServiceImpl.java:128)
 at org.apache.cxf.jaxws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:82)
 at javax.xml.ws.Service.<init>(Service.java:112)
 
 
 quarkus-maven-plugin で uberJar=false で、回避はできるが、fatJar は 現状は諦めるしかない。
 ⇒ 現状は -runner.jar と lib 下の jar ファイルをコンテナ化。

  • 29. Mock オブジェクトがいまいち
 Spring Boot では @MockBean で、mockito と連携できるが、Quarkus の場合は Mock クラスは自作する必要がある。
 @Mock
 @ApplicationScoped 
 public class MockExternalService extends ExternalService {
 
 @Override
 public String service() {
 return "mock";
 }
 }
 
 
 Spring Boot + mockito に比べると、テストごとに Mock オブジェクトの 振る舞いをセットアップできなくて不便。

  • 30. Quarkus は画面はサポートしていない
 Quarkus は Spring Boot や Micronaut とは異なり画面は実装できな い。#1911 によると JSP などの View はサポートされておらず、今のと ころサポートするつもりもないらしい。
 現状、フロントエンドは Spring Boot で実装しているが、Micronaut か、 SPA への移行を検討。

  • 31. Azure App Insights との連携がいまいち
 Spring Boot の場合、以下の依存性を追加し、さらに application.properties で設定をするだけで、アプリケーションの変更せ ずに、Application Insights と自動で連携できる。
 <dependency>
 <groupId>com.microsoft.azure</groupId>
 <artifactId>applicationinsights-spring-boot-starter</artifactId>
 <version>2.5.1</version>
 </dependency>
 
 
 azure.application-insights.instrumentation-key=[your ikey from the resource]
 spring.application.name=[your app name]
 Quarkus は まだメジャーではないので Application Insights Spring Boot Starter のようなものは存在しない。

  • 32. Netty に関連する OOM
 Quarkus 内部的に Netty を利用しており、アプリケーション側で Direct Buffer を使う実装が多い場合、Direct buffer memory に起因する OutOfMemoryError が発生し易い。
 Exception in thread "Thread-316" java.lang.OutOfMemoryError: Direct buffer memory
 at java.base/java.nio.Bits.reserveMemory(Unknown Source)
 at java.base/java.nio.DirectByteBuffer.<init>(Unknown Source)
 at java.base/java.nio.ByteBuffer.allocateDirect(Unknown Source)
 at java.base/sun.nio.ch.Util.getTemporaryDirectBuffer(Unknown Source)
 at java.base/sun.nio.ch.IOUtil.read(Unknown Source)
 at java.base/sun.nio.ch.IOUtil.read(Unknown Source)
 at java.base/sun.nio.ch.SimpleAsynchronousFileChannelImpl$2.run(Unknown Source)
 at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
 at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
 at java.base/java.lang.Thread.run(Unknown Source)
 

  • 33. JVM のチューニング
 Java ヒープを多く確保するため、Native メモリのチューニングを攻めた チューニングとしてたため、MaxDirectMemorySize を増やし、 -Djdk.nio.maxCachedBufferSize=262144 を設定。
 -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -XX:InitialCodeCacheSize=64m -XX:ReservedCodeCacheSize=64m -XX:CompressedClassSpaceSize=64m -XX:MaxDirectMemorySize=64m -Djdk.nio.maxCachedBufferSize=262144
  • 34. Quarkus のリリースサイクル
 
 バージョン
 リリース日
 1.0.x
 1.0.0.Final
 2019/10/25
 1.0.1.Final
 2019/11/28
 1.1.x
 1.1.0.Final
 2019/12/17
 1.1.1.Final
 2020/01/07
 1.2.x
 1.2.0.Final
 2020/01/23
 1.2.1.Final
 2020/02/19
 Quarkus はマイナーバージョンアップが早く、新しいマイナーバージョン がリリースされると、パッチバージョンはリリースされない。
 エンタープライズでは、できるだけ長くメジャー/マイナーバージョンを使 い続けたいので、昨今の JDK の問題と同様悩ましい。

  • 35. Quarkus のバージョンアップ
 2 週間のイテレーションでアジャイル開発しており、リリースのタイミング で最新の OS、JDK、Quakus にバージョンアップし、最新のバージョンに 追従することで対応。
 ソースコード
 静的解析
 単体
 テスト
 結合
 テスト
 システム
 テスト
 コンテナ
 保存
 webhook Azure Kubernetes Service
 Azure Container Registory
社内 Docker Registory 
 pull deploy
  • 37. Quarkus おすすめです
 JavaEE に慣れ親しんだエンジニアにとって、MicroProfile の移行先とし て、学習コストも低くお勧め。
 1) REST API だけでよく、画面は実装する必要はない場合
 2) JavaEE の慣れ親しんだエンジニアが社内に多い場合
 3) WildFly 等の JBoss.org の製品を利用している場合
 4) Microservice、CloudNative な開発を視野に入れている場合
 ただし、バージョンアップが早いため、短いリリースサイクルで、最新 バージョンに追従していける体制が必要。

  • 39. ネイティブイメージの利用について
 「Javaの起動時間といかに戦うか」 
  https://speakerdeck.com/kishida/how-to-fight-against-java-warmup-time 
 
 JIT
 AOT
 ビルド時間
 ○
 ✕
 起動時間
 ✕
 ○
 スループット
 ○
 ✕
 ピークパフォーマンスまで 
 ✕
 ○
 ネイティブイメージにも将来的には挑戦したいが、AOT にもメリデメが あり、JIT でも十分起動は高速なので、ネイティブイメージであと数秒削 るのが有意義なのかは、慎重に判断。

  • 40. CDS の利用について
 「Javaの起動時間といかに戦うか」 
  https://speakerdeck.com/kishida/how-to-fight-against-java-warmup-time 
 現状は LTS の Java 11 を利用しているが、リリースごとに最新の Java に追従していくなら、LTS でなくてよいので、最新の Java に移行し、 Class-Data Sharing を利用した起動の高速化も検討。
 機能
 バージョン
 JEP
 Application Class-Data Sharing 
 Java 10
 JEP 310
 Default CDS Archives 
 Java 12
 JEP 341

  • 41. Azure Application Insights 対応
 Java 用の Application Insights の API は提供されているので、 Application Insights Spring Boot Starter のようなものを実装し、Spring Boot と同等にアプリケーションを監視できるようにしたい。

  • 43. #
 資料名
 ①
 【JJUG CCC 2019 Fall】JavaオンプレシステムをAKS + Quarkusに移行した話
 ②
 Quarkus is Eclipse MicroProfile 3.2 compatible!
 ③
 Thorntail Community Announcement on Quarkus
 ④
 Quarkus Dependency Injection
 ⑤
 Quarkus入門
 ⑥
 Unable to forward from a JAX-RS service to JSP
 ⑦
 Extension for CXF
 ⑧
 Skip adding signature files to the generated uber jar
 ⑨
 Fixing Java's ByteBuffer native memory "leak"
 ⑩
 Javaの起動時間といかに戦うか
 参考資料