Optimizing Java's serverless capabilities in Kubernetes

ce4f77f1e1691b262b296bff8f170027.gif

The new titanium cloud service has shared 742 technical dry goods for you

78a1762a081b496608967d6813fe78f5.gif

Achieve faster startup and smaller memory footprint to run serverless functions on Kubernetes.

Faster startup and smaller memory footprint are always important in Kubernetes due to the expense of running thousands of application pods and saving costs by using fewer worker nodes and other resources. On containerized microservices on Kubernetes, memory is more important than throughput because:

l It is more expensive due to eternity (unlike CPU cycles).

l Microservices multiply overhead costs.

l A single application becomes N microservices (for example, 20 microservices ≈ 20GB)

This significantly impacts serverless feature development and Java deployment models. That's because many enterprise developers have chosen alternatives like Go, Python, and Nodejs to overcome performance bottlenecks -- until now, thanks to Quarkus, a new Kubernetes-native Java stack. This article describes how to optimize Java performance to run serverless functions on Kubernetes using Quarkus.

container-first design

Traditional frameworks in the Java ecosystem come at a price in terms of the memory and startup time required to initialize those frameworks, including configuration processing, classpath scanning, class loading, annotation processing, and building a metamodel of the world, which frameworks require. This is multiplied again and again for different frameworks.

Quarkus helps address these Java performance issues by "left-shifting" nearly all overhead to the build phase. By doing code and framework analysis, bytecode transformation, and dynamic metamodel generation only once at build time, you end up with a highly optimized runtime executable that starts super fast and doesn't require all the memory of a traditional launch , because the work is done once in the build phase.

7a6f0fa79987f08a356a38c55034849c.png

What's more, Quarkus allows you to build native executables with performance advantages, including amazingly fast startup times and very small resident set size (RSS) memory, enabling instant scaling and high Density memory utilization - native Java stack.

dc52e27008835ca778813714b7916f16.png

This is a quick example of how to use Quarkus to build a native executable from a Java serverless functional project.

01

Create a Quarkus serverless Maven project

This command generates a Quarkus project (such as quarkus-serverless-native) to create a simple function:

99030c5c41f8e4bf4c7bed09226b8375.png

02

Build native executables

You need a GraalVM to build native executables for Java applications. You can choose any GraalVM distribution, such as Oracle GraalVM Community Edition (CE) and Mandrel (a downstream distribution of Oracle GraalVM CE). Mandrel is designed to support building Quarkus native executables on OpenJDK 11.

Open pom.xml, you will find this native configuration file. You'll use this to build native executables:

23839b60518143b1e16535f6259370f0.png

Note: You can install GraalVM or the Mandrel distribution locally. You can also download the Mandrel container image to build it (like I did), so you'll need a container engine (e.g. Docker) running locally.

Assuming you have already started the container runtime, run one of the following Maven commands.

For Docker:

4768f8eac0fda27db5f6f7e4acffbe1b.png

For Podman:

86cea9334c45503bd888e834d21a4734.png

The output should end with BUILD SUCCESS.

b41947f06f5bce19eddb0b679a195cc3.png

To run native executables directly without a Java Virtual Machine (JVM):

0b16438af81ed47a290e766a1dcd5b96.png

The output will look like this:

fda4d1cd884f3a77ac457fc53937788b.png

Supersonic! Startup time is 19 ms. Times may vary depending on your environment.

It also has extremely low memory usage, as reported by the Linux ps utility. While the app is running, run this command in another terminal:

9a0bbeed24fee27946d822f8af6af9df.png

You should see something like:

eb5f2a722c12c24016cecbc7cc3a14ed.png

This process uses approximately 11MB of memory (RSS). Quite compact!

Note: RSS and memory usage for any application (including Quarkus) will vary based on your specific environment and will increase as the application experience loads.

You can also access the function using the REST API. Then the output should be Hello RESTEasy:

ceba459e3562b8dc7fc97dd2c660c41d.png

03

Deploy the function to the Knative service

If you haven't already, create a namespace (e.g. quarkus-serverless-native) on OKD (OpenShift Kubernetes Distribution) to deploy this native executable as a serverless function. Then add a quarkus-openshift extension for Knative service deployment:

ca5ba86ac6da09e449b07b8f9206f3ce.png

Add the following variables in src/main/resources/application.properties to configure Knative and Kubernetes resources:

159052bdd0ec30e30e8fd9549cdaca10.png

Build a native executable, then deploy it directly to the OLD cluster:

dfa1f29acee9fdfa14b503dab9b0f1a6.png

Note: Make sure to log in to the correct project (e.g. quarkus-serverless-native) using the oc login command ahead of time.

The output should end with BUILD SUCCESS. It takes a few minutes for the native binary to build and deploy the new Knative service. After successfully creating the service, you should see the Knative service (KSVC) and revision (REV) using the kubectl or oc command tools:

2af896920beaa32d7b12143e6a7150b7.png

04

Access native executable functions

Retrieve the serverless function's endpoint by running the following kubectl command:

ef2112c814edc57f94359f9fa9ca4187.png

The output should look like this:

c188ff58c1a3d39776fcfc85b68b0d2b.png

Access the route URL with the curl command:

e94d868e15066bf728dd45727231b965.png

In less than a second, you'll get the same result as locally:

1ff45db629477ac5dd444be6e783a359.png

When you visit the Quarkus running pods logs in the OLD cluster, you will see native executables running as Knative services.

5ff5b7d56bf9954aac84f60633cc33b7.png

What's next?

You can use the GraalVM distribution to optimize Java serverless functions and deploy them as serverless functions on Knative and Kubernetes. Quarkus achieves this kind of performance optimization with simple configuration in common microservices.

Original link:

https://opensource.com/article/21/6/java-serverless-functions-kubernetes

    recommended reading   

ae39603a5a43e5a112a2f0a5b9ab342d.png

5d6145d14af908a0ed7d133c1c251aad.png

    recommended video    

Guess you like

Origin blog.csdn.net/NewTyun/article/details/130377114