I’ve been running the Derbyshire Dot Net user group for a number of years now and thought it was high time that I gave a talk myself. So on the 27th April I gave a talk on Serverless Architecture with Azure Functions. I had intended to post the slides from the talk on this site but a number of the slides wouldn’t have made much sense without some background context. So, I decided to turn it into a blog post….
What is Serverless Architecture?
Serverless Architecure is a kind of misleading term. It implies that there are no servers involved but this is clearly not the case. Your code is is still running on a server however as a developer the idea is that you should not have to think about servers. You should only be focusing on developing core business functionality.
There are currently two schools of thought around serverless architeture and these are BaaS (Background as a Service) and FaaS (Function as a Service).
Background as a Service (BaaS)
Background as a Service (BaaS) provides developers with a way to connect their applications to back-end cloud storage and processing while also providing common features such as authentication (e.g. Auth0), logging, push notifications, and other features that users expect from their applications. BaaS is essentially another way of describing connecting to an API for a vendor to provide your processing so you don’t have to.
Function as a Service (FaaS)
Function as a Service (Faas), which is the focus of this post, is defined as:
server side logic is run in stateless compute container that are event-triggered, and are ephemeral (may only last for one invocation) – @mikebroberts
How does Serverless Architecture differ from Platform as a Service?
The key differentiator between Funcation as a Service (FaaS) and Platform as a Service (PaaS) is scaling.
With most PaaS’s you still need to think about scale. For example, with Azure Websites you must start by selecting the app service tier you need. Shared and Basic tier allows you to have only 1 instance, where Standard scales to 3 instances, standard 10 and premium 50. There is some level of automatic scaling with Azure websites however if you’re scaling has reached the limit of you app service tier (i.e you are using 3 instances in standard tier) and you need to scale further then you will need some manual intervention to scale up to the next tier.
With a Function as a Service application this scaling is completely transparent. Even if you setup your PaaS application to auto-scale you won’t be doing this to the level of individual requests (unless you have a very specifically shaped traffic profile), and so a FaaS application is much more efficient when it comes to costs.
Benefits of Serverless Architecture?
Cost
The major benefit to adopting a Serverless Architecture is reduced cost. Serverless Architecture is essentially a cloud based offering so offers the same reduced operational cost savings as IaaS, PaaS and SaaS because you are taking advantage of economies of scale. Because the vendor is running multi-tenant services the cost of running the infrastructure is dramatically reduced and passed onto the client.
Background as a Service (BaaS) offerings help to reduce the overall development cost because you are consuming an existing service rather than creating it from scratch. The added benefit of this approach is that the provider is likely an expert in the area of functionality that you are consuming. If you were to attempt to re-create the functionality yourself you would most likely end up with an inferior product.
However, the biggest win for Serverless is the ability to elastically auto-scale Functions as a Service (FaaS). The major vendors such as Azure Functions and AWS Lambda charge based on actual usage. If you had a service that had to be ready to accept infrequent requests then you would need a PaaS Service continually running ready to accept the request. This means you would have to keep the resource switched cosntantly incurring a cost.
With FaaS the compute resource is only built up when the request/trigger is received, the function is performed then the compute resource is torn down again. During my experimentation with Azure functions I am yet to incur any cost as you get 400,000 GB-s resource usage and 1 million requests free every month.
Disadvantages of Serverless Architecture?
Vendor Lock-in
It’s very likely that whatever Serverless features you’re using from a vendor that they’ll be differently implemented by another vendor. For example Azure Functions using a Run method in the run.csx file as the entry point whereas when you create a Lambda function, you specify a handler that AWS Lambda can invoke when the service executes the function on your behalf.
If you want to switch vendors you’ll almost certainly need to update your operational tools. In the case of deployment if you moved from Amazon to Azure you woud have to move from AWS CodeDeploy to a model that supported deployment to Azure such as WebDeploy. , monitoring, etc.)
You may need to change your code (e.g. to satisfy a different FaaS interface), and you may even need to change your design or architecture if there are differences to how competing vendor implementations behave.
Execution Time
FaaS functions are time limited, as of writing this post both Amazon AWS and Azure Functions have a constraint of 5 minutes of processing before the execution is aborted. Although, I believe that this limit is configurable in AWS Lambda.
Whenever possible, try to refactor large functions into smaller function sets that work together and return fast responses.
For example, a webhook or HTTP trigger function might require an acknowledgment response within a certain time limit. You can pass the HTTP trigger payload into a queue to be processed by a queue trigger function. This approach allows you to defer the actual work and return an immediate response. It is common for webhooks to require an immediate response.
– taken directly from Azure Functions documentation
Start-up Time
Under the covers Function as a Service (FaaS) implementations create a container for your code to run in on the first request. This means that the first request to a function may take quite a long time, as it is loading the container and any dependencies your application requires.
After a function is executed, the serverless vendor (Lambda / Azure Functsoin) keeps the container ready whilst waiting for another request to the function. Therefore on subsequent requests re-use the existing container so the function executes more speedily.
This works in unison with the previous constraint of bounded execution time. If your function does not get used within the time boundaries then the resource is torn down and any further requests would once again require the container computer resource to be stood up again, meaning the response time is once again diminished.
Don’t use FaaS for time critical apps unless you an guarantee a steady stream of traffic…or potentially ping every 5 minutes.
Microsoft’s offering: Azure Functions
Azure Functions are part of the Azure Web + Mobile suite of App Services that enable the creation of small pieces of meaningful, reusable methods, easily shared across services. These serverless, event-driven methods are often referred to as “nanoservices” due to their small size. Although an Azure Function can contain quite a bit of code, they are typically designed to serve a single purpose, and respond to events.
Supported Languages
Azure Functions can be created in most common development and scripting languages including Javascript, C#, Python, Bash, Batch and Powershell. They an be “triggered” by events in other Azure App Services, such as Web, Mobile, Logic, and API apps. Azure Functions can also be exposed via HTTP URL schemes for easy integration into legacy systems.
Common Scenarios for Azure Functions
Azure Functions are “event-driven” meaning they run based on associated and configure events, or “triggers”. For example a function could be triggered by a schedule such as running a process once every 24-hours or by an event in a document management system,
Azure Functions can also respond to Azure-specific events, such as an image added to a Storage Blob or a notification arriving in a Message Queue.
Azure Functions: Templates
Azure Functions can be created from scratch but the Azure Portal exposes a large number of templates to help get developers started. These templates are designed with specific triggers in mind such as a Blob Storage event (triggered when a file is uploaded to blob storage) or a GitHub webhook event and many more.
Templates can easily form the basis for robust function creation, and are really designed just to get a developer started.
Azure Functions : Timer Apps
Timer Functions are Azure Functions that are triggered by a specific time event.
Timer Functions are perfect for clean up and maintenance processes and can easily be combined with other functions for more robust scenarios.
Timer Functions us CRON expressions to configure schedules.
Azure Functions : Data Processing Apps
Data Processing Azure Functions are triggered by some activity in a data store, such as a table, queue, or container.
Data Processing Functions also typically have both “in” and “out” parameters, meaning they can accept an object as a parameter, and then process information and then return another object from within the function.
In and Out parameters controlled by Bindings which can be defined in the Azure Functions Portal or via the project.json file.
The In and Out parameters are not the same as a “return” value, as most Azure Functions either return void, or an HTTP response such as “created”, “accepted”, or “OK”.
Azure Functions : HTTP and Webhooks
Webhook and API Functions are designed to easily integrate with 3rd party systems, like GitHub, Office 365, and especially Microsoft PowerApps.
Since Webhook and API Functions are often exposed to external or legacy systems, they typically need CORS settings managed in order to “allow” external resources to “see” and execute the function.
Most Azure Logic Apps leverage Webhook and API Functions directly.
Anatomy of an Azure Function
An Azure Function is really a group of a few files that work in harmony.
All actual function logic resides in a “Run.csx” file written in a language of choice.
A “Project” file is similar to a project file in other technologies such as .NET Core or and contains “secondary” assembly references such as NuGet packages (or dlls).
Finally a “Function” file contains information about triggers and parameters, such as locations of Storage Queue connection strings and whether the parameter is design as an “in”, “out” or “bi-directional”.
Optionally, additional configuration is also found in the Function App Settings such as an API Key or database connection string.
Azure Function Bindings
Without bindings, an Azure Function would just be a “disconnected” algorithm without any way to serve a purpose.
Bindings server to connect functions and output to other services. Some of the most common binding types and features are listed in the table, however variations and adaptations can and do exist.
Testing Functions
Many Azure Functions are exposed via an actual URL that can be called directly from a web client or browser. When an Azure Function is not exposed via a URL its common practice to call the function from another function, such as a Timer-based Function for testing purposes only. Since Azure Functions can be nested, testing scenarios can be quite varied. For managing and testing Azure Functions that integrate with Storage Containers, Microsoft provides the Microsoft Azure Storage Explorer, as well as the Visual Studio Cloud Explorer. The Logs console in the Azure Function Designer is also a great way to view and trace function processing.
Closing thoughts
I finished the talk with a few demos (these are included in the actual slides and I may make them the subject of a further post). Some of the questions that were asked echoed my own thoughts on particularly on aspects of tooling. One of the key concerns raised was how do we get it into source control and into a continuous delivery pipeline. There are some tools available to develop locally but this requires an CLI utility that can be installed via npm at https://www.npmjs.com/package/azure-cli.
Leave a Reply