The Modern Java Platform - 2021 Edition
Many developers were burned by the overly complex world of Java back in the early 2000s. The Gang of Four patterns and middleware / J2EE / Java EE led to ridiculous levels of alleged decoupling as is evident in this sequence diagram from an open source J2EE ecommerce system I worked on in 2002:
Back in 2014 I wrote about how things had changed: Java Doesn’t Suck – You’re Just Using it Wrong. But six years have passed since I wrote that and things have continued to improve, making the Java platform a fantastic option when building microservices, data pipelines, web apps, mobile apps, and more. Let’s walk through some of the “modern” (as of 2021) aspects to the Java platform.
Running One-Off/Admin Jobs for Cloud Run Services
Disclaimer: This is not officially supported by Google Cloud.
Cloud Run hosts services that handle HTTP requests but sometimes you need a way to run one-off / admin jobs with the same settings and container image. At this time the managed Cloud Run service doesn’t provide a way to run those kinds of processes and running them through HTTP handlers can result in short timeouts (5 minutes by default, max 60 minutes), the possibility to accidentally run them more than once, and potential security issues. Whether you need this for schema migrations, management tasks, or something else, I’ve made it easy for you. Click to launch a tool in Cloud Shell that will walk you through it:
Want to see more about how it works? Watch this short demo:
Container-based Serverless Scheduled Jobs on Google Compute Engine
Most of my compute workloads today are on Cloud Run, a serverless for containers platform. But some workloads like scheduled jobs don’t fit the service-oriented model of Cloud Run. There are many places I can run those workloads but I’d like to keep the serverless “pay for what you use” model and still use containers as my packaging format. I could use Kubernetes for these and use Cloud Run for Anthos to run everything in one place but I wanted something more bare-bones. I created a way to hook up Cloud Scheduler so that it starts scheduled jobs from containers on Google Compute Engine. Here is a video walkthrough for how to set it up and use it:
GraalVM Native Image Tips & Tricks
Elastic infrastructure that scales up & down based on demand is not just a “serverless” fad but an operational model which reduces cost and waste. Yet there is a little devil lurking under the covers… When an application / microservice needs to spin up based on demand there can be some lag as the application needs to be downloaded to the node, potentially a VM needs to be started, the application itself needs to be started, and potentially local caches need to be hydrated. In traditional enterprise systems this “cold start” process can realistically take tens of minutes. But it’s near impossible to have demand-based scaling when things take that long to start.
GraalVM is a Java Virtual Machine implementation that addresses parts of the “cold start” problem by doing Ahead-Of-Time (AOT) compilation on JVM-based applications. GraalVM can create a “native image” of your application so that it no longer needs to run inside a JVM. This can reduce startup time and in some cases improve overall performance. The native images can also be much smaller than the usual OS + JVM + all dependency JARs. For example, a recent application I was working on went from a pretty trim 208MB docker image (OS + JVM + deps + app) that started in 2 seconds, down to 14MB and a 0.5s startup time. Sounds amazing! But there are some caveats, tips, and tricks I’d like to share with you.