Cloud Native / Development / Microservices / Sponsored

A Step-by-Step Guide For AWS Lambda Deployments with Ballerina

28 May 2019 10:42am, by

WSO2 sponsored this post.

Anjana Fernando
Anjana is a director at WSO2, where he has further developed his expertise in data analytics and enterprise integration by leading several product initiatives at WSO2. He has also helped numerous customers in implementing their integration strategies. His latest venture is his role in the Ballerina project, where he has been involved extensively in the design and implementation of the language and its runtime.

Ballerina is a programming language for developers seeking to create and integrate microservices applications in a single interface for cloud-native applications. In addition to ensuring security standards are met before applications can be deployed, the open source language supports APIs, event streams, distributed applications and other functions.

In this post, we show how Ballerina, developed by WSO2, can be used to deploy functions in an AWS Lambda serverless environment.

When should you use serverless?

Serverless computing has been lauded as the next evolution of our quest to decentralize our architectures. This works on the notion of on-demand computing, where we do not have compute resources running always waiting for possible processing to be done, thus having to pre-allocate resources for these. But is it good to rely too much on this specific architectural pattern?. After all, if the only thing you have is a hammer, you will see everything as a nail.

So, one of the most important questions would be, when to use serverless? Even though people started to see serverless to be used for everything, this is necessarily not true. Serverless is used in specific scenarios. If you have a service that is constantly hit with requests, this is possibly not a good candidate for serverless. The main idea of using serverless is, executing some logic that is used sporadically, so at times, we could have unloaded the resources required for the service, and only when we want, load it and execute the logic. This behavior is ideal when we have event-based systems, where the events are triggered and our logic that is associated with these events are executed asynchronously. The asynchronous nature is important here, where due to this, the serverless logic unloading/loading behavior is not a hindrance, because no one is directly waiting for this to be finished executing. This would be the case if we have synchronous processing, such as the request/response pattern in a service call. The delay incurred due to loading an unloaded serverless unit is called a cold start, which is an undesirable behavior for synchronous service calls but is totally acceptable for event-based systems.

An example of an event processing scenario is, if you have a serverless function to be executed due to a database trigger, where the execution of the database trigger and the function execution does not have any perceivable time guarantees, so it can, in a reasonable time execute the logic, even if it has a cold start. After our serverless function is loaded, if it is regularly getting requests, it will be kept active and will respond quickly, and after some idle time, this will get unloaded and its resources will be released.

Deploying Ballerina Functions in AWS Lambda

Now that we got some definitions and its use cases out of the way, let us see how we can quickly write some serverless functions with Ballerina and AWS Lambda. AWS Lambda is the leading serverless platform, which has rich support for authoring serverless functions in many programming languages, and many event sources to trigger them.

Ballerina is a cloud-native programming language, that has in-built support for network primitives and language integration to many deployment models, thus making writing distributed networked applications a natural experience. Ballerina concentrate on having the right constructs, in order to only write the code that is absolutely required for your job, such as your program logic. The same philosophy is also followed in AWS Lambda support as well, where writing an AWS Lambda function is as simple as writing a typical Ballerina function. There aren’t any special callbacks, special operations for error handling and so on, but rather, they are handled as you would do in a normal function call.

The following is a code for a simple AWS Lambda function in Ballerina:

The Ballerina AWS Lambda layer information can be found here.

Run the following commands to deploy each Ballerina AWS Lambda function:

Run the following command to re-deploy an updated Ballerina AWS Lambda function:

The Ballerina AWS Lambda layer information can be found here.

Run the following commands to deploy each Ballerina AWS Lambda function:

Run the following command to re-deploy an updated Ballerina AWS Lambda function:

For a Ballerina function to be exposed as an AWS Lambda function, it needs to have a function signature similar to the above sample. This consists of a function that takes in a context object and a JSON value, and returns either an error or a JSON value. This return type we call it a union type, which can represent multiple types of the runtime value. After creating the function, you need to annotation the function with “awslambda:Function” in order to signal the compiler to generate the AWS Lambda related artifacts, which is simply a zip file with the compiled binary embedded into it, in the format AWS Lambda runtime expects it.

When the code is built, the compiler prints out the steps you need to follow to deploy it to AWS Lambda. These are simply AWS CLI commands that need to be used for the deployment. The first command is actually used for creating the actual lambda function in AWS.

In the above command, you will have to provide your own AWS user role ARN. The user role created should at least have the “AWSLambdaBasicExecutionRole” permission.

The second step is where you have to associate something called the Ballerina runtime layer to the lambda function. This is the point where a specific Ballerina runtime is associated with the function. The layer ARN can be looked up by navigating here, as mentioned in the earlier build output. Here, you need to pick the ARN value for the respective Ballerina release version that is being used. Also, this value has a place-holder for an AWS region value, which should be filled by you for your respective region to be used. Let’s see a sample command of this, used with Ballerina v0.991.0 and the “us-west-1” region:

At his point, the function is properly initialized, and it can be associated as a trigger for any event source that supported in AWS, such as S3, SNS and DynamoDB.

Figure 01: Configuring Lambda Function as a Trigger.

Figure 01 shows the AWS Lambda console in configuring a lambda function as a trigger for DynamoDB.

For our demonstration, let’s directly invoke the function from the AWS CLI to test out the function.

So we see how the simple function is executed and returning the payload we have passed into it as the input. Since the function is initialized in AWS Lambda, we can also quickly re-deploy the function by simply re-building the Ballerina source with “ballerina build” and then running the following AWS CLI command:

Execution Context

The Ballerina AWS Lambda function’s first parameter, “awslambda:Context” object contains the functionality to query the Lambda runtime for additional meta information. Such as the remaining time for the function call and so on. The list of all operations supported can be viewed here.

Error Handling and Debugging

Error handling is done simply by returning an error value from the Ballerina function. Due to the union return type, the user can either return a valid JSON value, or else, an error value representing the error condition that has occurred.

Let’s see how to return an error from our Ballerina function.

Figure 02: demo.bal

Here is an updated version of demo.bal, which is randomly returning an error. We can redeploy the code by running the following commands:

Now, execute the function a few times:

The error logs and the statistics can be viewed from the AWS Lambda console, and also gives a view of the application logs with their CloudWatch functionality.

Figure 03: Function Invocation Statistics

 

Figure 04: CloudWatch Logs

Conclusion

In this article, we have taken a look at what serverless is, when to apply it in your architecture and how to create a serverless solution quickly and easily by using AWS Lambda and the Ballerina programming language. This is accomplished by giving the maximum control to the developer with the lowest overhead of coding required to get the work done, which we believe has been made possible with the programming fundamentals of Ballerina and its extensibility.

Feature image via Pixabay.

A newsletter digest of the week’s most important stories & analyses.

View / Add Comments

Please stay on topic and be respectful of others. Review our Terms of Use.