Azure Functions for IoT enable developers to create scalable IoT applications that can be rapidly deployed without provisioning a fixed infrastructure capacity in advance.
IoT solutions especially benefit from the ability to scale infrastructure using Azure Functions.
Azure Functions is a part of the Azure serverless solution. Azure Serverless solution comprises of three elements:
Serverless Kubernetes
Serverless functions
Serverless application environments
Function App
Azure Functions are hosted in an execution context called a function app.
You define function apps to logically group and structure your functions and a compute resource in Azure.
There are a few decisions that need to be made to create the function app; you need to choose a service plan and select a compatible storage account.
Service plan
Function apps may use one of two types of service plans:
Consumption plan:
When using the Azure serverless application platform, choose the Consumption plan.
This plan provides automatic scaling* and bills you only when your functions are running.
The Consumption plan comes with a configurable timeout period for executing a function. By default, it’s five (5) minutes, but may be configured to have a timeout as long as 10 minutes.
Azure App Service plan:
The Azure App Service plan enables you to avoid timeout periods by having your function run continuously on a VM that you define.
When using an App Service plan, you are responsible for managing the app resources the function runs on, so this is technically not a serverless plan.
It may be a better choice if your functions are used continuously, or if your functions require more processing power or longer execution time than the Consumption plan can provide.
Storage account requirements:
When you create a function app, it must be linked to a storage account.
The function app uses this storage account for internal operations, such as logging function executions and managing execution triggers.
On the Consumption plan, this is also where the function code and configuration file are stored.
Triggers and Bindings in Azure Functions:
An Azure function has two parts:
Triggers:
A function has a specific single trigger.
The trigger invokes the function.
Triggers provide data needed by the function.
Templates for Azure function triggers:
HTTP Trigger: When you want the code to execute in response to a request sent through the HTTP protocol.
Timer Trigger: When you want the code to execute according to a schedule.
Blob Trigger: When you want the code to execute when a new blob is added to an Azure Storage account.
CosmosDB Trigger: When you want the code to execute in response to new or updated documents in a NoSQL database.
Event Grid Trigger: Starts a function when an event is received from Event Grid.
Queue Storage Trigger: Starts a function when a new item is received on a queue. The queue message is provided as input to the function.
Service Bus Trigger: Starts a function in response to messages from a Service Bus queue.
Microsoft Graph Events Trigger: Starts a function in response to an incoming webhook from the Microsoft Graph. Each instance of this trigger can react to one Microsoft Graph resource type.
Bindings:
A trigger is a type of input binding that has the ability to initiate execution of some code.
Bindings connect Azure resources to the Azure functions.
Data from bindings is provided to the function as parameters.
Bindings interact with various data sources, which means you don't have to write the code in your function to connect to data sources and manage connections. The platform takes care of that complexity for you as part of the binding code.
Each binding has a direction, you could have input and output bindings for a function. Your code reads data from input bindings, and writes data to output bindings.
You can mix and match different bindings to suit your needs.
Bindings are optional and a function might have zero or multiple input and/or output bindings.
Triggers and bindings help you to avoid hardcoding access to other services.
Using the serverless computing approach, you can focus on the core logic of your solutions. You avoid the need to manage the underlying infrastructure that runs your solution. In the serverless application model, the cloud service provider automatically provisions, scales, and manages the underlying infrastructure required to run the code.
The serverless model has two aspects: function as a service and backend as a service.
Developers write the application as functions. Typically, these functions are stateless and short-lived.
Azure functions enable you to chain your functions to create the complete solution. Hence, as a developer, you’re concerned only with writing functions that interact with each other to solve the business problem.
Cloud service provider manages these deployed functions from the perspective of resources like processors, storage, and bandwidth (backend as a service). The resources are provided on an ‘as-needed’ basis and scaled as required.
You (the developer) are charged for the function only when the function is actually running (function as service).
IoT applications suit many of these characteristics. In the case of IoT applications, you can create a larger application by amalgamating/chaining many functions and scaling them dynamically as needed.
Merits of using Azure Functions for IoT solutions:
Scalable applications where you’re charged only for the resources you use.
Your solution can scale up or down dynamically and instantly depending on the business requirements. Ddon’t have to manage the infrastructure and to allocate the resources in advance.
Faster time to market
Flexibility to use multiple programming languages
Internet of Things solutions are typically event driven that is, you need to define a specific trigger that causes the function to run.
If your IoT solution could potentially scale from a small number of devices to millions of devices – you should consider Azure Functions.
Similarly, if your solution could see spikes of events to millions of events, you should consider Azure functions.
Constraints of Azure Functions to consider:
Execution time:
By default, functions have a timeout of five (5) minutes. This timeout is configurable to a maximum of 10 minutes.
If your function requires more than 10 minutes to execute, you can host it on a VM.
Additionally, if your service is initiated through an HTTP request and you expect that value as an HTTP response, the timeout is further restricted to 2.5 minutes.
But, there’s also an option called Durable Functions that enables you to orchestrate the executions of multiple functions without any timeout.
Execution frequency:
If you expect your function to be executed continuously by multiple clients, it would be prudent/sensible to estimate the usage and calculate the cost of using functions accordingly. It might be cheaper to host your service on a VM.
While scaling, only one function app instance can be created every 10 seconds, for up to 200 total instances.
Keep in mind, each instance can service multiple concurrent executions, so there’s no set limit about how much traffic a single instance can handle.
Different types of triggers have different scaling requirements, so research your choice of trigger and investigate its limits.
Custom handlers are lightweight web servers that receive events from the Azure Functions host.
Any language that supports HTTP primitives can implement a custom handler.
This means that custom handlers can be used to create functions in languages that aren’t officially supported.
Best practice guidelines for Azure Functions
Avoid long running functions:
Large, long-running functions can cause unexpected timeout issues.
Write functions to be stateless:
Functions should be stateless and idempotent if possible.
Idempotence is the property of certain operations in mathematics and computer science whereby they can be applied multiple times without changing the result beyond the initial application. For example, the number 1 is idempotent with respect to the multiplication operation because 1 x 1 = 1.
Associate any required state information with your data.
It’s possible to achieve cross function communication using Durable Functions and Azure Logic Apps that manage state transitions and communication between multiple functions.
Write defensive functions:
Design your functions with the ability to continue from a previous fail point during the next execution.
Scalability best practices:
Share and manage connections
Avoid sharing storage accounts
Manage function memory usage
Durable Functions:
Durable Functions is an extension of Azure Functions that lets you write stateful functions in a serverless compute environment.
The extension lets you define stateful workflows by writing orchestrator functions and stateful entities by writing entity functions using the Azure Functions programming model. Behind the scenes, the extension manages state, checkpoints, and restarts for you, allowing you to focus on your business logic.
Durable Orchestration Functions
Durable Functions is an extension of Azure Functions. You can use an orchestrator function to orchestrate the execution of other Durable functions within a function app. Orchestrator functions have the following characteristics:
Orchestrator functions define function workflows using procedural code. No declarative schemas or designers are needed.
Orchestrator functions can call other durable functions synchronously and asynchronously. Output from called functions can be reliably saved to local variables.
Orchestrator functions are durable and reliable. Execution progress is automatically checkpointed when the function "awaits" or "yields". Local state is never lost when the process recycles or the VM reboots.
Orchestrator functions can be long-running. The total lifespan of an orchestration instance can be seconds, days, months, or never-ending.
Entity Functions
Entity functions define operations for reading and updating small pieces of state, known as durable entities.
Like orchestrator functions, entity functions are functions with a special trigger type, the entity trigger.
Unlike orchestrator functions, entity functions manage the state of an entity explicitly, rather than implicitly representing state via control flow.
Entities provide a means for scaling out applications by distributing the work across many entities, each with a modestly sized state.