Saturday, January 26, 2019

Serverless Computing: Introduction and Hello World on Azure and AWS

A term that is all the rage now in cloud computing is "Serverless Computing". In this post we'll explain what serverless computing is, why it is important, and how to get started with it—on both Microsoft Azure and Amazon Web Services. We'll finish up with a Hello World function in both Azure Functions and AWS Lambda.


Leave the Driving to Us

If you're a developer, a term like "Serverless Computing" is immediately suspicious, since you know there must be servers somewhere—and indeed there are: it's simply that they are not visible to you. The cloud computing platform takes care of allocating servers, deploying your code to them, and managing scale. What does that leave for you to worry about? Just one thing, your code. As Greyhound used to say, "Leave the Driving to Us."

Functions as a Service (FaaS)

Serverless computing is often described as "Functions as a Service". If you've been keeping up with cloud computing, you've no doubt encounterd the _aaS (something as a Service) labels. Focusing on the primary categories of cloud computing, let's see how things have been progressing.

In its earliest years, cloud computing provided Infrastructure as a Service (IaaS), which meant you had a place in the cloud where you could set up virtual machines and related infrastructure like storage and load balancers. As an IT professional, you could get any kind of resource you needed minutes after requesting it and get right to work. As a service, you only paid for what you used/allocated and could stop anytime without penalty. This do-it-yourself instant computing was a hit, and it wasn't long before great minds started thinking about how to make it even better.

When Platform-as-a-Service (PaaS) services arrived, the cloud platform took care of underlying details like allocating and managing servers for you, including keeping servers patched and scaling them: you could now just focus on your application. A a PaaS developer, you could publish to the cloud right from your development environment and the rest would be handled for you. Similarly, on the data side of things, DBaaS (database as a service) provided the same ease of use for databases. It was hard to see how things could get much better.

Enter Functions as a Service (FaaS) and now things get even simpler. What's the smallest unit of code you can write? A function. FaaS lets you deploy just the code of a single function to the cloud. Like PaaS, all the details of server allocation, deployment, and scale are handled automatically. Unlike PaaS, you don't even allocate servers; you've uploaded and configured a function, and that's the only artifact you see in the cloud. The cloud platform takes it from there: if your function is used with increasing demand, it will scale onto mulitple servers. If your function use decreases, fewer resources will be allocated to it. FaaS is also typically delivered with a pay-by-request model, meaning you only pay for usage of your function. You pay nothing when it's idle.

Uses for FaaS

If you're used to deploying an entire application to the cloud as a single unit, it may strike you that a single function is way too granular a thing to deploy to the cloud. But consider the following:
  • There's growing interest in Microservices Architecture, in which small services are independently deployed.
  • The Internet of Things (IoT) phenomenon is connecting devices left and right; these devices need cloud-hosted code to manage them.
  • APIs are big nowadays; and to have a good one, you need a highly scalable platform and an easy way to deploy updates.
  • Many cloud applications in Production have a requirement for minimal disruption, yet traditional methods of deploying an entire application are overkill when you only need to apply a patch or update to one small area. 
For each of the above scenarios, FaaS is a perfect fit. Naturally, you are going to have to think carefully about security. As a new FaaS developer, you should follow the AWS Lambda Best Practices guidance or Azure Functions Best Pratices guidance.

Whether you've been aware of it or not, serverless computing is probably already impacting your life. Here are some real-world case studies of AWS Lambda:
And here are some real-world case studies of Azure Functions:

Please note that using FaaS does not necessarily mean you have to re-think your entire architecture: you can introduce FaaS organically if you like. It is completely feasible to take a more traditional cloud app, add a FaaS function, and grow your use of FaaS functions over time.

How FaaS Works

Services and Pricing

On Microsoft Azure, the serverless computing service is called Azure Functions. On AWS, the serverless computing service is called AWS Lambda

You can view Azure Functions rates and AWS Lambda rates to compare pricing. At the time of this writing, both platforms are generously providing a million free requests/month before charges apply. Cost really isn't a barrier to experimenting with FaaS.

How Does a FaaS Function Communicate?

