Welcome
This workshop offers attendees an intro-level, hands-on session on Cloud performance using different Java runtimes: From developing microservices written in Quarkus/Spring Boot/Micronaut, to packaging them in Docker containers, deploy them in Azure Container Apps and monitor the performances. You will analyze CPU load as well as memory usage. And then you will establish a baseline, so you can see the impact of scaling out or scaling up containers.
This workshop is a BYOL (Bring Your Own Laptop) session, so bring your Windows, OSX, or Linux laptop. You need JDK 17 on your machine, Apache Maven (3.9.x), Docker, Azure CLI and other few tools. On Mac and Windows, Docker for x is recommended instead of the Docker toolbox setup.
What you are going to do:
-
Create your own GitHub Repo based on a GitHub Template
-
Develop one microservice that consumes CPU and memory with Quarkus, another one with Spring Boot and Micronaut
-
Compile, package and containerize these microservices
-
Run these microservices locally on your machine
-
Create an Azure Container Apps environment
-
Deploy your containers to Azure Container Apps
-
Execute and monitor the microservices using different performance parameters
-
Load test the microservices
-
Analyze CPU load and scale containers appropriately
-
Analyze memory and scale containers appropriately
-
And much more!
Ready? Here we go! Check the workshop at https://aka.ms/java-runtimes of flash the QR Code if you don’t want to type.
Presenting the Workshop
This workshop is about understanding the performance of Java runtimes in a containerized environment in the cloud. It is a hands-on workshop, so you will be doing a lot of things in your local machine as well as on Azure Container Apps.
Today, most of us containerize our Java applications and then deploy them to the cloud. But how do we know if our application is performing well? What do we do if we see a spike in CPU or memory usage? Do we scale out or scale up? Do we change the JVM parameters? Do we change the container size? And what about having native binaries and compiling our code with GraalVM?
What Is This Workshop About?
To understand performance in a containerized environment we need a few simple algorithms that consume CPU and memory. We will then develop these same algorithms in Quarkus, Spring Boot and Micronaut, deploy them to Azure Container Apps and monitor their performance.
The algorithm consuming CPU will be a simple loop. The higher the iteration, the more CPU it uses:
while (iterations > 0) {
if (iterations % 20000 == 0) {
try {
Thread.sleep(20);
} catch (InterruptedException ie) {
}
}
iterations--;
}
The algorithm consuming memory will be a simple hashmap that we will fill with bites. The more bits you have, the more memory it uses:
HashMap hunger = new HashMap<>();
for (int i = 0; i < bites * 1024 * 1024; i += 8192) {
byte[] bytes = new byte[8192];
hunger.put(i, bytes);
for (int j = 0; j < 8192; j++) {
bytes[j] = '0';
}
}
What Will You Be Developing?
You will be developing 3 microservices, each doing the exact same thing (consuming CPU and memory), but using a different Java runtime: Quarkus, Spring Boot and Micronaut:
-
A REST endpoint (used as an entry point) that will execute our CPU and memory consuming algorithms
-
A repository used to store the results of the CPU and memory consuming algorithms
-
A statistics entity mapped to the relational database
What Will You Be Deploying?
Once developed and tested locally, you will be packaging your microservices in Docker containers and deploy them to Azure Container Apps:
-
You will first create an Azure Container Apps environment (a.k.a. ACA) in Azure
-
You will create a managed PostgreSQL database in Azure (one single database for all 3 microservices but one table per microservice)
-
You will create an Azure Registry to manage the Docker images
-
You will package each microservice in Docker images and configure them so they can connect to the PostgreSQL database
-
You will then push these images to Azure Container Registry
-
Then you will deploy the Docker images of your microservices into the ACA environment
Structure of the Workshop
You have this material in your hands, and you can now follow it step by step. The structure of this workshop is as follows:
-
Setting Up the Project: In this section, you will install all the tools and code to be able to bundle, package and deploy our application.
-
Developing the Quarkus Application: In this section, you will develop a microservice using Quarkus, test it and run it locally.
-
Developing the Micronaut Application: In this section, you will develop a microservice using Micronaut.
-
Developing the Spring Boot Application: In this section, you will develop a microservice using Spring Boot.
-
Setting Up the Azure Container Apps Environment: This section introduces Azure and the Container Apps service to prepare all the needed resources for our application. You will create an entire infrastructure on Azure (Container Registry, PostgreSQL database, etc.) to make everything ready for deployment.
-
Deploying the Applications: In this section, you will set up a CI/CD pipeline using GitHub Actions so that our application builds and deploy automatically on new commits. You will build Docker images out of our microservices, push them to Azure Registry, all that using Docker and Azure CLI.
-
Load Testing, Scaling and Monitoring the Applications: In this section, you will add some load to your microservices, monitor them, scale them, check the logs, etc.
-
Going Native: In this section you will compile your microservices with GraalVM, package them, deploy them on ACA, and see how it impacts the performance.
This workshop is modular, meaning that you can skip some sections if you want. For example, if you’re not interested in developing some microservices variants, you can instead use these pre-built Docker images when deploying to Azure Container Apps:
|
What Do You Have to Do?
This workshop should be as self-explanatory as possible. So your job is to follow the instructions by yourself, do what you are supposed to do, and do not hesitate to ask for any clarification or assistance; that’s why the team is here.
Oh, and be ready to have some fun!
Presenting Azure and Cloud Services
Azure is Microsoft’s cloud platform. It provides a wide range of services, from compute to storage, from databases to AI, from IoT to containers, from networking to security, and much more.
For this workshop, we’ll use in particular the following services:
-
Azure Container Apps: a managed container service to run our microservices.
-
Azure Container Registry: a private container registry to store our Docker images.
-
Azure Database for PostgreSQL: a managed PostgreSQL database.
What’s Azure Container Apps?
Azure Container Apps is a fully managed serverless container service on Azure. It allows you to run containerized applications without worrying about orchestration or managing complex infrastructure such as Kubernetes. You write code using your preferred programming language or framework (in this workshop it’s Java and Quarkus, but it can be anything), and build microservices with full support for Distributed Application Runtime (Dapr). Then, your containers will scale dynamically based on HTTP traffic or events powered by Kubernetes Event-Driven Autoscaling (KEDA).
There are already a few compute resources on Azure: from IaaS to FaaS . Azure Container Apps sits between PaaS and FaaS . On one hand, it feels more PaaS, because you are not forced into a specific programming model and you can control the rules on which to scale out / scale in. On the other hand, it has quite some serverless characteristics like scaling to zero, event-driven scaling, per second pricing and the ability to leverage Dapr’s event-based bindings.
Container Apps is built on top of Azure Kubernetes Service, including a deep integration with KEDA (event-driven auto scaling for Kubernetes), Dapr (distributed application runtime) and Envoy (a service proxy designed for cloud-native applications). The underlying complexity is completely abstracted for the end-user. So no need to configure your K8S service, deployment, ingress, volume manifests… You get a very simple API and user interface to configure the desired configuration for your containerized application. This simplification means also less control, hence the difference with AKS.
Azure Container Apps has the following features:
-
Revisions: automatic versioning that helps to manage the application lifecycle of your container apps
-
Traffic control: split incoming HTTP traffic across multiple revisions for Blue/Green deployments and A/B testing
-
Ingress: simple HTTPS ingress configuration, without the need to worry about DNS and certificates
-
Autoscaling: leverage all KEDA-supported scale triggers to scale your app based on external metrics
-
Secrets: deploy secrets that are securely shared between containers, scale rules and Dapr sidecars
-
Monitoring: the standard output and error streams are automatically written to Log Analytics
-
Dapr: through a simple flag, you can enable native Dapr integration for your Container Apps
Azure Container Apps introduces the following concepts:
-
Environment: this is a secure boundary around a group of Container Apps. They are deployed in the same virtual network, these apps can easily intercommunicate easily with each other and they write logs to the same Log Analytics workspace. An environment can be compared with a Kubernetes namespace.
-
Container App: this is a group of containers (pod) that is deployed and scale together. They share the same disk space and network.
-
Revision: this is an immutable snapshot of a Container App. New revisions are automatically created and are valuable for HTTP traffic redirection strategies, such as A/B testing.
Setting Up the Project
Before starting the development, you need to set up the project. This includes:
-
Creating a new project on GitHub based on an existing GitHub template
-
Setting up your development environment, either by installing all the needed tools manually, or installing a few tools and relying on VSCode and Dev Containers (easier as everything is set up for you).
Using the GitHub Template
Open this GitHub repository, click on Use this template
then Create a new repository
.
You will be redirected to the repository creation page.
Select the owner of the repository, enter a name for your new repository (eg.
aca-java-runtimes-workshop
), set the repo visibility to public
and click on Create repository from template
.
Once the repository is created, you have 3 options to work on the project:
-
You can work locally using your preferred IDE, but you will need to install all the tools manually.
-
You can work directly in GitHub Codespaces, without having to install anything on your machine.
-
You can work locally using VSCode, Docker and Dev Containers, so you have a pre-configured development environment.
All these options are described in the following sections. The fastest and easiest way is to use GitHub Codespaces, but you can pick the one that suits you best.
If you want to work locally, first you need to clone the project on your machine using git (you can skip these steps if you choose to use GitHub Codespaces).
1. Select the Code button, then copy your repository url.
2. Open a terminal and run:
git clone <your_repo_url>
Setting Up Your Development Environment Manually
If you decide to setup your environment yourself, you will need to install the following tools:
Java 17 |
|
Maven 3.9.x |
|
Docker 20.x |
|
Azure CLI |
|
Git |
|
GitHub account |
|
Azure account |
|
A code editor, such as VS Code, Eclipse, or IntelliJ |
|
cURL (or any other HTTP client) |
|
GraalVM (optional) |
|
jq (optional) |
You can test your installation by running the following commands:
java -version
mvn --version
docker --version
az --version
git --version
curl --version
jq --version
If everything is installed correctly, you should see the version of each tool.
If you are on Windows, you will need to run bash commands. You have multiples way to do that:
|
Setting Up Your Environment in GitHub Codespaces
GitHub Codespaces allows you to have an instant dev environment already prepared for this workshop.
Codespaces includes up to 60 hours of free usage per month for all GitHub users, see [the pricing details here](https://github.com/features/codespaces). |
After your project created on GitHub, select the Code button, then the Codespaces tab and click on Create Codespaces on main.