Dynamic Routing in Serverless Microservice with Vert.x Event Bus
This is a re-publication of the following blog post
The Serverless Framework has become the De Facto toolkit for building and deploying Serverless functions or applications. Its community has done a great job advancing the tools around Serverless architecture.
However, in the Serverless community there is debate among developers on whether a single AWS Lambda function should only be responsible for a single API endpoint. My answer, based on my real-world production experience, is NO.
Imagine if you are building a set of APIs with 10 endpoints and you need to deploy the APIs to DEV, STAGE and PROD environments. Now you are looking at 30 different functions to version, deploy and manage - not to mention the Copy & Paste code and configuration that will result from this type of set-up. NO THANKS!!!
I believe a more pragmatic approach is 1 Lambda Function == 1 Microservice.
For example, if you were building a User Microservice with basic CRUD functionality, you should implement
DELETE in a single Lambda function. In the code, you should resolve the desired action by inspecting the request or the context.
Vert.x to the rescue
There are many benefits to using Vert.x in any application. With Vert.x, you get a rock-solid and lightweight toolkit for building reactive, highly performant, event-driven and non-blocking applications. The toolkit even provides asynchronous APIs for accessing traditional blocking drivers such as JDBC.
However, for this example, we will mainly focus on the Event Bus. The event bus allows different parts of your application to communicate with each other via event messages. It supports publish/subscribe, point to point, and request-response messaging.
For the User Microservice example above, we could treat the combination of the
HTTP METHOD and
RESOURCE PATH as a unique event channel, and register the subscribers/handlers to respond appropriately.
Let’s dive right in.
Serverless stack definition:
14-19 initializes the Vert.x instance. AWS Lambda will hold on to this instance for the life of the container/JVM. It is reused in subsequent requests.
17 registers the User Service handlers
22 defines the main handler method that is called when the Lambda function is invoked.
27 sends the Lambda function input to the (dynamic) address where handlers are waiting to respond.
44-66 defines the specific handlers and binds them to the appropriate channels (http method + resource path)
As you can see, Vert.x’s Event Bus makes it very easy to dynamically support multiple routes in a single Serverless function. This reduces the number of functions you have to manage, deploy and maintain in AWS. In addition, you gain access to asynchronous, non-blocking APIs that come standard with Vert.x.
Serverless + Vert.x = BLISS
There are multiple tech stacks to build a real-time web app. What are the best choices to build Angular client apps, connected to a JVM-based backend?
The rise of Scala as one of the most important languages on the JVM caught many (me included) by surprise. This hybrid of functional and imperative paradigms struck a chord with many developers.