It's all well and good to say we're going to host a function in the cloud, but how exactly will that function be invoked? You're going to like the answer, because it's one of the most versatile examples of software re-use that ever existed: any way you want them to. Once you understand how many ways there are to plug in your FaaS function, your mind will be reeling with possibilities.

Do you want your function to act like a service, responding to HTTP traffic? Or to process tasks that have been queued? Or to fire whenever a database record change occurs? Or to respond to incoming email messages? Or to run regularly at scheduled intervals? Or to furnish the back-end logic for a smart assistant voice user interface? Or to connect to an IoT device? All of these connections are easily made for FaaS functions. 


Here's a (partial!) table of currently-supported event sources for AWS Lambda and Azure Functions. For the most up-to-date information and more detail about function inputs/outputs, see AWS Lambda Supported Event Sources and Azure Functions Triggers and Bindings Concepts. Both platforms are regularly introducing new ways of invoking functions.

TriggerAWSAzure
HTTPAPI GatewayAPI Management
DatabaseDynamoDBCosmosDB
Email MessagesSESSendGrid
File StorageS3 bucket eventsAzure Blob Storage
IoTAWS IoT ButtonIoT Hub
Push Notifications  SNSAzure Notification Hubs
Queue MessagesSQSAzure Queue Storage
TimersCloudWatch ScheduledEvents  Timer Trigger
VoiceAlexa Skill

As you configure the trigger for your function, your cloud platform will often provide features for data binding and security. Typically, you'll secure your function by configuring the security model of the trigger (such as an API or storage queue).

Limitations of FaaS: Programming Languages

You knew there had to be some drawbacks, didn't you? In return for the easy, auto-scaling, pay-for-invocation model, there are some limitations.

In terms of execution time, your function must execute quickly. Both platforms originally required functions to execute in 5 minutes' time or less. At the time of this writing, your AWS Lambda function must execute within 15 minutes and an Azure Function within 10 minutes.

Cloud platforms are only prepared to support a limited collection of development languages (although this is sure to grow over time). Even so, you're likely to find something you know in the list of support languages. Do note that if you're a dedicated .NET developer, .NET Core is supported on both platforms but not the .NET Framework.

LanguageAzure FunctionsAWS Lambda
C# (.NET Core)
F# (.NET Core)
Go
Java
JavaScript (Node.js)
Powershell
Python
Ruby

FaaS isn't available in every region but is available in most of them. You can view the AWS Regions and Azure Regions lists to confirm whether a particular region supports FaaS. If you are going to depend on FaaS, you should take region availability into account before deciding where to deploy your solution.

Another "limitation" we should consider is fragmentation. This is not anything imposed by a cloud platform, merely a side-effect of the granularity of deploying something as small as a function. If you have dependencies between your functions, deploying a function-at-a-time is a notable departure from prior methods of publishing when you deployed your application as an atomic unit. If you're not disciplined, you could end up with a poor mix of software that doesn't work together. You'll need to think through how you keep track of versioning and dependencies. Maintaining a comprehensive set of unit tests for your functions is highly recommended.

Differences Between AWS Lambda and Azure Functions

So far, we've seen an awful lot of similarities between Azure and AWS offerings: both platforms offer low-cost, auto-scaling FaaS in a variety of languages that can be invoked in many different ways. Are there any differences worth noting? There's a good comparison article here.

First off, credit where credit is due: AWS was first to offer serverless computing. AWS Lambda debuted in 2014; Azure Functions came in 2016. AWS Lambda functions execute on Linux machines; Azure Functions can run on Windows or Linux (Linux support is in Preview).

Although both platforms offer an impressive selection of ways to trigger functions, they are not identical. If your needs are specific, one platform may provide a distinct advantage over the other. AWS, for example, can integrate AWS Lambda functions with Alexa Skills for voice user interfaces. (see an example here). Azure, on the other hand, can integrate Azure Functions with Excel spreadsheets via Microsoft Graph. 

AWS Lambda and Azure Functions originally targeted a function execution to take no more than 5 minutes. More recently, AWS Lambda now allows up to 15 minutes; and Azure Functions can be configured for up to 10 minutes' duration.

AWS Lambda also offers Lambda@Edge, which permits functions to be deployed to CloudFront (CDN) edge locations around the world.

