The cloud is becoming more and more essential in today’s world. And tools developers use to create cloud-native applications are improving everyday. But as a developer who has had no previous experience with the cloud or containers, there were a lot of hurdles I had to overcome:
- The complexity of the cloud toolchain available to developers
- The ability to iteratively deploy cloud applications
The following describes how I learned to use Appsody to easily create cloud ready applications, followed by how I used OpenJ9’s SCC to dramatically reduce the deployment times of my application.
Appsody
I first heard about Appsody from my colleagues at work. Appsody is a layer on top of Docker that allows containers to be easily managed. It provides bundled images (called stacks) for major development environments such as Node.js, Java Spring, Rocket, Flask and many more. Installing Appsody is fairly simple. If it does not support your platform, they provide Golang binaries for download that works on all platforms that Golang supports. Assuming you have Docker installed and running, let’s go over some basic Appsody usage:
~$ mkdir my_new_project
~$ cd my_new_project
~$ appsody init java-spring-boot2
This will create a new Java Spring Boot project in my_new_project
and inside, you may see something similar to this:
|-- .appsody-config.yaml
|-- .gitignore
|-- .mvn
| `-- wrapper
| |-- MavenWrapperDownloader.java
| |-- maven-wrapper.jar
| `-- maven-wrapper.properties
|-- .vscode
| |-- launch.json
| `-- tasks.json
|-- mvnw
|-- mvnw.cmd
|-- pom.xml
`-- src
|-- main
| |-- java
| | `-- application
| | |-- LivenessEndpoint.java
| | `-- Main.java
| `-- resources
| |-- application.properties
| `-- public
| `-- index.html
`-- test
`-- java
`-- application
`-- MainTests.java
You can now modify your Spring Boot project however you like. After making changes, to deploy your project as a containerized application, simply run appsody run
inside the project root directory.
So Appsody solves our issue of managing complexity, but what about shaving down the deployment times?
OpenJ9 + SCC
One of the things that really slows down the development cycle is the time it takes to get the application running. Having to restart your Java application constantly to test if your changes worked can accumulate to a lot of time sitting around. A feature to combat this is OpenJ9’s Shared Classes Cache, which greatly reduces start up times for your Java application.
Shared Classes Cache (SCC)
From the OpenJ9 website:
Sharing class data between JVMs improves start up performance and reduces memory footprint.
Start up performance is improved by placing classes that an application needs when initializing into a shared classes cache. The next time the application runs, it takes much less time to start because the classes are already available.
Building An Image With SCC
As of writing this post, the changes I have made to Appsody are not upstreamed, but I will discuss the changes I’ve made to achieve my results.
Currently, Appsody’s Java Spring Boot stack is using IBM Java on the backend (which as we all know, is built on the OpenJ9 JVM). But we want to take advantage of OpenJ9’s Shared Classes Cache (SCC) ability, so we will be editing the Java Spring Boot stack.
~$ git clone https://github.com/appsody/stacks.git
~$ cd stacks
Now change the following lines to incubator/java-spring-boot2/image/Dockerfile-stack
:
Line 1: - FROM maven:3.6-ibmjava-8
Line 1: + FROM maven:3.6-jdk-8-openj9
...
Line 46: ENV APPSODY_TEST_KILL=true
Line 47: + ENV OPENJ9_JAVA_OPTIONS="-Xshareclasses:name=appsody_scc,cacheDir=/project/user-app,enableBCI -Xscmx80M"
Line 48: ENV PORT=8080
...
And then repackage it:
~$ cd incubator/java-spring-boot2
~$ appsody stack package
Now you should see your image when running Docker:
~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
dev.local/java-spring-boot2 SNAPSHOT 6faba0461d97 a few seconds ago 417MB
Now to use this new image for your development:
~$ mkdir my_new_project_scc
~$ cd my_new_project_scc
~$ appsody init dev.local/java-spring-boot2
Now you can continue developing as you would normally, but gain the speed benefits of OpenJ9’s SCC speed improvements between iterative builds.
Benchmarks
We created two default Java Spring Boot projects provided by Appsody; one with SCC enabled and one without. Here are the numbers:
OpenJ9 Without SCC
# initial run
Started Main in 4.018 seconds (JVM running for 4.532)
# subsequent runs
Started Main in 3.92 seconds (JVM running for 4.486)
Started Main in 3.971 seconds (JVM running for 4.51)
Started Main in 4.049 seconds (JVM running for 4.6)
Started Main in 3.989 seconds (JVM running for 4.527)
OpenJ9 With SCC
# initial run
Started Main in 4.498 seconds (JVM running for 4.745)
# subsequent runs
Started Main in 1.984 seconds (JVM running for 2.173)
Started Main in 1.762 seconds (JVM running for 1.93)
Started Main in 1.62 seconds (JVM running for 1.773)
Started Main in 1.721 seconds (JVM running for 1.873)
Conclusions
OpenJ9’s SCC feature paired with Appsody’s ease of use greatly reduces the development barrier and time for developers to produce and iterate on their cloud applications. Although the tests may seem to show only a few seconds of difference, this can change dramatically as your application grows and become more complex.