Share
Embed
What's the Magic Behind Quarkus
Quarkus is revolutionizing the way that we develop Java applications for the cloud-native era. Do you want to learn why Quarkus is different from everything else? Then come and join us on this session to take a look at how Quarkus works and the techniques it uses to achieve its dramatic startup speed improvements. As part of this we will also cover the Quarkus extension API, so you can see how to write your own extensions that take advantage of Quarkus’ unique architecture.
Edson Yanaga
July 24, 2019
Transcript
54 slides
-
From monolith to... !4 • 1 monolith ≈ 20 microservices
≈ 200 functions • Scale to 1 vs scale to 0 • Start up time MONOLITH MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE MICRO SERVICE F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F -
!5 Why go through this pain? Agility, Scalability, Faster Business
Reactivity Container platform App 1 Data App 2 Data App 3 Data App 4 App 5 Data -
• Startup overhead ◦ # of classes, bytecode, JIT •
Memory overhead ◦ # of classes, metadata, compilation !6 The hidden truth about Java + containers RSS Heap Metaspace off-heap -
!7 Container platform Node NodeJS NodeJS NodeJS NodeJS NodeJS NodeJS
NodeJS Node Go Go Go Go Go Go Go Go Go Go Go Go Go Go Node HotSpot Heap HotSpot Heap HotSpot Heap HotSpot Heap The hidden truth about Java + containers -
WHAT IS QUARKUS? QUARK: elementary particle / US: heart of
computer science -
!9 A cohesive platform for optimized developer joy: • Based
on standards, but not limited • Unified configuration • Zero config, live reload in the blink of an eye • Streamlined code for the 80% common usages, flexible for the 20% • No hassle native executable generation Benefit No. 1: Developer Joy -
!10 Benefit No. 2: Supersonic Subatomic Java Memory (RSS) in
Megabytes Quarkus + GraalVM 13 MB Quarkus + OpenJDK 74 MB Traditional Cloud-Native Stack 140 MB REST -
!11 Benefit No. 2: Supersonic Subatomic Java Memory (RSS) in
Megabytes REST + CRUD Quarkus + GraalVM 35 MB Quarkus + OpenJDK 130 MB Traditional Cloud-Native Stack 218 MB -
!12 Benefit No. 2: Supersonic Subatomic Java Boot + First
Response Time (in seconds) Quarkus + GraalVM 0.014 Seconds REST REST + CRUD Quarkus + OpenJDK 0.75 Seconds Quarkus + GraalVM 0.055 Seconds Quarkus + OpenJDK 2.5 Seconds Traditional Cloud-Native Stack 9.5 Seconds Traditional Cloud-Native Stack 4.3 Seconds Time to first response -
!13 Benefit No. 3: Unifies Imperative and Reactive • Combine
both Reactive and imperative development in the same application • Use the technology that fits your use-case • Key for reactive systems based on event driven apps @Inject SayService say; @GET @Produces(MediaType.TEXT_PLAIN) public String hello() { return say.hello(); } @Inject @Stream(”kafka”) Publisher<String> reactiveSay; @GET @Produces(MediaType.SERVER_SENT_EVENTS) public Publisher<String> stream() { return reactiveSay; } -
!14 Benefit No. 4: Best of Breed Frameworks & Standards
Eclipse Vert.x Hibernate RESTEasy Apache Camel Eclipse MicroProfile Netty Kubernetes OpenShift Jaeger Prometheus Apache Kafka Infinispan -
GraalVM You keep using that word. I do not think
it means what you think it means. The Enabler -
!16 JVM CI Sulong (LLVM) Truffle Graal Compiler Substrate VM
Java HotSpot VM -
Closed-world assumption !17 Dead code elimination Substrate VM Classes JDK
Classes JDK Classes Substrate VM Classes Java Application Classes Java Application Classes Native Executable -
!18 Not supported The Dark Side • Dynamic classloading •
InvokeDynamic & Method handles • Finalizer • Security manager • JVMTI, JMX, native VM Interfaces OK with caveats in usage • Reflection (manual list) • Dynamic proxy (manual list) • JNI (manual list) • Static initializers • Lambda, Threads (OK, pfff!) • References (similar) -
!19 Not supported The Dark Side • Dynamic classloading •
InvokeDynamic & Method handles • Finalizer • Security manager • JVMTI, JMX, native VM Interfaces OK with caveats in usage • Reflection (manual list) • Dynamic proxy (manual list) • JNI (manual list) • Static initializers • References (similar) The Good Parts -
!21 What does a framework do at startup time Move
startup time to build time • Parse config files • Classpath & classes scanning ◦ for annotations, getters or other metadata • Build framework metamodel objects • Prepare reflection and build proxies • Start and open IO, threads etc -
!22 Do the work once, not at each start All
the bootstrap classes are no longer loaded Less time to start, less memory used Less or no reflection nor dynamic proxy Build time benefits -
!23 Drives the gathering of metadata needed by GraalVM More
Build time benefits • based on framework knowledge • Classes using reflection, resources, etc Minimize dependencies Help dead code elimination -
!24 The end result of a Quarkus build should be
just enough bytecode to start the services that your application requires Anatomy of a Quarkus Application -
!25 Traditional Application Application Startup • Scan for annotations •
Parse descriptors • Generate metamodel • Start Services Quarkus • Start Services -
!26 The final application contains Anatomy of a Quarkus Application
• Your (possibly transformed) application code • All libraries needed for runtime • Generated code to wire up and start your services • Generated CDI (ArC) bean classes -
!27 Quarkus Extensions RESTEasy Netty Hibernate ORM Hibernate Validator MP
OpenAPI MP JWT Eclipse Vert.X Agroal (conn pool) Narayana JTA MP Reactive Messaging Apache Camel ... Quarkus Core Arc (DI) Jandex Gizmo Graal SDK HotSpot SubstrateVM -
!28 Quarkus Consists of Two Parts Core Runtime Core Deployment
Undertow Runtime Undertow Deployment ArC Runtime ArC Deployment -
!29 Build Process Compile Provision (curate) Wiring & Assemble (deployment)
AOT Native Compilation Hotspot Runnable & Image Native Executable & Image app.jar frameworks Runnable java app native-app -
!31 Provisioning Phase • Applications only depend on runtime components
• But we need the deployment components to execute the build • Provisioning phase resolves the required deployment dependencies -
!32 Provisioning Phase • Extensions contain a quarkus-extension.properties, generated by
the extension-maven-plugin • This tells Quarkus what the corresponding deployment artifact is -
!34 Creating the runnable application Augmentation Phase • Processing done
by @BuildStep methods • All processors produce and consume BuildItem instances • Ordering is based on a dependency graph, a build step is executed when all its dependencies are available -
!35 BuildItem • All information flows through this process via
BuildItem instances • Two types, SimpleBuildItem and MultiBuildItem • A @BuildStep method will be run as soon as all the items it depends on have been produced • The build is seeded with some initial items (e.g. the current application root) • The build asks for some specific outputs (e.g. GeneratedClassBuildItem) • Core build items are in io.quarkus.deployment.builditem -
!36 Build Graph • The build is a directed graph,
it starts with the requested outputs, and then figures out which @BuildStep methods it needs to call to achieve this and in what order • If your method does not produce anything it needs then it is not called -
!37 CombinedIndexBuildItem Important Items • Holds the Jandex annotation index
• Can be used to look at any annotation or type hierarchy -
!38 AdditionalBeanBuildItem Important Items • Producing this turns a given
class into a CDI bean • If you have classes in your runtime module that you want to be beans you should produce one of these -
!40 Declarative Config Configuration • Configuration is done via @ConfigRoot
objects • All config is under the quarkus.* namespace • All config must have javadoc, which used as the documentation in the generated config file -
!42 Recorders let you invoke on an object at deployment
time, but the actual invocation gets delayed to runtime. Bytecode Recording -
!43 Serializing logic and data Bytecode Recording • Recording allows
you to specify what happens at startup time, without knowing anything about bytecode • Invocations made on a recorder are written to bytecode and executed at runtime • Primitives, JavaBean style objects and collections can all be passed as arguments • The return values can be passed into other recorders (although cannot be used directly) -
!44 Return Values • The return value from a recorder
cannot be used directly (the object it represents has not actually been created yet) • But they can be passed to other recorders methods • We do this by creating proxies, so if the return type cannot be proxied wrap it in a RuntimeValue<> • This does not have to be the same recorder, or even the same build step • To pass them between build steps wrap them in a BuildItem -
!46 Quarkus simplifies the process Substrate • SubstrateVM has a
lot of limitations compared to a normal JVM • Quarkus provides tools to easily work around these limitations • Most of these take the form of build items to explicitly request substrate functionality • For a full list see io.quarkus.deployment.builditem.substrate package • Also we support compile time boot -
!47 Not supported The Dark Side • Dynamic classloading •
InvokeDynamic & Method handles • Finalizer • Security manager • JVMTI, JMX, native VM Interfaces OK with caveats in usage • Reflection (manual list) • Dynamic proxy (manual list) • JNI (manual list) • Static initializers • Lambda, Threads (OK, pfff!) • References (similar) -
!48 ReflectiveClassBuildItem Native Build Items • Reflection does not work
in native images unless it is explicitly enabled • This build item allows you to enable reflection for a given class • Fine grained, so you can choose if you want methods, fields and constructors registered -
!49 ReflectiveHierarchyBuildItem Native Build Items • Registers everything about the
class for reflection • Supertypes, Field types, method parameters etc • Good for serialization use cases, where you need to set everything via reflection -
!50 SubstrateResourceBuildItem Native Build Items • Resources are not included
by default in SubstrateVM • Using this build item you can specify resources that you want to include in the image -
!51 Boot once, run everywhere Compile time boot • When
SubstrateVM creates a native image it can run java static initializers as part of the process • These run in a normal JVM, with no restrictions • The results are serialized directly into the native image • If you record code with @Record(ExecutionTime.STATIC_INIT) then this code will be run once at native image build time • The results are directly unpacked into memory when the native image is actually run -
!53 Unit and Integration Tests Extension Testing Framework • @QuarkusUnitTest
can be used to test a different application for each test class • Quarkus is started and stopped between each class • @QuarkusTest can also be used (especially for native image), but needs its own ‘integration-tests’ module • A comprehensive test suite will generally have both