Azure Functions are organized into Azure Function Apps, which can contain multiple functions. This allows you to organize related functions and, if you wish, update all functions with a single publish action. In AWS Lambda, you can tag functions to group them.

Azure Functions have CI features allowing them to be deployed from GitHub, BitBucket, Dropbox, , and Azure DevOps. AWS Lambda Functions have CI features that leverage AWS' CodePipeline, CodeCommit, and CodeBuild services (CodeCommit can use GitHub or S3 as sources).

Although both platforms strive to support developers and platforms of all kinds, if you're a Microsoft developer you'll find some nice things in Azure Functions such as the ability to debug functions remotely from within Visual Studio.

Hello World in Azure Functions

Let's create an Azure Function so we can see all this goodness in action on Microsoft Azure.

Step 1: Create a Function app in the Azure Portal.

Ensure you have a subscription, access the Azure Portal, and start creation of a function.

A. Sign up for a free Azure account if you don't already have one.
B. Sign in to the Azure Portal.
C. At top left, click Create a Resource.
D. Select Compute > Function App
E. Select the Author from scratch option.

Step 2: Provision your Function App

Create a Function.

A. Set a name for your function app. I used davidpallmann-hello. As you enter your name, you'll notice the full URL path will add .azurewebsites.net, and must be unique.
B. Select your operating system.I'll use Windows.
C. Choose a location near you. I'll use Central US.
D. Choose a Runtime Stack (platform/language). I'll use JavaScript.
E. You can default the remaining options.
F. Click Create.

Azure Funtion App Create Dialog

G. Wait for a portal notification to arrive that your function has been provisioned.

Provisoning Complete Portal Notification

H. Finally, locate your function in the portal. It should now be listed under the Azure Functions area.

Newly-Provisioned Function in Azure Portal

3. Write Your Function App

Write the code of your function.

A. Viewing your function in the portal, click the + button next to Functions in the outline at left. You'll now be given a choice as to where you want to author your code. Choices include using Microsoft's Visual Studio Code editor, some other editor of your choice, or writing code in the portal. We'll choose the In-Portal option and click Continue,

Selecting Code Editor

B. Next, you're given a choice of how your function will be invoked. We want this simple function to respond to HTTP traffic and be testable in a browser, so we'll choose Webhook + API, and click Create.

C. You're now taken to your function's code editing area in the portal, where a starter function has been written for us in JavaScript. The code given to us checks whether there is a query string parameter called name. If there is, it says 'Hello ' + name. If not, it prompts us to pass name. Note this is written to work with both GET and POST requests: the name may be passed as a URL argument or in the body of the HTTP request.

Default JavaScript Function Code

D. If you've made any changes to the code, click Save to save your changes.

4. Test Your Function

Test your function by invoking it.

A. To give yourself more room, collapse the black Azure services outline at left.

B. On the right, click on Test to open the Test Panel.

C. Note you can control the request type (GET or POST). We'll leave it set to POST.

D. Note you can edit the Request body. The default sets the name to "Azure". I'll change it to my name, David.

E. Click Run. The function is invoked, and you see the results in the Output area at bottom right. You've just run your first Azure function!

Testing Function in Portal

F. Now we'd like to test outside of the portal, in a browser. In the portal, click the </> Get function URL link to view your function's HTTP URL and copy it to the clipboard. This will give you a link similar to the following:

https://davidpallmann-hello.azurewebsites.net/api/HttpTrigger1?code=BXQPobZ5euQJATM3d4psQz4lSZzz1ssJLjyeUXS92acshFlsaztaJg==

Perhaps this is longer than you expected; what's that code= parameter? It's simply a security mechanism: you don't necessarily want everyone in the world invoking your function.

G. Enter the URL you copied in Step F. It responds with:

Please pass a name on the query string or in the request body

H. Mess up the code value in the URL and try again. This time, an HTTP 401 results.

I. Now, go back to the original URL from Step G and add &name= to the end. This time, the function sees the name parameter and greets you:

Hello Stranger

Testing Function in Browser with Name Parameter

Congratulations, you've now created and tested your first Azure Function and seen how easy it is. From here, you can explore creating real functions that do useful things, different ways to trigger functions, different ways of authoring function code, and monitoring your function.

