While COVID-19 continues to make face-to-face collaboration an impossibility, cloud-based applications and workloads provide a well-defined method for remote development and project deployment. This is a perfect opportunity for us to explore Azure (and other cloud) serverless offerings as the ultimate contact-less development option.
Serverless offerings, like Azure Functions and Azure Logic Apps, take this to the next level while allowing us, as developers, to focus only on our application functionality and not the backing infrastructure or uptime of servers.
These serverless solutions will be the focus of this blog. We will cover the following topics:
Azure Functions
Definition
Azure functions are just that – a function of code that performs an action. These actions are event-driven and ephemeral. Basically, functions should be fire-and-forget workloads that can handle:
- Microservices
- Lightweight APIs
- System Integration
- Bulk Workloads
Some perks? Azure functions allow you to choose your programming language, only pay for the actual usage time of the function on the consumption plan, and are completely serverless.
Azure functions are code snippets that are written in a language you choose (the supported languages are C#, Javascript, Java, Python, and Powershell). For this sample, I am using VS Code.
Additionally, I have installed the Azure Function Extension. The extension has a wysiwyg to help build out a new function, and it asks for basic setup information like location and function name. It also allows you to select the language and type of function you want to develop – we chose an HTTP trigger function. This function is activated whenever the corresponding HTTP endpoint is hit, hence the name HTTP trigger.
Below is an example of an Azure Function using an HTTP trigger:
namespace Company.Function { public static class HttpTriggerExample { [FunctionName("HttpTriggerExample")] public static async Task<IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) { log.LogInformation("C# HTTP trigger function processed a request."); string name = req.Query["name"]; string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); dynamic data = JsonConvert.DeserializeObject(requestBody); name = name ?? data?.name; string responseMessage = string.IsNullOrEmpty(name) ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response." : $"Hello, {name}. This HTTP triggered function executed successfully."; return new OkObjectResult(responseMessage); } } }
This simple sample just returns a message with the name that passed in on the query string or in the request body; nothing too fancy here. The key is to look at the simplicity of the code. This sample can be rewritten to perform any number of tasks from sending an email to sending a command/question to a data store.
**Note – there is an editor in the Azure Portal that will allow you to write and test your functions directly without the need for an IDE like VS Code. However, only C# functions are supported in the portal at this time.
For more information about what Azure Functions are and the basics of how they operate, take a look at Microsoft’s Azure Functions Overview.
Best Use Cases
Based on previous clients and how they have used functions successfully, here are some of the best uses for Azure functions.
Triggering Activities on Datastore Inserts
In typical on-premise databases, using triggers to perform activities like auditing or kicking off additional streams of functionality is often frowned upon. This is mainly due to the fact that in most data stores, triggers are blocking actions and can have negative effects on performance.
Azure functions, however, do not have this limitation. They have clean integrations with Azure-based data stores like Azure SQL, Blob Storage, and Cosmos DB for example, and they can do considerably more than merely kick off a stored procedure or fill up audit data.
Starting an ingest process when a new document lands in Blob Storage is an example of an effective use for functions. I’ll use an experience with a client as an example. In this particular client’s previous solution, they had relied on a scheduled batch process to handle new documents, and they often faced challenges determining which documents had been processed and which had not.
Since they were using a batch process, they often ran into batch process problems like failure, restarts, and incomplete processing. Moving from a batch process to an event-driven process with functions proved to be extremely beneficial. Azure functions allowed the workload to be much more granular, and problem documents could easily be isolated from normal ones without the time-consuming work of researching what went wrong in the batch.
Extending Functionality of Legacy Systems
As most of us have seen, adding in new functionality to legacy applications often has unintended consequences. So, instead of cracking open decades-old code bases and adding internally, adding the new functionality externally in an Azure function with the legacy app calling out to it allows the old code to remain closed and safe from potentially hazardous modifications.
Ever-changing and growing needs constantly forge businesses ahead, and the necessity of cleaning up technical debt is often pushed to the back burner or forgotten altogether. This results in applications that live much longer than is advisable because they are constantly being added to and tweaked as the business grows and changes.
In one particular case I worked on, the client had a mainframe application that handled most of their critical business functions, and they needed to add a new set of functionality in order to take advantage of an emerging revenue stream.
In the past, they would simply add code to an already aged code base and have to redeploy the entire module, hoping that nothing else was impacted. However, in the new project (as per our recommendation and with our help) they chose to build out the functionality in an Azure function, which allowed them to build and test the code in isolation. Building the new functionality in this manner has also given them a path towards modernization in place of their legacy application.
What Not To Use Azure Functions For
Azure functions can be addictive because it allows developers and businesses to be completely myopic and only focus on what they want to do in the moment. This can be problematic when building out applications of any size because you run the risk of entirely functionally decomposing your application. Without proper orchestration and limits on the amount and types of functions that are introduced into a system, you can end up creating a support and maintenance nightmare. Again, based on previous client experiences, here some examples of what not to use a function for.
ETL
With their built-in triggers and ease of development, it can be tempting to see functions as an ideal tool to accomplish ETL (Extract – Transform – Load) activities. After all, each of the steps can be their own function or set of functions. This seems like a great idea to help isolate these concerns and to narrow the focus to only what needs to happen in each individual step.
In reality, however, things are not as perfect as they seem. Take a client I worked with for example. They had previously used functions to transform data that had landed in Azure SQL, and they used another function to move it to its final table destination. The problems arose when large data workloads were put through these functions. Since functions are made to be transient/ephemeral, failures on these were extremely difficult to track down without additional monitoring and research.
In addition, as more ETL pipelines were needed, more and more functions were created in the same pattern. Soon, a few functions became a few hundred. Couple that with the difficulty in tracking down failures or errors, and the process was untenable. Ultimately, the decision was made to move to a more robust ETL framework with all the monitoring, retries, and auditing built-in – in this case Azure Data Factory.
APIs For A High Volume System
While lightweight APIs are a good use case for functions, high volume APIs can prove problematic. An experience I had with a client demonstrates this. Their application performed well enough, but like the ETLs in the previous example, a couple APIs soon turned into several hundred.
Also, since these functions were set up on a consumption plan, they began to be very expensive. Initially, the system was a low-use system, but as adoption increased, the HTTP volume through the system increased. This ultimately resulted in a large increase in the monthly spend to the point where it became a regular budgetary topic for the business. In addition to the administrative challenges with maintaining multiple functions as the API evolved, now the financial side of the application also became a challenge. Ultimately, the decision was made to collapse the function endpoints into an app service that would be billed on an app service place tier instead of a consumption basis. This solved both the complexity issue and the financial issue.
Azure Logic Apps
Definition
Azure Logic Apps are a cloud service that allows users to schedule, integrate, and orchestrate workloads through a low/no-code Azure Portal experience. Logic Apps can handle workflows, business process management, IFTTT, and disparate system integrations. Using visual tooling in the portal, you can create complex and robust workflows that otherwise would involve a hefty external infrastructure.
Using the Azure Portal and the tooling, users can easily integrate with systems like SharePoint, O365, and even with AI and Cognitive Services. An example of the designer is below:
One of the main benefits of Azure logic apps is that users do not need to write code to build out these complex and robust integrations/processes. This can greatly increase the number of users who are able to add value to systems while also reducing the workloads of developers who have less contextual knowledge of business processes.
On the other hand, logic apps can create problems as it can introduce the opportunity for poorly built flows to make their way into your system and can obfuscate functionality away from the developers of the system. This can pose a problem when it comes to troubleshooting issues that arise.
**Note – you can build these logic apps through Visual Studio, but you will still be using the Logic App Designer tool.
For more information about what Azure Logic Apps are and the basics of how they operate, take a look at Microsoft’s Azure Logic Apps Overview.
Best Uses for Logic Apps
Based on my previous experience with clients’ usage of Logic Apps, below are some of the best uses I’ve seen for them in production applications.
Orchestration of Functions
One of the main capabilities of Logic Apps is their ability to perform orchestration activities. By that, I mean controlling the flow of code execution, and potentially data, across systems.
The ability to wait on a function to succeed or fail before triggering another activity is what made Logic Apps so powerful in one instance I had while working with a client. In this instance, the client had some Azure Functions that were performing linked, sequential activities. In order to ensure the correct sequence of execution, they had to build out additional functions for each step to coordinate the proper stop/starts of each function on either side of the sequence. When things failed or went wrong, it was extremely difficult to determine which function failed – the function performing the action or the function coordinating the actions.
The client felt very confident in the functions performing the actions themselves; it was the validation and coordination functions that seemed to be the weak spot. The client chose a Logic App to replace this process. Using the designer toolset, it was very easy to create not only happy-path workflows through the functions but also easy to set up email alerts if the process failed at any point in the process.
Integration With Other Azure/Microsoft Services
Another of the main benefits of Logic Apps is the vast amount of connectors that are available to use, especially with Microsoft applications. This makes for a perfect solution when data is needed in or out of one of these applications quickly.
The example case I’ll use to demonstrate this is a project I worked on for a client with a need to extract large amounts of data out of SharePoint and into Blob Storage, so it could eventually be piped downstream for larger-scale analytics. Initially, they tried to build out a custom solution to extract the data and move it to blob storage. This took a fair amount of development effort, and once it was built and working, other concerns instantly began to come to light. Error tracking became an issue, scheduling of the process involved even more teams, and once the need for only extracting deltas appeared, the code was going to have to be modified to accommodate.
Instead, however, the client chose to move this activity to a Logic App. They followed a tutorial similar to this one, and they were able to get this new process up and running, which fully addressed their concerns in less than a day.
It is important to remember, however, that Logic Apps are best used for higher-level process flows and business process management, and code-heavy tasks may not be best suited for them.
Conclusion
Azure Serverless solutions like Logic Apps and Functions allow developers to focus on building out the functionality of their applications without having to focus on infrastructure support. In this blog, we discussed some of the best ways to use both of these serverless services. We also reviewed some ways that are not effective for using Functions and reviewed a sample of both.
Serverless computing has come a long way and is now providing direct business value and being put into production in enterprise clients. Hopefully, this blog whets your appetite for learning more about the capabilities of the services offered on Azure, specifically Azure Logic Apps and Azure Functions. If you have not done so already, I encourage you to sign up for a free Azure account and begin to experiment with these tools. As always, if you have any questions or need a guide on your cloud journey, we at Keyhole Software can help – so please reach out.
Before we close, one last word on our current reality. Most people probably know someone affected or currently dealing with the impacts of COVID-19. I know people who have had their livelihoods affected, I know people who have been laid off or furloughed, I know people who are essential workers going into offices and hospitals every day, and I know people who have COVID-19 or who have relatives who have passed away from this virus. It is important to keep perspective at this time. While software design problems can seem daunting – they pale in comparison to the reality outside of our front doors. If you know someone who is an essential worker – take time to thank them. If you know someone who is isolated because of stay at home orders – reach out to them. If you know someone who is currently infected with COVID-19 – stay in touch with them or their family and keep them in your thoughts. This too will pass, but until it does we all have everyday life to deal with and need to pay attention to it. Stay home, stay safe.
Thank You,
Dallas Monson