06/14/2023 | Press release | Distributed by Public on 06/14/2023 08:23
By:Chinmoy Das, Managing Principal - Architecture (Digital Engineering)
Many of our customers are modernizing their platforms from legacy stacks to micro-service-based architecture in Amazon Web Services (AWS). The source technology is as varied as Dot Net, COBOL, older versions of Java, etc. We consider different aspects like target application architecture (K8-based or aws serverless applications like Lambda or Elastic Container Service (ECS) with Fargate) and target languages (e.g., different frameworks of Java, NodeJS, Python, Dot Net, etc.) to come up with the proposed solution which operates on optimal cost and still becomes scalable. This article outlines possible approaches for identifying such target technology stack by application architects.
The major criteria for selecting a proposed technology stack are as below:
Let us see how each of these attributes impacts the technology selection process.
Uniform transaction frequency pattern, as well as very high concurrency, is better addressed by ECS, and Elastic Kubernetes Services (EKS), where abrupt scale-out (for example, 100 transactions per second increase within a second) and scale-in are rare. Such abrupt scale in and outs can be addressed by calculated overprovisioning, without any performance impact. Short-lived transactions and spikes in the pattern are better addressed by AWS Lambda, where the cost is governed by the number of requests and the GB-sec parameters and the concurrency is lower than 1000 across all functions in a region
AWS Lambda provides much more cost-effective deployment for applications with high and sudden spikes during the daytime, and very limited requests during the lean period, where the peak transaction concurrency is moderate to low. Application startup and execution must be extremely fast to leverage the cost benefits without any performance impact in any containerized application deployment.
Applications that require integration of multiple external APIs will be faster if the connections are cached and reused across multiple transactions. In Lambda, the caching may not have much impact, as the instances will get terminated after a request. Also, warm instances add to the cost. Each connection creation to external applications increases response time. Hence, ECS or EKS-based deployments will have better response time over AWS Lambda for many requests for such scenarios.
Tech-stack affinity often decides the target technology. For example, if a customer prefers .Net, ECS is a better option, as Lambda will have a poor cold start. ECS with Fargate becomes the default choice if a containerized deployment and operational ease of serverless stack is preferred. Java may be the obvious choice if there is a requirement for complex computations and fast processing with parallel processing. Similarly, if the application is already in Java (say monolith architecture), it is better to use Java as a technology stack instead of migrating to Python or NodeJS. This helps to reuse some of the business logic codes with minimal change.
When deploying a Java microservice in AWS Lambda, the cold start becomes a key consideration, as frameworks like Spring Boot require around 10 seconds to start a container. Similarly, this impacts the fast scale-out requirements.
As mentioned in the section above, this limitation for using Java in Serverless application models has been largely overcome by lightweight Java frameworks like Micronaut and Quarkus. When these are combined with GraalVM to generate a native image, the performance and the start-up time become much faster. The GraalVM community edition is free for commercial use. Its Ahead-of-time (AOT) compiler generates optimized machine code specific to a target platform. This helps in achieving a fast start-up time and low memory footprint.
Both Micronaut and Quarkus have well-developed library support for AWS service integrations and reactive invocation of RDS, Kafka, and Redis clients. By default, these two frameworks do not support reflection to handle object serialization and deserialization. Micronaut has @Introspected, whereas Quarkus have @RegisterForReflection to address this.
To compare the performances with the common Java frameworks with NodeJS, we developed a simple CRUD application with RDS for PostgreSQL, keeping the database credentials encrypted in the SSM parameter store using these stacks. The applications were deployed in AWS Lambda in a private subnet, using VPC endpoints to connect to System Managers Agent (SSM). The observation was as below:
Table 1: Performance metrics comparison tech stacks
Both Quarkus and Micronaut can create native images without installing Graal VM in the local machine. The corresponding build commands for images to be deployed in AWS Lambda are as below:
Micronaut:
./mvnw package -Dpackaging=docker-native -Dmicronaut.runtime=lambda -Pgraalvm
Quarkus:
./mvnw package -Pnative -Dnative-image.docker-build=true
The above requires the docker runtime and Java 11+ to be available in the build machine. Both frameworks have different mechanisms to enable the runtime image to understand the Lambda handler, such that the handler name is not to be explicitly configured in Lambda. Micronaut has the following in its pom.xml:
lambda
com.ltimindtree.FunctionLambdaRuntime
Quarkus requires annotating its RequestHandler with a name, as below:
@Named("myLambda") // myLambda is the name for this example
This RequestHandler is configured in the application.properties using the following:
quarkus.lambda.handler = myLambda
Both frameworks create a zip file to be uploaded to AWS Lambda as a code source.
Details of the configurations are in the links in the References section of this blog.
Some technology owners may feel better seeing the application code in AWS Management Console, as that may help to analyze during troubleshooting activities. In that perspective, NodeJs or Python has an edge. Still, ideally, the code should be committed to the source control tool like git before creating and deploying a build.
Also, the Java-based images (jar/zip files) are larger than that generated from NodeJs or Python. Hence, data transfer during the deployment may take a little longer time.
The cold start in Java in the context of serverless applications model is no longer there with GraalVM and lightweight frameworks like Quarkus and Micronaut. If the existing source code is in Java, be it a monolith application, using Java as the target platform is suggested, as the conversion will be easier and faster. These new frameworks mainly require the addition of the wrapper and dependencies to use Netty as the default embedded HTTP server. Netty is a high-performance, non-blocking I/O-based application framework, that helps to achieve scalability. In addition to this, some framework-related annotations are recommended for Cloud-native service integrations and integration with regular RDBMS, Apache Kafka, Redis, etc.
Since the frameworks, when deployed as GraalVM image, have excellent processing speed, we can even think of converting even the NodeJs or Python-based code to Java, in case high performance and scalability are vital criteria.
https://guides.micronaut.io/latest/mn-serverless-function-aws-lambda-graalvm-maven-java.html
https://quarkus.io/guides/
https://github.com/aws-samples/aws-quarkus-demo
https://github.com/quarkusio/quarkus/blob/main/docs/src/main/asciidoc/amazon-lambda.adoc
https://quarkus.io/guides/building-native-image#container-runtime
Managing Principal - Architecture (Digital Engineering)
Chinmoy has end-to-end expertise in Real-Time Payment (RTP) design, implementation, and continuous improvement with 10K+ Transactions Per Second (TPS). His experience includes implementation of data security, core-banking integration, payment settlement, reconciliation, fraud and dispute processing, AI integration within RTP. He worked as the chief architect of a Centralized Enterprise Fraud and Risk Management solution for Unified Payment Interface (UPI), IMPS, RuPay card, all Indian ATM transactions, Aadhar-Enabled Payment System (AEPS), and National Electronic Toll Collection (NETC). His key technology interest areas include developing cloud-native mission-critical applications with high throughput, and low latency using lightweight open-source frameworks like Micronaut, and Quarkus on Java running in GraalVM, leveraging software like Redis and Kafka.
Data Cloud - An essential for organizations of today Modern-day enterprises, based on the…
Observability is a foundational capability needed for making data-driven decisions around Artificial…