For the official Microsoft Azure tutorial, see Create your first function in the Azure portal for detailed steps. Their example uses .NET (C#) rather than JavaScript but is otherwise similar.

Hello World in AWS Lambda

Let's now also create Hello World in AWS Lambda.

Step 1: Create a Function app in the AWS Console.

Ensure you have a subscription, access the AWS Console, and start creation of a function.

A. Sign up for a free AWS account if you don't already have one.
B. Sign in to the AWS Console.
C. Navigate to the AWS Lambda service area of the console.
D. Click Create Function.

Step 2: Provision your Function App

Configure a Function.

A. Set a name for your function app, such as yourname-hello.. I used davidpallmann-hello.
B. Select a Runtime. I selected Node.js 8.10, which means I'll be coding in JavaScript.
C .For Role, choose Create a a new role from one or more templates.
D. For Role Name, enter any name you like. I entered hello-role.
E. You can default the remaining options.
F. Click Create Function.

AWS Lambda Create Function Dialog

Step 3: Write Your Function

Configure and code your function.

A. Your function now looks like this in the console:

AWS Lamda Function in Console after Creation 

B. In the Designer panel under Add Triggers, select API Gateway. We are adding this trigger so our function can be invoked via an HTTP request. An API Gateway item appears in the Designer panel.

C. Below the Designer panelj, under Configure triggers, leave the default selection for Create a new API in place.

D. Under Security,  select Open (note that we could choose to require an API Key, or could associate the API with an IAM Role if we wished).

E. Click the Add button. The API Gateway connection to your function is now configured, and the API name is shown (davidpallmann-hello-API in my case).

F. In the Designer panel, click on the name of your function (davidpallmann-hello in my case). A Function code panel should now be visible showing your code.

G. Click Save

4. Test Your Function

Test your function by invoking it.

A. To test your function in the console, click Test. A dialog appears for configuring a test event..

Configure Test Event Dialog

B. On the Configure Test dialog, enter a name for the event such as HelloTest1.

C. Click Create. Your test event is created.

D. Again click Test on the console. This time, test results are shown. Expand and inspect.


Test Results

E. We've now seen the function work within the console, but we also want to see it work from a browser. But there's another thing: the current code is too simple: it only outputs a message. We'd like our function to be able to retreieve a query parameter as incoming data, so we will make some changes to the code.

Click the function name in the console so the code panel is visible, and replace the existing code with the code below. This new code will change its message based on whether or not a parameter named name is present.

exports.handler = async (event) => {

    var message = "Hello. Tell me your name by adding a ?name= parameter to the URL";
    if (event.queryStringParameters && event.queryStringParameters.name)
    {
            message = "Hello, " + event.queryStringParameters.name;
    }
    
    const response = {
        statusCode: 200,
        body: JSON.stringify(message),
    };
    return response;
};

F. In the console, click the API Gateway area at top  to see the API Gateway panel. Note the API Endpoint and copy it to your clipboard. It will be a URL with a format similar to this:

https://6rgtclt94i.execute-api.us-east-1.amazonaws.com/default/davidpallmann-hello

Viewing API Endpoint

G. In another browser tab, paste the URL from Step E. You see the service respond.

"Hello. Tell me your name by adding a ?name= parameter to the URL"



Testing Function in Browser
H. Now, add a ?name= parameter to the end of the URL. This time, we get a different response, showing the function saw an input parameter.
"Hello, Handsome"

Testing in Browser with a URL Parameter

Congratulations, you've now created and tested your first AWS Lambda Function and seen how easy it is. From here, you can explore creating real functions that do useful things, different ways to trigger functions, different ways of authoring function code, and monitoring your functions with AWS CloudWatch.

In Conclusion

Serverless Computing is a real phenomenon worth looking into. There has never been an easier or more effective way to get maximum reuse from your code. Cloud platforms have spared no effort to let you connect functions to, well, anything. You only pay for functions when they are used, giving them a superior payment model to always-allocated application servers. If you're a developer who has been using PaaS cloud services because they let you focus on your application instead of infrastructure details, you should look at FaaS to take that idea even further.