Skip to main content

Serverless Azure Functions

Introduction
Azure function capabilities are fast evolving.  They have come a long way from their inception just a few years ago.   Originally conceived to be small functions with short execution.  There were no modern architecture capabilities like dependency injection. The functions were also originally limited in the number of parallel instances that were allowed.    
From these somewhat humble beginnings Azure functions have quickly matured as a platform.  Today it is possible to run long running methods using durable functions.  Additionally, we now have support for dependency injection using an extension library.
Azure Functions are event driven, that is they do not run continuously, but are called in response to an event such as a http request, timer, or an update to a blob storage account.   The function is triggered executes and is then shut down. 
The billing for Azure Functions is based on consumption, you pay for the resources used.  If for example your function is not needed and never called, then there is no cost associated with having it deployed in the azure cloud.  This is an extreme example but illustrates the premise consumption based billing.
There are a wide range of Azure resources that are made available to Azure functions, these include storage with CosmosDB and Azure Blobs, security from Azure AD, and event support through event hubs.   
Recent improvements in capabilities include dependency injection.  I demo this in the code in this post.   These improvements coupled with the wide range of resources available to azure functions make them an excellent platform for developing modern cloud applications
For this post we will develop a simplified microservice that manages access to our customers identity.  The code can be found here along with a simplified script to create the relevant tables in an azure sql datastore.

You can find the code for this post here

Microservices
Azure Functions are an excellent platform for developing microservices.   Many times, microservices are associated with a docker containers.  The microservices design pattern does not require docker containers,  rather containers are simply one means of delivering microservices. A microservice is a small service component that can be deployed independently and that communicates using a well defined interface.  
The diagram below does a good job contrasting the development approach for microservices vs traditional development.  Azure Functions basic architecture assists in following the microservices architectural approach.


Microservices approach involves breaking the application down into logical units that can be deployed and scaled independently.  

Now that we have covered our intro lets get to the demo code.
The azure function that I created for this post is a simple customer account management service.  It provides a single endpoint for retrieval and updating a customer account.

Database Layer
        Our new service makes use of entity framework core to provide database access with our Azure Sql database.  The experience with working with EF .NET core is significantly different than the .net framework.  There is no design surface with EF core generating the database context is entirely command line driven.    The command lines don’t change when working with Azure SQL just be sure to grant your machine access to the database in the firewall settings on the azure portal.   If you are new to EF core a good EF core tutorial can be found here. 
Once we have our context we wrap the database access with a repository pattern the governs access to the database. 
You can find a copy of the database script with the code.  The Db has a customer table and a  customer lookup table.  The look up table is intended to be used with a provider such as Facebook that would pass back the customer id after the customer logs in.

Dependency Injection
     Dependency Injection requires the use of an extension library and some changes to the default azure function template.   To enable dependency injection the following must be done to the project:
1. Add a reference from NuGet to Microsoft.Azure.Functions.Extensions.
2. Add a new class to the project that inherits from FunctionsStartup. This class handles the heavy lifting of setting up dependency injection.  Note that you need to set the assembly reference at the top to the class you create. 

3. Remove static keyword from the azure function.  This is required in order to be able to instantiate the class and thereby provide the avenue for dependency injection. 
Once these changes are made you can add all your standard dependency injection code into the configure method of your FunctionStartUp class. 

Azure Function
        Our Azure Function by default supports both ‘Post’ and ‘Get’ methods, that will be sufficient for our demo. From an architecture, and design prospective we do not want to have the function contain any business logic. The Azure Function should only be used as the infrastructure to support the request.
In our demo our actual business logic is contained in the account service class. The service handles the logic of calling our repository and converting our database model to one that will be consumed by the client. From an architecture standpoint our database model should never be consumed directly by the client. Model factories are injected into the service as shown below to provide that abstraction layer between our database layer and the consuming client.





Testing and Deployment
It should be noted that Microsoft gives many options for development of Azure functions including a design surface in Azure itself.  This section assumes that the development is using VS 2019.   
Using Azure Functions Core Tools we can test our function locally.  This capability greatly simplifies the development process.   Once testing is completed locally we are ready to deploy our function to the cloud. 
As you expect from Microsoft deploying to the Azure Cloud is straight forward.  The first diagram after you select publish menu item you get a dialog a part of which is displayed below.  Most of the data needed on this dialog is defaulted.  



       It should be noted that this first dialog is actually just to setup the environment that you will be hosting not to actually deploy the service.   The next dialog shown below will be displayed once the environment for the new service is provisioned. 





     Once the deployment is completed we can navigate to the azure portal and test our new azure function.   

That’s it, azure functions are great platform for developing modern cloud centric applications.  


You can find the code for this post here





Comments